* refactor: transfer、tooltip (#4306)

* refactor(transfer): use composition api (#4135)

* refactor(transfer): use composition api

* fix: remove console

* refactor(tooltip): use composition api (#4059)

* refactor(tooltip): use composition api

* chore: useConfigInject

* fix: remove useless

* style: format code

* refactor: transfer

* refactor: tooltip

Co-authored-by: ajuner <106791576@qq.com>

* Refactor mentions (#4341)

* refactor(mentions): use compositionAPI (#4313)

* refactor: mentions

* refactor: mentions

Co-authored-by: ajuner <106791576@qq.com>

* Refactor progress (#4358)

* fix: timepicker error border not show #4331

* fix(UploadDragger): fix UploadDrager no export (#4334)

* refactor(switch): support customize checked value #4329 (#4332)

* refactor(switch): support customize checked value #4329

* test: add test case

* refactor: update props name

* refactor: update ts

* refactor: optimize

* style: uncheckedValue to unCheckedValue

* test: update snap

* feat: udpate switch ts

* docs: remove ie11

* fix: tree-select throw error when use slot title

* fix: TypeScript definition of Table interface for typescript 4.3.5 (#4353)

* fix type for typescript 4.3.5

* Update interface.ts

close #4296

* fix: dropdown submenu style error #4351
close #4351

* fix(notification): 完善notification类型 (#4346)

* refactor(progress): use composition API (#4355)

* refactor(progress): use composition API

* refactor(vc-progress): update

* refactor: progress

* refactor: progress

* fix: timepicker error border not show #4331

* fix(UploadDragger): fix UploadDrager no export (#4334)

* refactor(switch): support customize checked value #4329 (#4332)

* refactor(switch): support customize checked value #4329

* test: add test case

* refactor: update props name

* refactor: update ts

* refactor: optimize

* style: uncheckedValue to unCheckedValue

* test: update snap

* feat: udpate switch ts

* docs: remove ie11

* fix: tree-select throw error when use slot title

* fix: TypeScript definition of Table interface for typescript 4.3.5 (#4353)

* fix type for typescript 4.3.5

* Update interface.ts

close #4296

* fix: dropdown submenu style error #4351
close #4351

* fix(notification): 完善notification类型 (#4346)

* refactor(progress): use composition API (#4355)

* refactor(progress): use composition API

* refactor(vc-progress): update

* refactor: progress

* refactor: progress

Co-authored-by: Jarvis <35361626+fanhaoyuan@users.noreply.github.com>
Co-authored-by: John <John60676@qq.com>
Co-authored-by: 艾斯特洛 <axetroy.dev@gmail.com>
Co-authored-by: zanllp <qc@zanllp.cn>

* docs: add changelog

* refactor: tree

* refactor: tree

* style: lint

* refactor: tree

* 热factor: tree

* refactor: tree

* refactor: tree

* refactor: tree

* refactor: directory tree

* refactor: tree

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* style: lint format

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* refactor: tree-select

* fix: upload ts error

* fix: update tree title render & switchIcon

* test: update tree test

* feat: add VirtualScroll tree

* refactor: datePicker & calendar & trigger (#4522)

* style: update

* test: update calendar test

* test: update test

* test: update test

* refactor: slider

* feat: update slider css

* refactor: slider to ts

* refactor: slider to ts

* perf: update default itemHeight

* test: update

* fix: uddate ts type

* fix: update skeleton

* fix: update skeleton

* refactor: update vc-pagination

* refactor: pagination

* refactor: timeline

* refactor: steps

* refactor: collapse

* refactor: collapse

* refactor: popconfirm

* refactor: popover

* refactor: dropdown

* doc: merge doc

* chore: vite for dev (#4602)

* style: js to jsx

* doc: add site

* style: lint

* style: format ts type

* doc: update

* style: format code

* style: format site

* doc: update

* style: dmeo

* style: format scripts

* chore: remove sub-modules

* chore: update vite

* site: add site build

* test: update snap

* doc(select): add tip (#4606)

* refactor: table (#4641)

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* refactor: table

* fix: column not pass to cell

* doc: uppate table

* fix: update bodyCell headerCell

* doc: remove examples

* refactor: table

* fix: table title not work

* fix: table selection

* fix: table checkStrictly

* refactor: table

* fix: table template error

* feat: table support summary

* test: update snap

* perf: table

* docs(table): fix ajax demo (#4639)

* test: update table

* refactor: remove old table

* doc: update  table doc

* doc: update doc

* doc: update select

* doc: update summary

Co-authored-by: John <John60676@qq.com>

* doc: update doc

* fix: menu arrow not work

* test: update

* doc: add next site

* style: format

* doc: update

* doc: update site script

* fix: expand icon not fixed

* feat: use renderSlot

* test: update table snap

* feat: confirm support reactively

* feat: configProvider.config

* feat: message support configprovider.config

* feat: notification support configprovider.config

* doc: update doc

* fix: typescript compile error

* style: add import eslint

* doc: update demo

* chore: set transpileOnly true

* style: fix eslint error

* test: update snap

* doc: update

* test: mock date

* test: update snap

* chore: remove gulp-typescript (#4675)

* feat: V3 form (#4678)

* chore: update husky

* perf: update formItem

* perf: useInjectFormItemContext

* fix: table ts error

* doc: add Customized Form Controls demo

* feat: export useInjectFormItemContext

* doc: update form doc

* doc: update doc

* doc: update doc

* feat: autocomplete support option slot

* doc: update

* feat: add form item rest

* style: remove omit.js

* refactor: autocomplete

* doc: add changelog to site

* doc: update site anchor

* doc: update doc layout

* test: update table test

* doc: update

* chore: udpate gulp script

* chore: udpate gulp script

* doc: add changelog

* doc: update

* test: ignore some test wait vue-test-utils

* fix: form id error #4582
close #4582

* doc: add select Responsive demo

* doc: remove temp doc

Co-authored-by: ajuner <106791576@qq.com>
Co-authored-by: Jarvis <35361626+fanhaoyuan@users.noreply.github.com>
Co-authored-by: John <John60676@qq.com>
Co-authored-by: 艾斯特洛 <axetroy.dev@gmail.com>
Co-authored-by: zanllp <qc@zanllp.cn>
Co-authored-by: Amour1688 <lcz_1996@foxmail.com>
This commit is contained in:
tangjinzhou 2021-09-25 16:51:32 +08:00 committed by GitHub
parent 2e22b221c9
commit 3aeeeb2aed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2172 changed files with 140759 additions and 82892 deletions

View File

@ -1,77 +0,0 @@
{
"root": true,
"env": {
"browser": true,
"node": true,
"jasmine": true,
"jest": true,
"es6": true
},
"parserOptions": {
"parser": "babel-eslint"
},
"extends": ["plugin:vue/vue3-recommended", "prettier"],
"plugins": ["markdown", "jest"],
"overrides": [
{
"files": ["**/demo/*.md"],
"processor": "markdown/markdown",
"rules": {
"no-console": "off"
}
},
{
"files": ["*.ts", "*.tsx"],
"extends": [
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/prettier/@typescript-eslint"
],
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/ban-types": 0,
"@typescript-eslint/consistent-type-imports": 1,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{ "vars": "all", "args": "after-used", "ignoreRestSiblings": true }
],
"@typescript-eslint/ban-ts-comment": 0
}
}
],
"rules": {
"comma-dangle": [2, "always-multiline"],
"no-var": "error",
"no-console": [2, { "allow": ["warn", "error"] }],
"object-shorthand": 2,
"no-unused-vars": [2, { "ignoreRestSiblings": true, "argsIgnorePattern": "^h$" }],
"no-undef": 2,
"camelcase": "off",
"no-extra-boolean-cast": "off",
"semi": ["error", "always"],
"vue/require-explicit-emits": "off",
"vue/require-prop-types": "off",
"vue/require-default-prop": "off",
"vue/no-reserved-keys": "off",
"vue/comment-directive": "off",
"vue/prop-name-casing": "off",
"vue/one-component-per-file": "off",
"vue/custom-event-name-casing": "off",
"vue/max-attributes-per-line": [
2,
{
"singleline": 20,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}
]
},
"globals": {
"h": true
}
}

101
.eslintrc.js Normal file
View File

@ -0,0 +1,101 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
jasmine: true,
jest: true,
es6: true,
},
parser: '@typescript-eslint/parser',
parserOptions: {
parser: 'babel-eslint',
},
extends: [
'plugin:vue/vue3-recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'prettier',
],
plugins: ['markdown', 'jest', '@typescript-eslint', 'import'],
overrides: [
{
files: ['*.md'],
processor: 'markdown/markdown',
rules: {
'no-console': 'off',
},
},
{
files: ['*.ts', '*.tsx'],
extends: ['@vue/typescript/recommended', '@vue/prettier', '@vue/prettier/@typescript-eslint'],
parserOptions: {
project: './tsconfig.json',
},
rules: {
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/ban-types': 0,
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-non-null-assertion': 0,
'@typescript-eslint/no-unused-vars': [
'error',
{ vars: 'all', args: 'after-used', ignoreRestSiblings: true },
],
'@typescript-eslint/ban-ts-comment': 0,
},
},
{
files: ['*.vue'],
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
},
rules: {
'no-console': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{ vars: 'all', args: 'after-used', ignoreRestSiblings: true },
],
},
},
],
rules: {
'import/no-named-as-default': 'off',
'import/namespace': [2, { allowComputed: true }],
'import/no-named-as-default-member': 'off',
'import/no-unresolved': [2, { ignore: ['ant-design-vue'] }],
'comma-dangle': [2, 'always-multiline'],
'no-var': 'error',
'no-console': [2, { allow: ['warn', 'error'] }],
'object-shorthand': 2,
'no-unused-vars': [2, { ignoreRestSiblings: true, argsIgnorePattern: '^_' }],
'no-undef': 2,
camelcase: 'off',
'no-extra-boolean-cast': 'off',
semi: ['error', 'always'],
'vue/no-v-html': 'off',
'vue/require-explicit-emits': 'off',
'vue/require-prop-types': 'off',
'vue/require-default-prop': 'off',
'vue/no-reserved-keys': 'off',
'vue/comment-directive': 'off',
'vue/prop-name-casing': 'off',
'vue/one-component-per-file': 'off',
'vue/custom-event-name-casing': 'off',
'vue/max-attributes-per-line': [
2,
{
singleline: 20,
multiline: {
max: 1,
allowFirstLine: false,
},
},
],
},
globals: {
h: true,
},
};

5
.gitignore vendored
View File

@ -63,7 +63,6 @@ _site
yarn.lock
package-lock.json
/coverage
.husky
# 备份文件
/components/test/*
@ -73,3 +72,7 @@ site/dev.js
# IDE 语法提示临时文件
vetur/
report.html
site/src/router/demoRoutes.js

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "v2-doc"]
path = v2-doc
url = https://github.com/vueComponent/v2-doc

1
.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

4
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install pretty-quick --staged

View File

@ -8,9 +8,7 @@ const transformIgnorePatterns = [
'node_modules/(?!@ant-design/icons-vue|@ant-design/icons-svg|lodash-es)/',
];
const testPathIgnorePatterns = ['/node_modules/', 'node'];
if (process.env.WORKFLOW === 'true') {
testPathIgnorePatterns.push('demo\\.test*');
}
module.exports = {
testURL: 'http://localhost/',
setupFiles: ['./tests/setup.js'],

View File

@ -1,9 +1,11 @@
{
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf",
"printWidth": 100,
"proseWrap": "never",
"arrowParens": "avoid",
"htmlWhitespaceSensitivity": "ignore",
"overrides": [
{
"files": ".prettierrc",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ try {
outputDir: path.resolve(rootPath, './vetur'),
tagPrefix: 'a-',
});
// eslint-disable-next-line no-console
console.log('generator types success');
} catch (e) {
console.error('generator types error', e);

View File

@ -1,7 +1,6 @@
/* eslint-disable no-continue */
import { Artical, Articals } from './parser';
import type { Articals } from './parser';
import { formatType, removeVersion, toKebabCase } from './utils';
import { VueTag } from './type';
import type { VueTag } from './type';
function getComponentName(name: string, tagPrefix: string) {
if (name) {
@ -35,7 +34,7 @@ function parserProps(tag: VueTag, line: any) {
});
}
export function formatter(articals: Articals, componentName: string, tagPrefix: string = '') {
export function formatter(articals: Articals, componentName: string, tagPrefix = '') {
if (!articals.length) {
return;
}

View File

@ -1,10 +1,10 @@
import glob from 'fast-glob';
import { join, dirname, basename } from 'path';
import { join, dirname } from 'path';
import { mdParser } from './parser';
import { formatter } from './formatter';
import { genWebTypes } from './web-types';
import { readFileSync, outputFileSync } from 'fs-extra';
import { Options, VueTag } from './type';
import type { Options, VueTag } from './type';
import { normalizePath, getComponentName } from './utils';
import { genVeturTags, genVeturAttributes } from './vetur';

View File

@ -1,4 +1,4 @@
import { PathLike } from 'fs';
import type { PathLike } from 'fs';
export type VueSlot = {
name: string;

View File

@ -18,7 +18,7 @@ export function formatType(type: string) {
}
export function getComponentName(name: string) {
let title = name
const title = name
.split('-')
.map(it => it.substring(0, 1) + it.substring(1))
.join('');

View File

@ -1,4 +1,4 @@
import { VueTag, VeturTags, VeturAttributes } from './type';
import type { VueTag, VeturTags, VeturAttributes } from './type';
export function genVeturTags(tags: VueTag[]) {
const veturTags: VeturTags = {};

View File

@ -1,4 +1,4 @@
import { VueTag, Options } from './type';
import type { VueTag, Options } from './type';
// create web-types.json to provide autocomplete in JetBrains IDEs
export function genWebTypes(tags: VueTag[], options: Options) {

View File

@ -79,7 +79,6 @@ function getWebpackConfig(modules) {
},
module: {
noParse: [/moment.js/],
rules: [
{
test: /\.vue$/,
@ -124,6 +123,9 @@ function getWebpackConfig(modules) {
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},

View File

@ -17,23 +17,22 @@ const chalk = require('chalk');
const getNpmArgs = require('./utils/get-npm-args');
const getChangelog = require('./utils/getChangelog');
const path = require('path');
// const watch = require('gulp-watch')
const ts = require('gulp-typescript');
const gulp = require('gulp');
const fg = require('fast-glob');
const fs = require('fs');
const rimraf = require('rimraf');
const { createCompilerHost, createProgram } = require('typescript');
const stripCode = require('gulp-strip-code');
const compareVersions = require('compare-versions');
const getTSCommonConfig = require('./getTSCommonConfig');
// const getTSCommonConfig = require('./getTSCommonConfig');
const replaceLib = require('./replaceLib');
const packageJson = require(getProjectPath('package.json'));
const tsDefaultReporter = ts.reporter.defaultReporter();
const cwd = process.cwd();
const libDir = getProjectPath('lib');
const esDir = getProjectPath('es');
const tsConfig = getTSCommonConfig();
// const tsConfig = getTSCommonConfig();
function dist(done) {
rimraf.sync(path.join(cwd, 'dist'));
@ -72,29 +71,51 @@ function dist(done) {
});
}
const tsFiles = ['**/*.ts', '**/*.tsx', '!node_modules/**/*.*', 'typings/**/*.d.ts'];
async function compileTs(modules = false, cb) {
const options = {
allowJs: true,
declaration: true,
emitDeclarationOnly: true,
};
function compileTs(stream) {
return stream
.pipe(ts(tsConfig))
.js.pipe(
through2.obj(function (file, encoding, next) {
// console.log(file.path, file.base);
file.path = file.path.replace(/\.[jt]sx$/, '.js');
this.push(file);
next();
}),
)
.pipe(gulp.dest(process.cwd()));
const createdFiles = {};
const host = createCompilerHost(options);
host.writeFile = (fileName, contents) => {
createdFiles[path.isAbsolute(fileName) ? path.relative(cwd, fileName) : fileName] = contents;
};
const files = await fg(
[
'components/**/*.js',
'components/**/*.jsx',
'components/**/*.tsx',
'components/**/*.ts',
'!components/*/__tests__/*',
'!components/*/style/*',
'!components/styles.ts',
],
{ cwd },
);
const program = createProgram(files, options, host);
program.emit();
Object.keys(createdFiles).forEach(fileName => {
const contents = createdFiles[fileName];
const filePath = path.join(
cwd,
fileName.replace(/^components/, modules === false ? 'es' : 'lib'),
);
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(filePath, contents);
});
cb(0);
}
gulp.task('tsc', () =>
compileTs(
gulp.src(tsFiles, {
base: cwd,
}),
),
);
gulp.task('tsc', () => compileTs());
function babelify(js, modules) {
const babelConfig = getBabelCommonConfig(modules);
@ -169,7 +190,7 @@ function compile(modules) {
const assets = gulp
.src(['components/**/*.@(png|svg)'])
.pipe(gulp.dest(modules === false ? esDir : libDir));
let error = 0;
// let error = 0;
const source = [
'components/**/*.js',
'components/**/*.jsx',
@ -179,27 +200,8 @@ function compile(modules) {
'!components/*/__tests__/*',
];
const tsResult = gulp.src(source).pipe(
ts(tsConfig, {
error(e) {
tsDefaultReporter.error(e);
error = 1;
},
finish: tsDefaultReporter.finish,
}),
);
function check() {
if (error && !argv['ignore-error']) {
process.exit(1);
}
}
tsResult.on('finish', check);
tsResult.on('end', check);
const tsFilesStream = babelify(tsResult.js, modules);
const tsd = tsResult.dts.pipe(gulp.dest(modules === false ? esDir : libDir));
return merge2([less, tsFilesStream, tsd, assets]);
const jsFilesStream = babelify(gulp.src(source), modules);
return merge2([less, jsFilesStream, assets]);
}
function tag() {
@ -292,7 +294,6 @@ gulp.task(
function publish(tagString, done) {
let args = ['publish', '--with-antd-tools'];
args = args.concat(['--tag', 'next']);
if (tagString) {
args = args.concat(['--tag', tagString]);
}
@ -327,7 +328,10 @@ function pub(done) {
}
}
let startTime = new Date();
gulp.task('compile-with-es', done => {
startTime = new Date();
console.log('start compile at ', startTime);
console.log('[Parallel] Compile to es...');
compile(false).on('finish', done);
});
@ -337,11 +341,31 @@ gulp.task('compile-with-lib', done => {
compile().on('finish', done);
});
gulp.task('compile-with-es-ts-type', async done => {
console.log('[Parallel] Compile to es ts type...');
await compileTs(false, done);
});
gulp.task('compile-with-lib-ts-type', async done => {
console.log('[Parallel] Compile to lib ts type...');
await compileTs(true, done);
});
gulp.task(
'compile',
gulp.series(gulp.parallel('compile-with-es', 'compile-with-lib'), done => {
done();
}),
gulp.series(
gulp.parallel(
'compile-with-es',
'compile-with-lib',
'compile-with-es-ts-type',
'compile-with-lib-ts-type',
),
done => {
console.log('end compile at ', new Date());
console.log('compile time ', (new Date() - startTime) / 1000, 's');
done();
},
),
);
gulp.task(

View File

@ -1,48 +0,0 @@
import PropTypes from './vue-types';
import { defineComponent, nextTick, Teleport } from 'vue';
export default defineComponent({
name: 'Portal',
props: {
getContainer: PropTypes.func.isRequired,
children: PropTypes.any.isRequired,
didUpdate: PropTypes.func,
},
data() {
this._container = null;
return {};
},
mounted() {
this.createContainer();
},
updated() {
const { didUpdate } = this.$props;
if (didUpdate) {
nextTick(() => {
didUpdate(this.$props);
});
}
},
beforeUnmount() {
this.removeContainer();
},
methods: {
createContainer() {
this._container = this.$props.getContainer();
this.$forceUpdate();
},
removeContainer() {
if (this._container && this._container.parentNode) {
this._container.parentNode.removeChild(this._container);
}
},
},
render() {
if (this._container) {
return <Teleport to={this._container}>{this.$props.children}</Teleport>;
}
return null;
},
});

View File

@ -0,0 +1,38 @@
import PropTypes from './vue-types';
import {
defineComponent,
nextTick,
onBeforeUnmount,
onMounted,
onUpdated,
ref,
Teleport,
} from 'vue';
export default defineComponent({
name: 'Portal',
inheritAttrs: false,
props: {
getContainer: PropTypes.func.isRequired,
didUpdate: PropTypes.func,
},
setup(props, { slots }) {
const container = ref();
onMounted(() => {
container.value = props.getContainer();
});
onUpdated(() => {
nextTick(() => {
props.nextTick?.(props);
});
});
onBeforeUnmount(() => {
if (container.value && container.value.parentNode) {
container.value.parentNode.removeChild(container.value);
}
});
return () => {
return container.value ? <Teleport to={container.value}>{slots.default?.()}</Teleport> : null;
};
},
});

View File

@ -20,7 +20,6 @@ export default defineComponent({
wrapperClassName: PropTypes.string,
forceRender: PropTypes.looseBool,
getContainer: PropTypes.any,
children: PropTypes.func,
visible: PropTypes.looseBool,
},
data() {
@ -130,7 +129,7 @@ export default defineComponent({
},
render() {
const { children, forceRender, visible } = this.$props;
const { forceRender, visible } = this.$props;
let portal = null;
const childProps = {
getOpenCount: () => openCount,
@ -141,8 +140,8 @@ export default defineComponent({
portal = (
<Portal
getContainer={this.getDomContainer}
children={children(childProps)}
ref={this.savePortal}
v-slots={{ default: () => this.$slots.default?.(childProps) }}
></Portal>
);
}

View File

@ -0,0 +1,89 @@
// copy from https://github.dev/vueuse/vueuse
import type { Ref, WatchOptions, WatchStopHandle } from 'vue';
import { unref, watch } from 'vue';
type MaybeRef<T> = T | Ref<T>;
type Fn = () => void;
export type FunctionArgs<Args extends any[] = any[], Return = void> = (...args: Args) => Return;
export interface FunctionWrapperOptions<Args extends any[] = any[], This = any> {
fn: FunctionArgs<Args, This>;
args: Args;
thisArg: This;
}
export type EventFilter<Args extends any[] = any[], This = any> = (
invoke: Fn,
options: FunctionWrapperOptions<Args, This>,
) => void;
const bypassFilter: EventFilter = invoke => {
return invoke();
};
/**
* Create an EventFilter that debounce the events
*
* @param ms
*/
export function debounceFilter(ms: MaybeRef<number>) {
let timer: ReturnType<typeof setTimeout> | undefined;
const filter: EventFilter = invoke => {
const duration = unref(ms);
if (timer) clearTimeout(timer);
if (duration <= 0) return invoke();
timer = setTimeout(invoke, duration);
};
return filter;
}
export interface DebouncedWatchOptions<Immediate> extends WatchOptions<Immediate> {
debounce?: MaybeRef<number>;
}
interface ConfigurableEventFilter {
eventFilter?: EventFilter;
}
/**
* @internal
*/
function createFilterWrapper<T extends FunctionArgs>(filter: EventFilter, fn: T) {
function wrapper(this: any, ...args: any[]) {
filter(() => fn.apply(this, args), { fn, thisArg: this, args });
}
return wrapper as any as T;
}
export interface WatchWithFilterOptions<Immediate>
extends WatchOptions<Immediate>,
ConfigurableEventFilter {}
// implementation
export function watchWithFilter<Immediate extends Readonly<boolean> = false>(
source: any,
cb: any,
options: WatchWithFilterOptions<Immediate> = {},
): WatchStopHandle {
const { eventFilter = bypassFilter, ...watchOptions } = options;
return watch(source, createFilterWrapper(eventFilter, cb), watchOptions);
}
// implementation
export default function debouncedWatch<Immediate extends Readonly<boolean> = false>(
source: any,
cb: any,
options: DebouncedWatchOptions<Immediate> = {},
): WatchStopHandle {
const { debounce = 0, ...watchOptions } = options;
return watchWithFilter(source, cb, {
...watchOptions,
eventFilter: debounceFilter(debounce),
});
}

View File

@ -0,0 +1,10 @@
function firstNotUndefined<T>(arr: T[] = []): T {
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] !== undefined) {
return arr[i];
}
}
return undefined;
}
export default firstNotUndefined;

View File

@ -1,6 +1,12 @@
let cached;
/* eslint-disable no-param-reassign */
let cached: number;
export default function getScrollBarSize(fresh?: boolean) {
if (typeof document === 'undefined') {
return 0;
}
export default function getScrollBarSize(fresh) {
if (fresh || cached === undefined) {
const inner = document.createElement('div');
inner.style.width = '100%';
@ -10,8 +16,8 @@ export default function getScrollBarSize(fresh) {
const outerStyle = outer.style;
outerStyle.position = 'absolute';
outerStyle.top = 0;
outerStyle.left = 0;
outerStyle.top = '0';
outerStyle.left = '0';
outerStyle.pointerEvents = 'none';
outerStyle.visibility = 'hidden';
outerStyle.width = '200px';
@ -36,3 +42,21 @@ export default function getScrollBarSize(fresh) {
}
return cached;
}
function ensureSize(str: string) {
const match = str.match(/^(.*)px$/);
const value = Number(match?.[1]);
return Number.isNaN(value) ? getScrollBarSize() : value;
}
export function getTargetScrollBarSize(target: HTMLElement) {
if (typeof document === 'undefined' || !target || !(target instanceof Element)) {
return { width: 0, height: 0 };
}
const { width, height } = getComputedStyle(target, '::-webkit-scrollbar');
return {
width: ensureSize(width),
height: ensureSize(height),
};
}

View File

@ -10,6 +10,7 @@ export default (
): {
configProvider: UnwrapRef<ConfigProviderProps>;
prefixCls: ComputedRef<string>;
rootPrefixCls: ComputedRef<string>;
direction: ComputedRef<Direction>;
size: ComputedRef<SizeType>;
getTargetContainer: ComputedRef<() => HTMLElement>;
@ -18,32 +19,49 @@ export default (
form?: ComputedRef<{
requiredMark?: RequiredMark;
}>;
autoInsertSpaceInButton: ComputedRef<Boolean>;
autoInsertSpaceInButton: ComputedRef<boolean>;
renderEmpty?: ComputedRef<(componentName?: string) => VNodeChild | JSX.Element>;
virtual: ComputedRef<boolean>;
dropdownMatchSelectWidth: ComputedRef<boolean | number>;
getPopupContainer: ComputedRef<ConfigProviderProps['getPopupContainer']>;
} => {
const configProvider = inject<UnwrapRef<ConfigProviderProps>>(
'configProvider',
defaultConfigProvider,
);
const prefixCls = computed(() => configProvider.getPrefixCls(name, props.prefixCls));
const direction = computed(() => configProvider.direction);
const direction = computed(() => props.direction ?? configProvider.direction);
const rootPrefixCls = computed(() => configProvider.getPrefixCls());
const autoInsertSpaceInButton = computed(() => configProvider.autoInsertSpaceInButton);
const renderEmpty = computed(() => configProvider.renderEmpty);
const space = computed(() => configProvider.space);
const pageHeader = computed(() => configProvider.pageHeader);
const form = computed(() => configProvider.form);
const getTargetContainer = computed(
() => props.getTargetContainer || configProvider.getTargetContainer,
);
const getPopupContainer = computed(
() => props.getPopupContainer || configProvider.getPopupContainer,
);
const virtual = computed(() => props.virtual ?? configProvider.virtual);
const dropdownMatchSelectWidth = computed<boolean | number>(
() => props.dropdownMatchSelectWidth ?? configProvider.dropdownMatchSelectWidth,
);
const size = computed(() => props.size || configProvider.componentSize);
const getTargetContainer = computed(() => props.getTargetContainer);
return {
configProvider,
prefixCls,
direction,
size,
getTargetContainer,
getPopupContainer,
space,
pageHeader,
form,
autoInsertSpaceInButton,
renderEmpty,
virtual,
dropdownMatchSelectWidth,
rootPrefixCls,
};
};

View File

@ -1,9 +1,9 @@
import type { Ref } from 'vue';
import type { Ref, WatchSource } from 'vue';
import { ref, watch } from 'vue';
export default function useMemo<T>(
getValue: () => T,
condition: any[],
condition: (WatchSource<unknown> | object)[],
shouldUpdate?: (prev: any[], next: any[]) => boolean,
) {
const cacheRef: Ref<T> = ref(getValue() as any);

View File

@ -0,0 +1,47 @@
import type { Ref, UnwrapRef } from 'vue';
import { toRaw, watchEffect, unref, watch, ref } from 'vue';
export default function useMergedState<T, R = Ref<T>>(
defaultStateValue: T | (() => T),
option?: {
defaultValue?: T | (() => T);
value?: Ref<T> | Ref<UnwrapRef<T>>;
onChange?: (val: T, prevValue: T) => void;
postState?: (val: T) => T;
},
): [R, (val: T) => void] {
const { defaultValue, value = ref() } = option || {};
let initValue: T =
typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue;
if (value.value !== undefined) {
initValue = unref(value as any) as T;
}
if (defaultValue !== undefined) {
initValue = typeof defaultValue === 'function' ? (defaultValue as any)() : defaultValue;
}
const innerValue = ref(initValue) as Ref<T>;
const mergedValue = ref(initValue) as Ref<T>;
watchEffect(() => {
let val = value.value !== undefined ? value.value : innerValue.value;
if (option.postState) {
val = option.postState(val as T);
}
mergedValue.value = val as T;
});
function triggerChange(newValue: T) {
const preVal = mergedValue.value;
innerValue.value = newValue;
if (toRaw(mergedValue.value) !== newValue && option.onChange) {
option.onChange(newValue, preVal);
}
}
// Effect of reset value to `undefined`
watch(value, () => {
innerValue.value = value.value as T;
});
return [mergedValue as unknown as R, triggerChange];
}

View File

@ -2,9 +2,9 @@ import type { Ref } from 'vue';
import { onBeforeUpdate, ref } from 'vue';
export type UseRef = [(el: any, key: string | number) => void, Ref<any>];
export type Refs = Record<string | number, any>;
export const useRef = (): UseRef => {
const refs = ref<any>({});
const refs = ref<Refs>({});
const setRef = (el: any, key: string | number) => {
refs.value[key] = el;
};
@ -13,3 +13,5 @@ export const useRef = (): UseRef => {
});
return [setRef, refs];
};
export default useRef;

View File

@ -0,0 +1,17 @@
import type { Ref } from 'vue';
import { ref } from 'vue';
export default function useState<T, R = Ref<T>>(
defaultStateValue: T | (() => T),
): [R, (val: T) => void] {
const initValue: T =
typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue;
const innerValue = ref(initValue) as Ref<T>;
function triggerChange(newValue: T) {
innerValue.value = newValue;
}
return [innerValue as unknown as R, triggerChange];
}

View File

@ -1,4 +0,0 @@
// https://github.com/moment/moment/issues/3650
export default function interopDefault(m) {
return m.default || m;
}

View File

@ -1,75 +0,0 @@
import interopDefault from './interopDefault';
import moment from 'moment';
import warning from './warning';
import isNil from 'lodash-es/isNil';
export const TimeType = {
validator(value) {
return typeof value === 'string' || isNil(value) || moment.isMoment(value);
},
};
export const TimesType = {
validator(value) {
if (Array.isArray(value)) {
return (
value.length === 0 ||
value.findIndex(val => typeof val !== 'string') === -1 ||
value.findIndex(val => !isNil(val) && !moment.isMoment(val)) === -1
);
}
return false;
},
};
export const TimeOrTimesType = {
validator(value) {
if (Array.isArray(value)) {
return (
value.length === 0 ||
value.findIndex(val => typeof val !== 'string') === -1 ||
value.findIndex(val => !isNil(val) && !moment.isMoment(val)) === -1
);
} else {
return typeof value === 'string' || isNil(value) || moment.isMoment(value);
}
},
};
export function checkValidate(componentName, value, propName, valueFormat) {
const values = Array.isArray(value) ? value : [value];
values.forEach(val => {
if (!val) return;
valueFormat &&
warning(
interopDefault(moment)(val, valueFormat).isValid(),
componentName,
`When set \`valueFormat\`, \`${propName}\` should provides invalidate string time. `,
);
!valueFormat &&
warning(
interopDefault(moment).isMoment(val) && val.isValid(),
componentName,
`\`${propName}\` provides invalidate moment time. If you want to set empty value, use \`null\` instead.`,
);
});
}
export const stringToMoment = (value, valueFormat) => {
if (Array.isArray(value)) {
return value.map(val =>
typeof val === 'string' && val ? interopDefault(moment)(val, valueFormat) : val || null,
);
} else {
return typeof value === 'string' && value
? interopDefault(moment)(value, valueFormat)
: value || null;
}
};
export const momentToString = (value, valueFormat) => {
if (Array.isArray(value)) {
return value.map(val => (interopDefault(moment).isMoment(val) ? val.format(valueFormat) : val));
} else {
return interopDefault(moment).isMoment(value) ? value.format(valueFormat) : value;
}
};

10
components/_util/omit.ts Normal file
View File

@ -0,0 +1,10 @@
function omit<T extends object, K extends keyof T>(obj: T, fields: K[]): Omit<T, K> {
// eslint-disable-next-line prefer-object-spread
const shallowCopy = Object.assign({}, obj);
for (let i = 0; i < fields.length; i += 1) {
const key = fields[i];
delete shallowCopy[key];
}
return shallowCopy;
}
export default omit;

View File

@ -3,6 +3,7 @@ import classNames from '../classNames';
import { isVNode, Fragment, Comment, Text, h } from 'vue';
import { camelize, hyphenate, isOn, resolvePropValue } from '../util';
import isValid from '../isValid';
import initDefaultProps from './initDefaultProps';
// function getType(fn) {
// const match = fn && fn.toString().match(/^\s*function (\w+)/);
// return match ? match[1] : '';
@ -28,6 +29,7 @@ const parseStyleText = (cssText = '', camel) => {
const res = {};
const listDelimiter = /;(?![^(]*\))/g;
const propertyDelimiter = /:(.+)/;
if (typeof cssText === 'object') return cssText;
cssText.split(listDelimiter).forEach(function (item) {
if (item) {
const tmp = item.split(propertyDelimiter);
@ -41,7 +43,7 @@ const parseStyleText = (cssText = '', camel) => {
};
const hasProp = (instance, prop) => {
return prop in getOptionProps(instance);
return instance[prop] !== undefined;
};
// 重构后直接使用 hasProp 替换
const slotHasProp = (slot, prop) => {
@ -367,16 +369,6 @@ export function filterEmpty(children = []) {
});
return res.filter(c => !isEmptyElement(c));
}
const initDefaultProps = (propTypes, defaultProps) => {
Object.keys(defaultProps).forEach(k => {
if (propTypes[k]) {
propTypes[k].def && (propTypes[k] = propTypes[k].def(defaultProps[k]));
} else {
throw new Error(`not have ${k} prop`);
}
});
return propTypes;
};
export function mergeProps() {
const args = [].slice.call(arguments, 0);
@ -395,13 +387,15 @@ export function mergeProps() {
}
function isValidElement(element) {
if (Array.isArray(element) && element.length === 1) {
element = element[0];
}
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
}
function getPropsSlot(slots, props, prop = 'default') {
return props[prop] ?? slots[prop]?.();
}
export {
splitAttrs,
hasProp,

View File

@ -17,7 +17,13 @@ const initDefaultProps = <T>(
Object.keys(defaultProps).forEach(k => {
const prop = propTypes[k] as VueTypeValidableDef;
if (prop) {
prop.default = defaultProps[k];
if (prop.type || prop.default) {
prop.default = defaultProps[k];
} else if (prop.def) {
prop.def(defaultProps[k]);
} else {
propTypes[k] = { type: prop, default: defaultProps[k] };
}
} else {
throw new Error(`not have ${k} prop`);
}

View File

@ -0,0 +1,14 @@
import type { UnwrapRef } from 'vue';
import { reactive, toRef } from 'vue';
/**
* Reactively pick fields from a reactive object
*
* @see https://vueuse.js.org/reactivePick
*/
export function reactivePick<T extends object, K extends keyof T>(
obj: T,
...keys: K[]
): { [S in K]: UnwrapRef<T[S]> } {
return reactive(Object.fromEntries(keys.map(k => [k, toRef(obj, k)]))) as any;
}

View File

@ -0,0 +1,42 @@
import { isRef, reactive } from 'vue';
import type { Ref } from 'vue';
type MaybeRef<T> = T | Ref<T>;
/**
* Converts ref to reactive.
*
* @see https://vueuse.org/toReactive
* @param objectRef A ref of object
*/
export function toReactive<T extends object>(objectRef: MaybeRef<T>): T {
if (!isRef(objectRef)) return reactive(objectRef) as T;
const proxy = new Proxy(
{},
{
get(_, p, receiver) {
return Reflect.get(objectRef.value, p, receiver);
},
set(_, p, value) {
(objectRef.value as any)[p] = value;
return true;
},
deleteProperty(_, p) {
return Reflect.deleteProperty(objectRef.value, p);
},
has(_, p) {
return Reflect.has(objectRef.value, p);
},
ownKeys() {
return Object.keys(objectRef.value);
},
getOwnPropertyDescriptor() {
return {
enumerable: true,
configurable: true,
};
},
},
);
return reactive(proxy) as T;
}

View File

@ -1,20 +1,32 @@
import type { BaseTransitionProps, CSSProperties, Ref } from 'vue';
import { onUpdated } from 'vue';
import { getCurrentInstance } from 'vue';
import { defineComponent, nextTick, Transition as T, TransitionGroup as TG } from 'vue';
import type {
BaseTransitionProps,
CSSProperties,
Ref,
TransitionGroupProps,
TransitionProps,
} from 'vue';
import {
onUpdated,
getCurrentInstance,
defineComponent,
nextTick,
Transition as T,
TransitionGroup as TG,
} from 'vue';
export const getTransitionProps = (transitionName: string, opt: object = {}) => {
export const getTransitionProps = (transitionName: string, opt: TransitionProps = {}) => {
if (process.env.NODE_ENV === 'test') {
return opt;
}
const transitionProps = transitionName
const transitionProps: TransitionProps = transitionName
? {
appear: true,
// type: 'animation',
// appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
// appearActiveClass: `antdv-base-transtion`,
appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
// appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
enterFromClass: `${transitionName}-enter ${transitionName}-enter-prepare`,
// enterActiveClass: `antdv-base-transtion`,
// enterActiveClass: `${transitionName}-enter ${transitionName}-enter-active`,
enterToClass: `${transitionName}-enter ${transitionName}-enter-active`,
leaveFromClass: ` ${transitionName}-leave`,
leaveActiveClass: `${transitionName}-leave ${transitionName}-leave-active`,
@ -25,8 +37,8 @@ export const getTransitionProps = (transitionName: string, opt: object = {}) =>
return transitionProps;
};
export const getTransitionGroupProps = (transitionName: string, opt: object = {}) => {
const transitionProps = transitionName
export const getTransitionGroupProps = (transitionName: string, opt: TransitionProps = {}) => {
const transitionProps: TransitionGroupProps = transitionName
? {
appear: true,
// appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
@ -146,6 +158,13 @@ const collapseMotion = (style: Ref<CSSProperties>, className: Ref<string>): CSSM
};
};
export { Transition, TransitionGroup, collapseMotion };
const getTransitionName = (rootPrefixCls: string, motion: string, transitionName?: string) => {
if (transitionName !== undefined) {
return transitionName;
}
return `${rootPrefixCls}-${motion}`;
};
export { Transition, TransitionGroup, collapseMotion, getTransitionName };
export default Transition;

View File

@ -1,4 +1,4 @@
import type { App, PropType, VNodeChild, Plugin } from 'vue';
import type { App, PropType, VNodeChild, Plugin, Ref } from 'vue';
// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
export const tuple = <T extends string[]>(...args: T) => args;
@ -39,3 +39,5 @@ export const withInstall = <T>(comp: T) => {
return comp as T & Plugin;
};
export type MaybeRef<T> = T | Ref<T>;

View File

@ -1,3 +1,4 @@
import type { VueNode } from './type';
export const isFunction = val => typeof val === 'function';
export const isArray = Array.isArray;
@ -62,4 +63,20 @@ export function getDataAndAriaProps(props) {
}, {});
}
export function toPx(val) {
if (typeof val === 'number') return `${val}px`;
return val;
}
export function renderHelper<T = Record<string, any>>(
v: VueNode | ((arg0: T) => VueNode),
props: T = {} as T,
defaultV?: any,
) {
if (typeof v === 'function') {
return v(props);
}
return v ?? defaultV;
}
export { isOn, cacheStringFunction, camelize, hyphenate, capitalize, resolvePropValue };

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./antdv-demo/docs/affix/demo/basic.md correctly 1`] = `
exports[`renders ./components/affix/demo/basic.vue correctly 1`] = `
<div style="width: 0px; height: 0px;">
<div class="ant-affix" style="position: fixed; top: 10px; width: 0px; height: 0px;"><button class="ant-btn ant-btn-primary" type="button">
<!----><span>Affix top</span>
@ -13,7 +13,7 @@ exports[`renders ./antdv-demo/docs/affix/demo/basic.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/affix/demo/on-change.md correctly 1`] = `
exports[`renders ./components/affix/demo/on-change.vue correctly 1`] = `
<div style="width: 0px; height: 0px;">
<div class="ant-affix" style="position: fixed; top: 120px; width: 0px; height: 0px;"><button class="ant-btn" type="button">
<!----><span>120px to affix top</span>
@ -21,7 +21,7 @@ exports[`renders ./antdv-demo/docs/affix/demo/on-change.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/affix/demo/target.md correctly 1`] = `
exports[`renders ./components/affix/demo/target.vue correctly 1`] = `
<div id="components-affix-demo-target" class="scrollable-container">
<div class="background">
<div>

View File

@ -0,0 +1,41 @@
<docs>
---
order: 0
title:
zh-CN: 基本
en-US: Basic
---
## zh-CN
最简单的用法
## en-US
The simplest usage.
</docs>
<template>
<a-affix :offset-top="top">
<a-button type="primary" @click="top += 10">Affix top</a-button>
</a-affix>
<br />
<a-affix :offset-bottom="bottom">
<a-button type="primary" @click="bottom += 10">Affix bottom</a-button>
</a-affix>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const top = ref<number>(10);
const bottom = ref<number>(10);
return {
top,
bottom,
};
},
});
</script>

View File

@ -0,0 +1,26 @@
<template>
<demo-sort>
<basic />
<on-change />
<traget />
</demo-sort>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import Basic from './basic.vue';
import OnChange from './on-change.vue';
import Traget from './target.vue';
export default defineComponent({
CN,
US,
components: {
Basic,
OnChange,
Traget,
},
});
</script>

View File

@ -0,0 +1,37 @@
<docs>
---
order: 1
title:
zh-CN: 固定状态改变的回调
en-US: Callback
---
## zh-CN
可以获得是否固定的状态
## en-US
Callback with affixed state.
</docs>
<template>
<a-affix :offset-top="120" @change="change">
<a-button>120px to affix top</a-button>
</a-affix>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const change = (affixed: boolean) => {
console.log(affixed);
};
return {
change,
};
},
});
</script>

View File

@ -0,0 +1,50 @@
<docs>
---
order: 2
title:
zh-CN: 滚动容器
en-US: Container to scroll.
---
## zh-CN
`target` 设置 `Affix` 需要监听其滚动事件的元素默认为 `window`
## en-US
Set a `target` for 'Affix', which is listen to scroll event of target element (default is `window`).
</docs>
<template>
<div id="components-affix-demo-target" ref="containerRef" class="scrollable-container">
<div class="background">
<a-affix :target="() => containerRef">
<a-button type="primary">Fixed at the top of container</a-button>
</a-affix>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const containerRef = ref();
return {
containerRef,
};
},
});
</script>
<style>
#components-affix-demo-target.scrollable-container {
height: 100px;
overflow-y: scroll;
}
#components-affix-demo-target .background {
padding-top: 60px;
height: 300px;
background-image: url('https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg');
}
</style>

View File

@ -0,0 +1,44 @@
---
category: Components
type: Navigation
title: Affix
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
---
Wrap Affix around another component to make it stick the viewport.
## When To Use
On longer web pages, its helpful for some content to stick to the viewport. This is common for menus and actions.
Please note that Affix should not cover other content on the page, especially when the size of the viewport is small.
## API
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| offsetBottom | Offset from the bottom of the viewport (in pixels) | number | - | |
| offsetTop | Offset from the top of the viewport (in pixels) | number | 0 | |
| target | Specifies the scrollable area DOM node | () => HTMLElement | () => window | |
### events
| Events Name | Description | Arguments | Version |
| ----------- | ---------------------------------------- | ----------------- | ------- |
| change | Callback for when Affix state is changed | Function(affixed) |
**Note:** Children of `Affix` must not have the property `position: absolute`, but you can set `position: absolute` on `Affix` itself:
```html
<a-affix :style="{ position: 'absolute', top: y, left: x}">
...
</a-affix>
```
## FAQ
### Affix bind container with `target`, sometime move out of container.
We don't listen window scroll for performance consideration.
Related issues[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)

View File

@ -12,7 +12,6 @@ import {
} from 'vue';
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import omit from 'omit.js';
import ResizeObserver from '../vc-resize-observer';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import { withInstall } from '../_util/type';
@ -24,6 +23,7 @@ import {
getFixedBottom,
} from './utils';
import useConfigInject from '../_util/hooks/useConfigInject';
import omit from '../_util/omit';
function getDefaultTarget() {
return typeof window !== 'undefined' ? window : null;
@ -46,7 +46,6 @@ const affixProps = {
* 距离窗口顶部达到指定偏移量后触发
*/
offsetTop: PropTypes.number,
offset: PropTypes.number,
/** 距离窗口底部达到指定偏移量后触发 */
offsetBottom: PropTypes.number,
/** 固定状态改变时触发的回调函数 */

View File

@ -0,0 +1,45 @@
---
category: Components
subtitle: 固钉
type: 导航
title: Affix
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
---
将页面元素钉在可视范围。
## 何时使用
当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。
页面可视范围过小时,慎用此功能以免遮挡页面内容。
## API
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | () => HTMLElement | () => window | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------------- | ----------------- | ---- |
| change | 固定状态改变时触发的回调函数 | Function(affixed) | 无 | |
**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
```html
<a-affix :style="{ position: 'absolute', top: y, left: x}">
...
</a-affix>
```
## FAQ
### Affix 使用 `target` 绑定容器时,元素会跑到容器外。
从性能角度考虑,我们只监听容器滚动事件。
相关 issue[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)

View File

@ -1,139 +1,320 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./antdv-demo/docs/alert/demo/banner.md correctly 1`] = `
<div class="ant-alert ant-alert-warning ant-alert-banner" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span><span class="ant-alert-message">Warning text</span><span class="ant-alert-description"><!----></span>
exports[`renders ./components/alert/demo/banner.vue correctly 1`] = `
<div class="ant-alert ant-alert-warning ant-alert-banner" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Warning text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div><br>
<div class="ant-alert ant-alert-warning ant-alert-banner ant-alert-closable" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span><span class="ant-alert-message">Very long warning text warning text text text text text text text</span><span class="ant-alert-description"><!----></span><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button></div><br>
<div class="ant-alert ant-alert-warning ant-alert-banner ant-alert-closable" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Very long warning text warning text text text text text text text</div>
<div class="ant-alert-description">
<!---->
</div>
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
</div><br>
<div class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-banner" data-show="true">
<!----><span class="ant-alert-message">Warning text without icon</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Warning text without icon</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div><br>
<div class="ant-alert ant-alert-error ant-alert-banner" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span><span class="ant-alert-message">Error text</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-error ant-alert-banner" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Error text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/basic.md correctly 1`] = `
exports[`renders ./components/alert/demo/basic.vue correctly 1`] = `
<div class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Success Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/closable.md correctly 1`] = `
exports[`renders ./components/alert/demo/closable.vue correctly 1`] = `
<div class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable" data-show="true">
<!----><span class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</span><span class="ant-alert-description"><!----></span><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
</div>
<div class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon ant-alert-closable" data-show="true">
<!----><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</span><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Error Text</div>
<div class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</div>
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/close-text.md correctly 1`] = `
exports[`renders ./components/alert/demo/close-text.vue correctly 1`] = `
<div class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-closable" data-show="true">
<!----><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"><!----></span><button type="button" class="ant-alert-close-icon" tabindex="0"><span class="ant-alert-close-text">Close Now</span></button>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Info Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span class="ant-alert-close-text">Close Now</span></button>
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/custom-icon.md correctly 1`] = `
exports[`renders ./components/alert/demo/custom-icon.vue correctly 1`] = `
<div class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">showIcon = false</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">showIcon = false</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-success" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Success Tips</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Informational Notes</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Warning</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Warning</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Error</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Error</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description">Detailed description and advices about successful copywriting.</span>
<div class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Success Tips</div>
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description">Additional description and informations about copywriting.</span>
<div class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Informational Notes</div>
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Warning</span><span class="ant-alert-description">This is a warning notice about copywriting.</span>
<div class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Warning</div>
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span class="ant-alert-icon"><span role="img" aria-label="smile" class="anticon anticon-smile"><svg class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span></span><span class="ant-alert-message">Error</span><span class="ant-alert-description">This is an error message about copywriting.</span>
<div class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Error</div>
<div class="ant-alert-description">This is an error message about copywriting.</div>
</div>
<!---->
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/description.md correctly 1`] = `
exports[`renders ./components/alert/demo/description.vue correctly 1`] = `
<div class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"><p> Success Description <span style="color: red;">Success</span> Description Success Description </p></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Success Text</div>
<div class="ant-alert-description">
<p> Success Description <span style="color: red;">Success</span> Description Success Description </p>
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Info Text</span><span class="ant-alert-description">Info Description Info Description Info Description Info Description</span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Info Text</div>
<div class="ant-alert-description">Info Description Info Description Info Description Info Description</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Warning Text</div>
<div class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Error Text</span><span class="ant-alert-description">Error Description Error Description Error Description Error Description</span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Error Text</div>
<div class="ant-alert-description">Error Description Error Description Error Description Error Description</div>
</div>
<!---->
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/icon.md correctly 1`] = `
<div class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></span><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description"><!----></span>
exports[`renders ./components/alert/demo/icon.vue correctly 1`] = `
<div class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Success Tips</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Informational Notes</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span><span class="ant-alert-message">Warning</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Warning</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span><span class="ant-alert-message">Error</span><span class="ant-alert-description"><!----></span>
<div class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Error</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span><span class="ant-alert-message">Success Tips</span><span class="ant-alert-description">Detailed description and advices about successful copywriting.</span>
<div class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Success Tips</div>
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"></path></svg></span><span class="ant-alert-message">Informational Notes</span><span class="ant-alert-description">Additional description and informations about copywriting.</span>
<div class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Informational Notes</div>
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"></path></svg></span><span class="ant-alert-message">Warning</span><span class="ant-alert-description">This is a warning notice about copywriting.</span>
<div class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Warning</div>
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span><span class="ant-alert-message">Error</span><span class="ant-alert-description">This is an error message about copywriting.</span>
<div class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
<div class="ant-alert-content">
<div class="ant-alert-message">Error</div>
<div class="ant-alert-description">This is an error message about copywriting.</div>
</div>
<!---->
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/smooth-closed.md correctly 1`] = `
exports[`renders ./components/alert/demo/smooth-closed.vue correctly 1`] = `
<div class="ant-alert ant-alert-success ant-alert-no-icon ant-alert-closable" data-show="true">
<!----><span class="ant-alert-message">Alert Message Text</span><span class="ant-alert-description"><!----></span><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Alert Message Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
</div>
`;
exports[`renders ./antdv-demo/docs/alert/demo/style.md correctly 1`] = `
exports[`renders ./components/alert/demo/style.vue correctly 1`] = `
<div class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Success Text</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Success Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-info ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Info Text</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Info Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-warning ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Warning Text</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Warning Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
<div class="ant-alert ant-alert-error ant-alert-no-icon" data-show="true">
<!----><span class="ant-alert-message">Error Text</span><span class="ant-alert-description"><!----></span>
<!---->
<div class="ant-alert-content">
<div class="ant-alert-message">Error Text</div>
<div class="ant-alert-description">
<!---->
</div>
</div>
<!---->
</div>
`;

View File

@ -0,0 +1,31 @@
<docs>
---
order: 6
title:
zh-CN: 顶部公告
en-US: Banner
---
## zh-CN
最简单的用法适用于简短的警告提示
## en-US
Display Alert as a banner at top of page.
</docs>
<template>
<a-alert message="Warning text" banner />
<br />
<a-alert
message="Very long warning text warning text text text text text text text"
banner
closable
/>
<br />
<a-alert :show-icon="false" message="Warning text without icon" banner />
<br />
<a-alert type="error" message="Error text" banner />
</template>

View File

@ -0,0 +1,21 @@
<docs>
---
order: 0
title:
zh-CN: 基本用法
en-US: Basic usage
---
## zh-CN
最简单的用法适用于简短的警告提示
## en-US
The simplest usage for short messages.
</docs>
<template>
<a-alert message="Success Text" type="success" />
</template>

View File

@ -0,0 +1,47 @@
<docs>
---
order: 2
title:
zh-CN: 可关闭的警告提示
en-US: Customized Close Text
---
## zh-CN
显示关闭按钮点击可关闭警告提示
## en-US
To show close button.
</docs>
<template>
<a-alert
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
type="warning"
closable
@close="onClose"
/>
<a-alert
message="Error Text"
description="Error Description Error Description Error Description Error Description Error Description Error Description"
type="error"
closable
@close="onClose"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const onClose = (e: MouseEvent) => {
console.log(e, 'I was closed.');
};
return {
onClose,
};
},
});
</script>

View File

@ -0,0 +1,21 @@
<docs>
---
order: 5
title:
zh-CN: 自定义关闭
en-US: Customized Close Text
---
## zh-CN
自定义图标让信息类型更加醒目
## en-US
Replace the default icon with customized text.
</docs>
<template>
<a-alert message="Info Text" type="info" close-text="Close Now" />
</template>

View File

@ -0,0 +1,77 @@
<docs>
---
order: 7
title:
zh-CN: 自定义图标
en-US: Custom Icon
---
## zh-CN
可以自定义关闭自定义的文字会替换原先的关闭 `Icon`
## en-US
Custom Icon make information more clear and more friendly.
</docs>
<template>
<a-alert message="showIcon = false" type="success">
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert message="Success Tips" type="success" show-icon>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert message="Informational Notes" type="info" show-icon>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert message="Warning" type="warning" show-icon>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert message="Error" type="error" show-icon>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert
message="Success Tips"
description="Detailed description and advices about successful copywriting."
type="success"
show-icon
>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert
message="Informational Notes"
description="Additional description and informations about copywriting."
type="info"
show-icon
>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert
message="Warning"
description="This is a warning notice about copywriting."
type="warning"
show-icon
>
<template #icon><smile-outlined /></template>
</a-alert>
<a-alert
message="Error"
description="This is an error message about copywriting."
type="error"
show-icon
>
<template #icon><smile-outlined /></template>
</a-alert>
</template>
<script lang="ts">
import { SmileOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
SmileOutlined,
},
});
</script>

View File

@ -0,0 +1,44 @@
<docs>
---
order: 3
title:
zh-CN: 含有辅助性文字介绍
en-US: Description
---
## zh-CN
含有辅助性文字介绍的警告提示
## en-US
Additional description for alert message.
</docs>
<template>
<a-alert message="Success Text" type="success">
<template #description>
<p>
Success Description
<span style="color: red">Success</span>
Description Success Description
</p>
</template>
</a-alert>
<a-alert
message="Info Text"
description="Info Description Info Description Info Description Info Description"
type="info"
/>
<a-alert
message="Warning Text"
description="Warning Description Warning Description Warning Description Warning Description"
type="warning"
/>
<a-alert
message="Error Text"
description="Error Description Error Description Error Description Error Description"
type="error"
/>
</template>

View File

@ -0,0 +1,48 @@
<docs>
---
order: 4
title:
zh-CN: 图标
en-US: Icon
---
## zh-CN
可口的图标让信息类型更加醒目
## en-US
Decent icon make information more clear and more friendly.
</docs>
<template>
<a-alert message="Success Tips" type="success" show-icon />
<a-alert message="Informational Notes" type="info" show-icon />
<a-alert message="Warning" type="warning" show-icon />
<a-alert message="Error" type="error" show-icon />
<a-alert
message="Success Tips"
description="Detailed description and advices about successful copywriting."
type="success"
show-icon
/>
<a-alert
message="Informational Notes"
description="Additional description and informations about copywriting."
type="info"
show-icon
/>
<a-alert
message="Warning"
description="This is a warning notice about copywriting."
type="warning"
show-icon
/>
<a-alert
message="Error"
description="This is an error message about copywriting."
type="error"
show-icon
/>
</template>

View File

@ -0,0 +1,50 @@
<template>
<demo-sort>
<basic />
<four-style />
<closable />
<description />
<icon />
<close-text />
<banner />
<custom-icon />
<smooth-closed />
</demo-sort>
</template>
<script lang="ts">
import Banner from './banner.vue';
import Basic from './basic.vue';
import Closable from './closable.vue';
import CloseText from './close-text.vue';
import Description from './description.vue';
import Icon from './icon.vue';
import Style from './style.vue';
import SmoothClosed from './smooth-closed.vue';
import CustomIcon from './custom-icon.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
export default defineComponent({
CN,
US,
components: {
Basic,
Banner,
Closable,
CloseText,
Description,
Icon,
FourStyle: Style, //style
SmoothClosed,
CustomIcon,
},
setup() {
return {};
},
});
</script>
<style>
[id^='components-alert-demo'] .ant-alert {
margin-bottom: 16px;
}
</style>

View File

@ -0,0 +1,42 @@
<docs>
---
order: 8
title:
zh-CN: 平滑地卸载
en-US: Smoothly Unmount
---
## zh-CN
平滑自然的卸载提示
## en-US
Smoothly and unaffectedly unmount Alert.
</docs>
<template>
<a-alert
v-if="visible"
message="Alert Message Text"
type="success"
closable
:after-close="handleClose"
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const visible = ref<boolean>(true);
const handleClose = () => {
visible.value = false;
};
return {
visible,
handleClose,
};
},
});
</script>

View File

@ -0,0 +1,24 @@
<docs>
---
order: 1
title:
zh-CN: 四种样式
en-US: More types
---
## zh-CN
共有四种样式 `success``info``warning``error`
## en-US
There are 4 types of Alert: `success`, `info`, `warning`, `error`.
</docs>
<template>
<a-alert message="Success Text" type="success" />
<a-alert message="Info Text" type="info" />
<a-alert message="Warning Text" type="warning" />
<a-alert message="Error Text" type="error" />
</template>

View File

@ -0,0 +1,33 @@
---
category: Components
type: Feedback
title: Alert
cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
---
Alert component for feedback.
## When To Use
- When you need to show alert messages to users.
- When you need a persistent static container which is closable by user actions.
## API
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| afterClose | Called when close animation is finished | () => void | - | |
| banner | Whether to show as banner | boolean | false | |
| closable | Whether Alert can be closed | boolean | | |
| closeText | Close text to show | string\|slot | - | |
| description | Additional content of Alert | string\|slot | - | |
| icon | Custom icon, effective when `showIcon` is `true` | vnode \| slot | - | |
| message | Content of Alert | string\|slot | - | |
| showIcon | Whether to show icon | boolean | false,in `banner` mode default is true | |
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`,in `banner` mode default is `warning` | |
### events
| Events Name | Description | Arguments | Version |
| ----------- | ----------------------------- | ----------------------- | ------- |
| close | Callback when Alert is closed | (e: MouseEvent) => void | - |

View File

@ -1,5 +1,5 @@
import type { ExtractPropTypes } from 'vue';
import { inject, cloneVNode, defineComponent, ref } from 'vue';
import { inject, defineComponent, ref } from 'vue';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined';
import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined';
@ -15,6 +15,7 @@ import { getTransitionProps, Transition } from '../_util/transition';
import { isValidElement, getPropsSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider';
import { tuple, withInstall } from '../_util/type';
import { cloneElement } from '../_util/vnode';
function noop() {}
@ -139,7 +140,7 @@ const Alert = defineComponent({
const iconNode = (icon &&
(isValidElement(icon) ? (
cloneVNode(icon, {
cloneElement(icon, {
class: `${prefixCls}-icon`,
})
) : (

View File

@ -0,0 +1,34 @@
---
category: Components
type: 反馈
title: Alert
subtitle: 警告提示
cover: https://gw.alipayobjects.com/zos/alicdn/8emPa3fjl/Alert.svg
---
警告提示,展现需要关注的信息。
## 何时使用
- 当某个页面需要向用户显示警告的信息时。
- 非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。
## API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| afterClose | 关闭动画结束后触发的回调函数 | () => void | - | |
| banner | 是否用作顶部公告 | boolean | false | |
| closable | 默认不显示关闭按钮 | boolean | 无 | |
| closeText | 自定义关闭按钮 | string\|slot | 无 | |
| description | 警告提示的辅助性文字介绍 | string\|slot | 无 | |
| icon | 自定义图标,`showIcon` 为 `true` 时有效 | vnode\|slot | - | |
| message | 警告提示内容 | string\|slot | 无 | |
| showIcon | 是否显示辅助图标 | boolean | false,`banner` 模式下默认值为 true | |
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info`,`banner` 模式下默认值为 `warning` | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | -------------------- | ----------------------- | ---- |
| close | 关闭时触发的回调函数 | (e: MouseEvent) => void | - |

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./antdv-demo/docs/anchor/demo/basic.md correctly 1`] = `
exports[`renders ./components/anchor/demo/basic.vue correctly 1`] = `
<div>
<div class="">
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
@ -29,7 +29,7 @@ exports[`renders ./antdv-demo/docs/anchor/demo/basic.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/anchor/demo/customizeHighlight.md correctly 1`] = `
exports[`renders ./components/anchor/demo/customizeHighlight.vue correctly 1`] = `
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
<div class="ant-anchor fixed">
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball visible" style="top: -4.5px;"></span></div>
@ -51,7 +51,7 @@ exports[`renders ./antdv-demo/docs/anchor/demo/customizeHighlight.md correctly 1
</div>
`;
exports[`renders ./antdv-demo/docs/anchor/demo/onChange.md correctly 1`] = `
exports[`renders ./components/anchor/demo/onChange.vue correctly 1`] = `
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
<div class="ant-anchor fixed">
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
@ -73,7 +73,7 @@ exports[`renders ./antdv-demo/docs/anchor/demo/onChange.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/anchor/demo/onClick.md correctly 1`] = `
exports[`renders ./components/anchor/demo/onClick.vue correctly 1`] = `
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
<div class="ant-anchor fixed">
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
@ -95,7 +95,7 @@ exports[`renders ./antdv-demo/docs/anchor/demo/onClick.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/anchor/demo/static.md correctly 1`] = `
exports[`renders ./components/anchor/demo/static.vue correctly 1`] = `
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
<div class="ant-anchor fixed">
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
@ -117,7 +117,7 @@ exports[`renders ./antdv-demo/docs/anchor/demo/static.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/anchor/demo/targetOffset.md correctly 1`] = `
exports[`renders ./components/anchor/demo/targetOffset.vue correctly 1`] = `
<div>
<div class="">
<div class="ant-anchor-wrapper" style="max-height: 100vh;">

View File

@ -0,0 +1,32 @@
<docs>
---
order: 0
title:
zh-CN: 基本使用
en-US: Basic Usage
---
## zh-CN
最简单的用法
## en-US
The simplest usage.
</docs>
<template>
<a-anchor>
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link
href="#components-anchor-demo-basic"
title="Basic demo with Target"
target="_blank"
/>
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>

View File

@ -0,0 +1,42 @@
<docs>
---
order: 3
title:
zh-CN: 自定义锚点高亮
en-US: Customize the anchor highlight
---
## zh-CN
自定义锚点高亮
## en-US
Customize the anchor highlight.
</docs>
<template>
<a-anchor :affix="false" :get-current-anchor="getCurrentAnchor">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const getCurrentAnchor = () => {
return '#components-anchor-demo-static';
};
return {
getCurrentAnchor,
};
},
});
</script>

View File

@ -0,0 +1,38 @@
<template>
<demo-sort>
<basic />
<static />
<on-click />
<customize-highlight />
<target-offset />
<on-change />
</demo-sort>
</template>
<script lang="ts">
import Basic from './basic.vue';
import Static from './static.vue';
import OnClick from './onClick.vue';
import CustomizeHighlight from './customizeHighlight.vue';
import TargetOffset from './targetOffset.vue';
import OnChange from './onChange.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
export default defineComponent({
CN,
US,
components: {
Basic,
Static,
OnClick,
CustomizeHighlight,
TargetOffset,
OnChange,
},
setup() {
return {};
},
});
</script>

View File

@ -0,0 +1,42 @@
<docs>
---
order: 5
title:
zh-CN: 监听锚点链接改变
en-US: Listening for anchor link change
---
## zh-CN
监听锚点链接改变
## en-US
Listening for anchor link change.
</docs>
<template>
<a-anchor :affix="false" @change="onChange">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const onChange = (link: string) => {
console.log('Anchor:OnChange', link);
};
return {
onChange,
};
},
});
</script>

View File

@ -0,0 +1,43 @@
<docs>
---
order: 2
title:
zh-CN: 自定义 click 事件
en-US: Customize the click event
---
## zh-CN
点击锚点不记录历史
## en-US
Clicking on an anchor does not record history.
</docs>
<template>
<a-anchor :affix="false" @click="handleClick">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const handleClick = (e: Event, link: string) => {
e.preventDefault();
console.log(link);
};
return {
handleClick,
};
},
});
</script>

View File

@ -0,0 +1,27 @@
<docs>
---
order: 1
title:
zh-CN: 静态位置
en-US: Static
---
## zh-CN
不浮动状态不随页面滚动变化
## en-US
Do not change state when page is scrolling.
</docs>
<template>
<a-anchor :affix="false">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>

View File

@ -0,0 +1,43 @@
<docs>
---
order: 4
title:
zh-CN: 设置锚点滚动偏移量
en-US: Set Anchor scroll offset
---
## zh-CN
锚点目标滚动到屏幕正中间
## en-US
Anchor target scroll to screen center.
</docs>
<template>
<a-anchor :target-offset="targetOffset">
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
<a-anchor-link href="#API" title="API">
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
<a-anchor-link href="#Link-Props" title="Link Props" />
</a-anchor-link>
</a-anchor>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
export default defineComponent({
setup() {
const targetOffset = ref<number | undefined>(undefined);
onMounted(() => {
targetOffset.value = window.innerHeight / 2;
});
return {
targetOffset,
};
},
});
</script>

View File

@ -0,0 +1,45 @@
---
category: Components
type: Other
cols: 2
title: Anchor
cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
---
Hyperlinks to scroll on one page.
## When To Use
For displaying anchor hyperlinks on page and jumping between them.
## API
### Anchor Props
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| affix | Fixed mode of Anchor | boolean | true | |
| bounds | Bounding distance of anchor area | number | 5(px) | |
| getContainer | Scrolling container | () => HTMLElement | () => window | |
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - | |
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | |
| showInkInFixed | Whether show ink-balls when `affix="false"` | boolean | false | |
| wrapperClass | The class name of the container | string | - | |
| wrapperStyle | The style of the container | object | - | |
| getCurrentAnchor | Customize the anchor highlight | () => string | - | 1.5.0 |
| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
### Events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- |
| click | set the handler to handle `click` event | Function(e: Event, link: Object) | |
| change | Listening for anchor link change | (currentActiveLink: string) => void | | 1.5.0 |
### Link Props
| Property | Description | Type | Default | Version |
| -------- | ----------------------------------------- | ------------ | ------- | ------- |
| href | target of hyperlink | string | | |
| title | content of hyperlink | string\|slot | | |
| target | Specifies where to display the linked URL | string | | 1.5.0 |

View File

@ -1,6 +1,8 @@
import type { App, Plugin } from 'vue';
import Anchor, { AnchorProps } from './Anchor';
import AnchorLink, { AnchorLinkProps } from './AnchorLink';
import type { AnchorProps } from './Anchor';
import type { AnchorLinkProps } from './AnchorLink';
import Anchor from './Anchor';
import AnchorLink from './AnchorLink';
Anchor.Link = AnchorLink;
@ -11,7 +13,8 @@ Anchor.install = function (app: App) {
return app;
};
export { AnchorLinkProps, AnchorProps, AnchorLink, AnchorLink as Link };
export type { AnchorLinkProps, AnchorProps };
export { AnchorLink, AnchorLink as Link };
export default Anchor as typeof Anchor &
Plugin & {

View File

@ -0,0 +1,46 @@
---
category: Components
subtitle: 锚点
cols: 2
type: 其他
title: Anchor
cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
---
用于跳转到页面指定位置。
## 何时使用
需要展现当前页面上可供跳转的锚点链接,以及快速在锚点之间跳转。
## API
### Anchor Props
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| affix | 固定模式 | boolean | true | |
| bounds | 锚点区域边界 | number | 5(px) | |
| getContainer | 指定滚动的容器 | () => HTMLElement | () => window | |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| showInkInFixed | `:affix="false"` 时是否显示小圆点 | boolean | false | |
| wrapperClass | 容器的类名 | string | - | |
| wrapperStyle | 容器样式 | object | - | |
| getCurrentAnchor | 自定义高亮的锚点 | () => string | - | 1.5.0 |
| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------- | ----------------------------------- | ---- |
| click | `click` 事件的 handler | Function(e: Event, link: Object) | |
| change | 监听锚点链接改变 | (currentActiveLink: string) => void | | 1.5.0 |
### Link Props
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| ------ | -------------------------------- | ------------ | ------ | ----- |
| href | 锚点链接 | string | | |
| title | 文字内容 | string\|slot | | |
| target | 该属性指定在何处显示链接的资源。 | string | | 1.5.0 |

View File

@ -1,10 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./antdv-demo/docs/auto-complete/demo/basic.md correctly 1`] = `
<div class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 200px;">
exports[`renders ./components/auto-complete/demo/basic.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input type="search" id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->
@ -12,13 +12,13 @@ exports[`renders ./antdv-demo/docs/auto-complete/demo/basic.md correctly 1`] = `
</div>
`;
exports[`renders ./antdv-demo/docs/auto-complete/demo/certain-category.md correctly 1`] = `
exports[`renders ./components/auto-complete/demo/certain-category.vue correctly 1`] = `
<div class="certain-category-search-wrapper" style="width: 250px;">
<div class="ant-select ant-select-lg certain-category-search ant-select-lg ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 100%;">
<div class="ant-select ant-select-lg certain-category-search ant-select-lg ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search" style="width: 100%;">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><span class="ant-select-selection-search-input ant-input-affix-wrapper"><!----><input type="search" id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"><span class="ant-input-suffix"><!----><span role="img" aria-label="search" class="anticon anticon-search certain-category-icon"><svg class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></span></span></span></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><span class="ant-select-selection-search-input ant-input-affix-wrapper"><!----><input placeholder="input here" id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" class="ant-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"><span class="ant-input-suffix"><!----><span role="img" aria-label="search" class="anticon anticon-search certain-category-icon"><svg focusable="false" class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></span></span></span></span>
<!----><span class="ant-select-selection-placeholder"><!----></span>
</div>
<!---->
<!---->
@ -26,11 +26,11 @@ exports[`renders ./antdv-demo/docs/auto-complete/demo/certain-category.md correc
</div>
`;
exports[`renders ./antdv-demo/docs/auto-complete/demo/custom.md correctly 1`] = `
<div class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 200px;">
exports[`renders ./components/auto-complete/demo/custom.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><textarea placeholder="input here" class="ant-input ant-select-selection-search-input" style="height: 50px;" id="rc_select_TEST_OR_SSR" autocomplete="off" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></textarea></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><textarea placeholder="input here" id="rc_select_TEST_OR_SSR" class="ant-input ant-select-selection-search-input" style="height: 50px;" autocomplete="off" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></textarea></span>
<!----><span class="ant-select-selection-placeholder"><!----></span>
</div>
<!---->
@ -38,11 +38,11 @@ exports[`renders ./antdv-demo/docs/auto-complete/demo/custom.md correctly 1`] =
</div>
`;
exports[`renders ./antdv-demo/docs/auto-complete/demo/non-case-sensitive.md correctly 1`] = `
<div class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 200px;">
exports[`renders ./components/auto-complete/demo/non-case-sensitive.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input type="search" id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->
@ -50,11 +50,11 @@ exports[`renders ./antdv-demo/docs/auto-complete/demo/non-case-sensitive.md corr
</div>
`;
exports[`renders ./antdv-demo/docs/auto-complete/demo/options.md correctly 1`] = `
<div class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 200px;">
exports[`renders ./components/auto-complete/demo/options.vue correctly 1`] = `
<div style="width: 200px;" class="ant-select ant-select-show-search ant-select-auto-complete ant-select-single ant-select-show-search">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input type="search" id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" type="search"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
</div>
<!---->
@ -62,13 +62,13 @@ exports[`renders ./antdv-demo/docs/auto-complete/demo/options.md correctly 1`] =
</div>
`;
exports[`renders ./antdv-demo/docs/auto-complete/demo/uncertain-category.md correctly 1`] = `
exports[`renders ./components/auto-complete/demo/uncertain-category.vue correctly 1`] = `
<div class="global-search-wrapper" style="width: 300px;">
<div class="ant-select ant-select-lg global-search ant-select-lg ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input" style="width: 100%;">
<div class="ant-select ant-select-lg global-search ant-select-lg ant-select-show-search ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search" style="width: 100%;">
<!---->
<!---->
<div class="ant-select-selector"><span class="ant-select-selection-search"><input type="search" id="rc_select_TEST_OR_SSR" autocomplete="off" class="ant-input ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0"></span>
<!----><span class="ant-select-selection-placeholder">input here</span>
<div class="ant-select-selector"><span class="ant-select-selection-search"><span class="ant-input-search ant-select-selection-search-input ant-input-search-enter-button ant-input-search-large ant-input-group-wrapper ant-input-group-wrapper-lg"><span class="ant-input-wrapper ant-input-group"><!----><input placeholder="input here" id="rc_select_TEST_OR_SSR" type="search" autocomplete="off" role="combobox" aria-haspopup="listbox" aria-owns="rc_select_TEST_OR_SSR_list" aria-autocomplete="list" aria-controls="rc_select_TEST_OR_SSR_list" aria-activedescendant="rc_select_TEST_OR_SSR_list_0" class="ant-input ant-input-lg"><span class="ant-input-group-addon"><button class="ant-btn ant-btn-primary ant-btn-lg ant-input-search-button" type="button"><!----><span role="img" aria-label="search" class="anticon anticon-search"><svg focusable="false" class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></span></button></span></span></span></span>
<!----><span class="ant-select-selection-placeholder"><!----></span>
</div>
<!---->
<!---->

View File

@ -0,0 +1,64 @@
<docs>
---
order: 0
title:
zh-CN: 基本使用
en-US: Basic Usage
---
## zh-CN
基本使用通过 options 设置自动完成的数据源
## en-US
Basic Usage, set datasource of autocomplete with `options` property.
</docs>
<template>
<a-auto-complete
v-model:value="value"
:options="options"
style="width: 200px"
placeholder="input here"
@select="onSelect"
@search="onSearch"
/>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
interface MockVal {
value: string;
}
const mockVal = (str: string, repeat = 1): MockVal => {
return {
value: str.repeat(repeat),
};
};
export default defineComponent({
setup() {
const value = ref('');
const options = ref<MockVal[]>([]);
const onSearch = (searchText: string) => {
console.log('searchText');
options.value = !searchText
? []
: [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)];
};
const onSelect = (value: string) => {
console.log('onSelect', value);
};
watch(value, () => {
console.log('value', value.value);
});
return {
value,
options,
onSearch,
onSelect,
};
},
});
</script>

View File

@ -0,0 +1,168 @@
<docs>
---
order: 4
title:
zh-CN: 查询模式 - 确定类目
en-US: Lookup-Patterns - Certain Category
---
## zh-CN
查询模式 - 确定类目
## en-US
Lookup-Patterns - Certain Category.
</docs>
<template>
<div class="certain-category-search-wrapper" style="width: 250px">
<a-auto-complete
v-model:value="value"
class="certain-category-search"
dropdown-class-name="certain-category-search-dropdown"
:dropdown-match-select-width="false"
:dropdown-style="{ width: '300px' }"
size="large"
style="width: 100%"
option-label-prop="value"
:options="dataSource"
>
<template #option="item">
<template v-if="item.options">
<span>
{{ item.value }}
<a
style="float: right"
href="https://www.google.com/search?q=antd"
target="_blank"
rel="noopener noreferrer"
>
more
</a>
</span>
</template>
<template v-else-if="item.value === 'all'">
<a
href="https://www.google.com/search?q=ant-design-vue"
target="_blank"
rel="noopener noreferrer"
>
View all results
</a>
</template>
<template v-else>
{{ item.title }}
<span class="certain-search-item-count">{{ item.count }} people</span>
</template>
</template>
<a-input placeholder="input here">
<template #suffix><search-outlined class="certain-category-icon" /></template>
</a-input>
</a-auto-complete>
</div>
</template>
<script lang="ts">
import { SearchOutlined } from '@ant-design/icons-vue';
import { defineComponent, ref } from 'vue';
const dataSource = [
{
value: 'Libraries',
options: [
{
value: 'AntDesign',
count: 10000,
},
{
value: 'AntDesign UI',
count: 10600,
},
],
},
{
value: 'Solutions',
options: [
{
value: 'AntDesign UI FAQ',
count: 60100,
},
{
value: 'AntDesign FAQ',
count: 30010,
},
],
},
{
value: 'Articles',
options: [
{
value: 'AntDesign design language',
count: 100000,
},
],
},
{
value: 'all',
},
];
export default defineComponent({
components: {
SearchOutlined,
},
setup() {
return {
value: ref(''),
dataSource,
};
},
});
</script>
<style>
.certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title {
color: #666;
font-weight: bold;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item-group {
border-bottom: 1px solid #f6f6f6;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item {
padding-left: 16px;
}
.certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all {
text-align: center;
cursor: default;
}
.certain-category-search-dropdown .ant-select-dropdown-menu {
max-height: 300px;
}
</style>
<style scoped>
.certain-category-search-wrapper
:deep(.certain-category-search.ant-select-auto-complete)
.ant-input-affix-wrapper
.ant-input-suffix {
right: 12px;
}
.certain-category-search-wrapper :deep(.certain-search-item-count) {
position: absolute;
color: #999;
right: 16px;
}
.certain-category-search-wrapper
:deep(.certain-category-search.ant-select-focused)
.certain-category-icon {
color: #108ee9;
}
.certain-category-search-wrapper :deep(.certain-category-icon) {
color: #6e6e6e;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
font-size: 16px;
}
</style>

View File

@ -0,0 +1,61 @@
<docs>
---
order: 2
title:
zh-CN: 自定义输入组件
en-US: Customize Input Component
---
## zh-CN
自定义输入组件
## en-US
Customize Input Component.
</docs>
<template>
<a-auto-complete
v-model:value="value"
:options="options"
style="width: 200px"
@search="handleSearch"
@select="onSelect"
>
<a-textarea
placeholder="input here"
class="custom"
style="height: 50px"
@keypress="handleKeyPress"
/>
</a-auto-complete>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = ref<{ value: string }[]>([]);
const onSelect = (value: string) => {
console.log('onSelect', value);
};
const handleSearch = (value: string) => {
options.value = !value
? []
: [{ value }, { value: value + value }, { value: value + value + value }];
};
const handleKeyPress = (ev: KeyboardEvent) => {
console.log('handleKeyPress', ev);
};
return {
value,
options,
onSelect,
handleSearch,
handleKeyPress,
};
},
});
</script>

View File

@ -0,0 +1,39 @@
<template>
<demo-sort>
<basic />
<options />
<custom />
<non-case-sensitive />
<certain-category />
<uncertain-category />
</demo-sort>
</template>
<script lang="ts">
import Basic from './basic.vue';
import Options from './options.vue';
import Custom from './custom.vue';
import NonCaseSensitive from './non-case-sensitive.vue';
import CertainCategory from './certain-category.vue';
import UncertainCategory from './uncertain-category.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
export default defineComponent({
CN,
US,
components: {
Basic,
Options,
Custom,
NonCaseSensitive,
CertainCategory,
UncertainCategory,
},
setup() {
return {};
},
});
</script>

View File

@ -0,0 +1,49 @@
<docs>
---
order: 3
title:
zh-CN: 不区分大小写
en-US: Non-case-sensitive AutoComplete
---
## zh-CN
不区分大小写的 AutoComplete
## en-US
A non-case-sensitive AutoComplete.
</docs>
<template>
<a-auto-complete
v-model:value="value"
:options="options"
style="width: 200px"
placeholder="input here"
:filter-option="filterOption"
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
interface Option {
value: string;
}
export default defineComponent({
setup() {
const filterOption = (input: string, option: Option) => {
return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0;
};
return {
value: ref(''),
options: ref<Option[]>([
{ value: 'Burns Bay Road' },
{ value: 'Downing Street' },
{ value: 'Wall Street' },
]),
filterOption,
};
},
});
</script>

View File

@ -0,0 +1,57 @@
<docs>
---
order: 1
title:
zh-CN: 自定义选项
en-US: Customized
---
## zh-CN
3.0 以上版本可以传递 `v-slot:option` 来自定义 Option
## en-US
For 3.0+, You could pass `v-slot:option` to custom option.
</docs>
<template>
<a-auto-complete
v-model:value="value"
style="width: 200px"
placeholder="input here"
:options="options"
@search="handleSearch"
>
<template #option="{ value: val }">
{{ val.split('@')[0] }} @
<span style="font-weight: bold">{{ val.split('@')[1] }}</span>
</template>
</a-auto-complete>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = ref<{ value: string }[]>([]);
const handleSearch = (val: string) => {
let res: { value: string }[];
if (!val || val.indexOf('@') >= 0) {
res = [];
} else {
res = ['gmail.com', '163.com', 'qq.com'].map(domain => ({ value: `${val}@${domain}` }));
}
options.value = res;
};
return {
value,
options,
handleSearch,
};
},
});
</script>

View File

@ -0,0 +1,125 @@
<docs>
---
order: 5
title:
zh-CN: 查询模式 - 不确定类目
en-US: Lookup-Patterns - Uncertain Category
---
## zh-CN
查询模式 - 不确定类目
## en-US
Lookup-Patterns - Uncertain Category.
</docs>
<template>
<div class="global-search-wrapper" style="width: 300px">
<a-auto-complete
v-model:value="value"
class="global-search"
size="large"
style="width: 100%"
option-label-prop="title"
:options="dataSource"
@select="onSelect"
@search="handleSearch"
>
<template #option="item">
Found {{ item.query }} on
<a
:href="`https://s.taobao.com/search?q=${item.query}`"
target="_blank"
rel="noopener noreferrer"
>
{{ item.category }}
</a>
<span class="global-search-item-count">{{ item.count }} results</span>
</template>
<a-input-search size="large" placeholder="input here" enter-button></a-input-search>
</a-auto-complete>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
interface Option {
query: string;
category: string;
value: string;
count: number;
}
export default defineComponent({
setup() {
const value = ref('');
const dataSource = ref<Option[]>([]);
const onSelect = (value: string) => {
console.log('onSelect', value);
};
const getRandomInt = (max: number, min = 0) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
const searchResult = (query: string): Option[] => {
return new Array(getRandomInt(5))
.join('.')
.split('.')
.map((_item, idx) => ({
query,
category: `${query}${idx}`,
value: `${query}${idx}`,
count: getRandomInt(200, 100),
}));
};
const handleSearch = (val: string) => {
dataSource.value = val ? searchResult(val) : [];
};
return {
value,
dataSource,
onSelect,
handleSearch,
};
},
});
</script>
<style>
.global-search-wrapper {
padding-right: 50px;
}
.global-search {
width: 100%;
}
.global-search.ant-select-auto-complete .ant-select-selection--single {
margin-right: -46px;
}
.global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input:not(:last-child) {
padding-right: 62px;
}
.global-search.ant-select-auto-complete .ant-input-affix-wrapper .ant-input-suffix button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.global-search-item {
display: flex;
}
.global-search-item-desc {
flex: auto;
text-overflow: ellipsis;
overflow: hidden;
}
.global-search-item-count {
flex: none;
}
</style>

View File

@ -0,0 +1,56 @@
---
category: Components
type: Data Entry
cols: 2
title: AutoComplete
cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
---
Autocomplete function of input field.
## When To Use
When there is a need for autocomplete functionality.
## API
```html
<a-auto-complete v-model:value="value" :options="options" />
```
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| allowClear | Show clear button, effective in multiple mode only. | boolean | false | |
| autofocus | get focus when component mounted | boolean | false | |
| backfill | backfill selected item the input when using keyboard | boolean | false | |
| #default (for customize input element) | customize input element | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| options | Data source for autocomplete | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| option | custom render option by slot | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
| dropdownMenuStyle | additional style applied to dropdown menu | object | | 1.5.0 |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | |
| disabled | Whether disabled select | boolean | false | |
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded. | boolean or function(inputValue, option) | true | |
| optionLabelProp | Which prop value of option will render as content of select. | string | `children` | |
| placeholder | placeholder of input | string | - | |
| v-model:value | selected option | string\|string\[]\|{ key: string, label: string\|vNodes }\|Array&lt;{ key: string, label: string\|vNodes }> | - | |
| defaultOpen | Initial open state of dropdown | boolean | - | |
| open | Controlled open state of dropdown | boolean | - | |
### events
| Events Name | Description | Arguments | Version |
| --- | --- | --- | --- | --- |
| change | Called when select an option or input value change, or value of input is changed | function(value) | |
| blur | Called when leaving the component. | function() | |
| focus | Called when entering the component | function() | |
| search | Called when searching items. | function(value) | - | |
| select | Called when a option is selected. param is option's value and option instance. | function(value, option) | |
| dropdownVisibleChange | Call when dropdown open | function(open) | |
## Methods
| Name | Description | Version |
| ------- | ------------ | ------- |
| blur() | remove focus | |
| focus() | get focus | |

View File

@ -1,25 +1,24 @@
import type { App, Plugin, VNode, ExtractPropTypes } from 'vue';
import { defineComponent, inject, provide } from 'vue';
import Select, { SelectProps } from '../select';
import Input from '../input';
import { defineComponent, ref } from 'vue';
import Select, { selectProps } from '../select';
import PropTypes from '../_util/vue-types';
import { defaultConfigProvider } from '../config-provider';
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
import Omit from 'omit.js';
import { isValidElement, flattenChildren } from '../_util/props-util';
import warning from '../_util/warning';
import Option from './Option';
import OptGroup from './OptGroup';
import omit from '../_util/omit';
import useConfigInject from '../_util/hooks/useConfigInject';
function isSelectOptionOrSelectOptGroup(child: any): boolean {
return child?.type?.isSelectOption || child?.type?.isSelectOptGroup;
}
const autoCompleteProps = {
...SelectProps(),
...selectProps(),
dataSource: PropTypes.array,
dropdownMenuStyle: PropTypes.style,
optionLabelProp: PropTypes.string,
dropdownMatchSelectWidth: PropTypes.looseBool,
dropdownMatchSelectWidth: { type: [Number, Boolean], default: true },
};
export type AutoCompleteProps = Partial<ExtractPropTypes<typeof autoCompleteProps>>;
@ -44,107 +43,101 @@ const AutoComplete = defineComponent({
defaultActiveFirstOption: PropTypes.looseBool.def(true),
},
emits: ['change', 'select', 'focus', 'blur'],
slots: ['option'],
Option,
OptGroup,
setup(props, { slots }) {
setup(props, { slots, attrs, expose }) {
warning(
!(props.dataSource !== undefined || 'dataSource' in slots),
!('dataSource' in slots),
'AutoComplete',
'`dataSource` is deprecated, please use `options` instead.',
'`dataSource` slot is deprecated, please use props `options` instead.',
);
return {
configProvider: inject('configProvider', defaultConfigProvider),
popupRef: null,
select: null,
};
},
created() {
provide('savePopupRef', this.savePopupRef);
},
methods: {
savePopupRef(ref: VNode) {
this.popupRef = ref;
},
saveSelect(node: VNode) {
this.select = node;
},
getInputElement() {
const children = getSlot(this);
const element = children.length ? children[0] : <Input lazy={false} />;
warning(
!('options' in slots),
'AutoComplete',
'`options` slot is deprecated, please use props `options` instead.',
);
const selectRef = ref();
const getInputElement = () => {
const children = flattenChildren(slots.default?.());
const element = children.length ? children[0] : undefined;
return element;
},
focus() {
if (this.select) {
this.select.focus();
}
},
blur() {
if (this.select) {
this.select.blur();
}
},
},
render() {
const { size, prefixCls: customizePrefixCls, dataSource } = this;
let optionChildren: VNode[];
const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('select', customizePrefixCls);
const { class: className } = this.$attrs;
const cls = {
[className as string]: !!className,
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-show-search`]: true,
[`${prefixCls}-auto-complete`]: true,
};
let childArray = getSlot(this, 'dataSource');
if ('options' in this.$slots) {
childArray = getSlot(this, 'options');
}
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
optionChildren = childArray;
} else {
optionChildren = dataSource
? dataSource.map((item: any) => {
if (isValidElement(item)) {
return item;
}
switch (typeof item) {
case 'string':
return (
<Option key={item} value={item}>
{item}
</Option>
);
case 'object':
return (
<Option key={item.value} value={item.value}>
{item.text}
</Option>
);
default:
throw new Error(
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
);
}
})
: [];
}
const selectProps = {
...Omit(getOptionProps(this), ['dataSource', 'optionLabelProp']),
...this.$attrs,
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
// optionLabelProp,
getInputElement: this.getInputElement,
notFoundContent: getComponent(this, 'notFoundContent'),
// placeholder: '',
class: cls,
ref: this.saveSelect,
const focus = () => {
selectRef.value?.focus();
};
const blur = () => {
selectRef.value?.blur();
};
expose({
focus,
blur,
});
const { prefixCls } = useConfigInject('select', props);
return () => {
const { size, dataSource, notFoundContent = slots.notFoundContent?.() } = props;
let optionChildren: VNode[];
const { class: className } = attrs;
const cls = {
[className as string]: !!className,
[`${prefixCls.value}-lg`]: size === 'large',
[`${prefixCls.value}-sm`]: size === 'small',
[`${prefixCls.value}-show-search`]: true,
[`${prefixCls.value}-auto-complete`]: true,
};
if (props.options === undefined) {
const childArray = slots.dataSource?.() || slots.options?.() || [];
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
optionChildren = childArray;
} else {
optionChildren = dataSource
? dataSource.map((item: any) => {
if (isValidElement(item)) {
return item;
}
switch (typeof item) {
case 'string':
return (
<Option key={item} value={item}>
{item}
</Option>
);
case 'object':
return (
<Option key={item.value} value={item.value}>
{item.text}
</Option>
);
default:
throw new Error(
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
);
}
})
: [];
}
}
const selectProps = {
...omit(props, ['dataSource', 'optionLabelProp']),
...attrs,
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
// optionLabelProp,
getInputElement,
notFoundContent,
// placeholder: '',
class: cls,
ref: selectRef,
};
return (
<Select {...selectProps} v-slots={{ option: slots.option }}>
{optionChildren}
</Select>
);
};
return <Select {...selectProps}>{optionChildren}</Select>;
},
});

View File

@ -0,0 +1,63 @@
---
category: Components
subtitle: 自动完成
type: 数据录入
cols: 2
title: AutoComplete
cover: https://gw.alipayobjects.com/zos/alicdn/qtJm4yt45/AutoComplete.svg
---
输入框自动完成功能。
## 何时使用
- 需要一个输入框而不是选择器。
- 需要输入建议/辅助提示。
和 Select 的区别是:
- AutoComplete 是一个带提示的文本输入框,用户可以自由输入,关键词是辅助**输入**。
- Select 是在限定的可选项中进行选择,关键词是**选择**。
## API
```html
<a-auto-complete v-model:value="value" :options="options" />
```
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| allowClear | 支持清除, 单选模式有效 | boolean | false | |
| autofocus | 自动获取焦点 | boolean | false | |
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
| #default (自定义输入框) | 自定义输入框 | HTMLInputElement / HTMLTextAreaElement | `<Input />` | |
| options | 自动完成的数据源 | [DataSourceItemType](https://github.com/vueComponent/ant-design-vue/blob/724d53b907e577cf5880c1e6742d4c3f924f8f49/components/auto-complete/index.vue#L9)\[] | | |
| option | 通过 option 插槽,自定义节点 | v-slot:option="{value, label, [disabled, key, title]}" | - | 3.0 |
| dropdownMenuStyle | dropdown 菜单自定义样式 | object | | 1.5.0 |
| defaultActiveFirstOption | 是否默认高亮第一个选项。 | boolean | true | |
| disabled | 是否禁用 | boolean | false | |
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | |
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | boolean or function(inputValue, option) | true | |
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。 | string | `children` | |
| placeholder | 输入框提示 | string \| slot | - | |
| v-model:value | 指定当前选中的条目 | string\|string\[]\|{ key: string, label: string\|vNodes }\|Array&lt;{ key: string, label: string\|vNodes }> | 无 | |
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
| open | 是否展开下拉菜单 | boolean | - | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| --- | --- | --- | --- |
| change | 选中 option或 input 的 value 变化时,调用此函数 | function(value) |
| blur | 失去焦点时的回调 | function() |
| focus | 获得焦点时的回调 | function() |
| search | 搜索补全项的时候调用 | function(value) |
| select | 被选中时调用,参数为选中项的 value 值 | function(value, option) |
| dropdownVisibleChange | 展开下拉菜单的回调 | function(open) |
## 方法
| 名称 | 描述 | 版本 |
| ------- | -------- | ---- |
| blur() | 移除焦点 |
| focus() | 获取焦点 |

View File

@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
import { asyncExpect } from '@/tests/utils';
import { asyncExpect } from '../../../tests/utils';
import Avatar from '..';
import useBreakpoint from '../../_util/hooks/useBreakpoint';

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,50 @@
<docs>
---
order: 3
title:
zh-CN: 带徽标的头像
en-US: With Badge
---
## zh-CN
通常用于消息提示
## en-US
Usually used for reminders and notifications.
</docs>
<template>
<span style="margin-right: 24px">
<a-badge :count="1">
<a-avatar shape="square">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-badge>
</span>
<span>
<a-badge dot>
<a-avatar shape="square">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-badge>
</span>
</template>
<script lang="ts">
import { UserOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
UserOutlined,
},
});
</script>
<style>
#components-avatar-demo-badge .ant-avatar {
margin-top: 0;
margin-right: 0;
}
</style>

View File

@ -0,0 +1,54 @@
<docs>
---
order: 0
title:
zh-CN: 基本
en-US: Basic
---
## zh-CN
头像有三种尺寸两种形状可选
## en-US
Three sizes and two shapes are available.
</docs>
<template>
<a-avatar :size="64">
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar size="large">
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar>
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar size="small">
<template #icon><UserOutlined /></template>
</a-avatar>
<br />
<a-avatar shape="square" :size="64">
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar shape="square" size="large">
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar shape="square">
<template #icon><UserOutlined /></template>
</a-avatar>
<a-avatar shape="square" size="small">
<template #icon><UserOutlined /></template>
</a-avatar>
</template>
<script lang="ts">
import { UserOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
UserOutlined,
},
});
</script>

View File

@ -0,0 +1,56 @@
<docs>
---
order: 2
title:
zh-CN: 自动调整字符大小
en-US: Autoset Font Size
---
## zh-CN
对于字符型的头像当字符串较长时字体大小可以根据头像宽度自动调整
## en-US
For letter type Avatar, when the letters are too long to display, the font size can be automatically adjusted according to the width of the Avatar.
</docs>
<template>
<a-avatar
shape="square"
size="large"
:style="{ backgroundColor: color, verticalAlign: 'middle' }"
>
{{ avatarValue }}
</a-avatar>
<a-button
size="small"
:style="{ marginLeft: '16px', verticalAlign: 'middle' }"
@click="changeValue"
>
改变
</a-button>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
const UserList = ['U', 'Lucy', 'Tom', 'Edward'];
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
export default defineComponent({
setup() {
const avatarValue = ref(UserList[0]);
const color = ref(colorList[0]);
const changeValue = () => {
const index = UserList.indexOf(avatarValue.value);
avatarValue.value = index < UserList.length - 1 ? UserList[index + 1] : UserList[0];
color.value = index < colorList.length - 1 ? colorList[index + 1] : colorList[0];
};
return {
avatarValue,
color,
changeValue,
};
},
});
</script>

View File

@ -0,0 +1,74 @@
<docs>
---
order: 4
title:
zh-CN: Avatar.Group
en-US: Avatar.Group
---
## zh-CN
头像组合展现
## en-US
Avatar group display.
</docs>
<template>
<a-avatar-group>
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<a-avatar style="background-color: #f56a00">K</a-avatar>
<a-tooltip title="Ant User" placement="top">
<a-avatar style="background-color: #87d068">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-tooltip>
<a-avatar style="background-color: #1890ff">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-avatar-group>
<a-divider />
<a-avatar-group :max-count="2" :max-style="{ color: '#f56a00', backgroundColor: '#fde3cf' }">
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<a-avatar style="background-color: #1890ff">K</a-avatar>
<a-tooltip title="Ant User" placement="top">
<a-avatar style="background-color: #87d068">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-tooltip>
<a-avatar style="background-color: #1890ff">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-avatar-group>
<a-divider />
<a-avatar-group
:max-count="2"
size="large"
:max-style="{
color: '#f56a00',
backgroundColor: '#fde3cf',
}"
>
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<a-avatar style="background-color: #1890ff">K</a-avatar>
<a-tooltip title="Ant User" placement="top">
<a-avatar style="background-color: #87d068">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-tooltip>
<a-avatar style="background-color: #1890ff">
<template #icon><UserOutlined /></template>
</a-avatar>
</a-avatar-group>
</template>
<script lang="ts">
import { UserOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
UserOutlined,
},
});
</script>

View File

@ -0,0 +1,45 @@
<template>
<demo-sort>
<basic />
<type />
<dynamic />
<badge />
<group />
<responsive />
</demo-sort>
</template>
<script lang="ts">
import Basic from './basic.vue';
import Type from './type.vue';
import Dynamic from './dynamic.vue';
import Badge from './badge.vue';
import Group from './group.vue';
import Responsive from './responsive.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
export default defineComponent({
CN,
US,
components: {
Basic,
Type,
Dynamic,
Badge,
Group,
Responsive,
},
setup() {
return {};
},
});
</script>
<style>
[id^='components-avatar-demo-'] .ant-avatar {
margin-top: 16px;
margin-right: 16px;
}
</style>

View File

@ -0,0 +1,34 @@
<docs>
---
order: 5
title:
zh-CN: 响应式尺寸
en-US: Responsive Size
---
## zh-CN
头像大小可以根据屏幕大小自动调整
## en-US
Avatar size can be automatically adjusted based on the screen size.
</docs>
<template>
<a-avatar :size="{ xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 }">
<template #icon>
<AntDesignOutlined />
</template>
</a-avatar>
</template>
<script lang="ts">
import { AntDesignOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
AntDesignOutlined,
},
});
</script>

View File

@ -0,0 +1,43 @@
<docs>
---
order: 1
title:
zh-CN: 类型
en-US: Type
---
## zh-CN
支持三种类型图片Icon 以及字符其中 Icon 和字符型可以自定义图标颜色及背景色
## en-US
Image, Icon and letter are supported, and the latter two kinds avatar can have custom colors and background colors.
</docs>
<template>
<a-avatar>
<template #icon>
<UserOutlined />
</template>
</a-avatar>
<a-avatar>U</a-avatar>
<a-avatar>USER</a-avatar>
<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<a-avatar style="color: #f56a00; background-color: #fde3cf">U</a-avatar>
<a-avatar style="background-color: #87d068">
<template #icon>
<UserOutlined />
</template>
</a-avatar>
</template>
<script lang="ts">
import { UserOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
UserOutlined,
},
});
</script>

View File

@ -0,0 +1,33 @@
---
category: Components
type: Data Display
title: Avatar
cover: https://gw.alipayobjects.com/zos/antfincdn/aBcnbw68hP/Avatar.svg
---
Avatars can be used to represent people or objects. It supports images, `Icon`s, or letters.
## API
### Avatar
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| icon | the `Icon` type for an icon avatar, see `Icon` Component | VNode \| slot | - |
| shape | the shape of avatar | `circle` \| `square` | `circle` |
| size | The size of the avatar | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 2.2.0 |
| src | the address of the image for an image avatar | string | - |
| srcset | a list of sources to use for different screen resolutions | string | - |
| alt | This attribute defines the alternative text describing the image | string | - |
| gap | Letter type unit distance between left and right sides | number | 4 | 2.2.0 |
| draggable | Whether the picture is allowed to be dragged | boolean \| `'true'` \| `'false'` | - | 2.2.0 |
| loadError | handler when img load error, return false to prevent default fallback behavior | () => boolean | - |
### Avatar.Group (2.2.0)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| maxCount | Max avatars to show | number | - | |
| maxPopoverPlacement | The placement of excess avatar Popover | `top` \| `bottom` | `top` | |
| maxStyle | The style of excess avatar style | CSSProperties | - | |
| size | The size of the avatar | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | |

View File

@ -1,9 +1,9 @@
import type { App, Plugin } from 'vue';
import Avatar from './Avatar';
import Group from './Group';
export { AvatarProps, AvatarSize, avatarProps } from './Avatar';
export { AvatarGroupProps } from './Group';
export { avatarProps } from './Avatar';
export type { AvatarProps, AvatarSize } from './Avatar';
export type { AvatarGroupProps } from './Group';
Avatar.Group = Group;

View File

@ -0,0 +1,38 @@
---
category: Components
subtitle: 头像
type: 数据展示
title: Avatar
cover: https://gw.alipayobjects.com/zos/antfincdn/aBcnbw68hP/Avatar.svg
---
用来代表用户或事物,支持图片、图标或字符展示。
## 设计师专属
安装 [Kitchen Sketch 插件 💎](https://kitchen.alipay.com),一键填充高逼格头像和文本。
## API
### Avatar
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| icon | 设置头像的图标类型,可设为 Icon 的 `type` 或 VNode | VNode \| slot | - |
| shape | 指定头像的形状 | `circle` \| `square` | `circle` | |
| size | 设置头像的大小 | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | 2.2.0 |
| src | 图片类头像的资源地址 | string | - |
| srcset | 设置图片类头像响应式资源地址 | string | - |
| alt | 图像无法显示时的替代文本 | string | - |
| gap | 字符类型距离左右两侧边界单位像素 | number | 4 | 2.2.0 |
| draggable | 图片是否允许拖动 | boolean \| `'true'` \| `'false'` | - | 2.2.0 |
| loadError | 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 | () => boolean | - |
### Avatar.Group (2.2.0)
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| maxCount | 显示的最大头像个数 | number | - | |
| maxPopoverPlacement | 多余头像气泡弹出位置 | `top` \| `bottom` | `top` | |
| maxStyle | 多余头像样式 | CSSProperties | - | |
| size | 设置头像的大小 | number \| `large` \| `small` \| `default` \| { xs: number, sm: number, ...} | `default` | |

View File

@ -1,13 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./antdv-demo/docs/back-top/demo/basic.md correctly 1`] = `
<div>
<!----> Scroll down to see the bottom-right <strong style="color: rgba(64, 64, 64, 0.6);"> gray </strong> button.
</div>
`;
exports[`renders ./components/back-top/demo/basic.vue correctly 1`] = `<!----> Scroll down to see the bottom-right <strong style="color: rgba(64, 64, 64, 0.6);">gray</strong> button.`;
exports[`renders ./antdv-demo/docs/back-top/demo/custom.md correctly 1`] = `
exports[`renders ./components/back-top/demo/custom.vue correctly 1`] = `
<div id="components-back-top-demo-custom">
<!----> Scroll down to see the bottom-right <strong style="color: rgb(16, 136, 233);"> blue </strong> button.
<!----> Scroll down to see the bottom-right <strong style="color: rgb(16, 136, 233);">blue</strong> button.
</div>
`;

View File

@ -0,0 +1,23 @@
<docs>
---
order: 0
title:
zh-CN: 基本使用
en-US: Basic Usage
---
## zh-CN
最简单的用法
## en-US
The simplest usage.
</docs>
<template>
<a-back-top />
Scroll down to see the bottom-right
<strong style="color: rgba(64, 64, 64, 0.6)">gray</strong>
button.
</template>

View File

@ -0,0 +1,43 @@
<docs>
---
order: 1
title:
zh-CN: 自定义样式
en-US: Custom style
---
## zh-CN
可以自定义回到顶部按钮的样式限制宽高`40px * 40px`
## en-US
You can customize the style of the button, just note the size limit: no more than `40px * 40px`.
</docs>
<template>
<div id="components-back-top-demo-custom">
<a-back-top>
<div class="ant-back-top-inner">UP</div>
</a-back-top>
Scroll down to see the bottom-right
<strong style="color: #1088e9">blue</strong>
button.
</div>
</template>
<style scoped>
#components-back-top-demo-custom .ant-back-top {
bottom: 100px;
}
#components-back-top-demo-custom .ant-back-top-inner {
height: 40px;
width: 40px;
line-height: 40px;
border-radius: 4px;
background-color: #1088e9;
color: #fff;
text-align: center;
font-size: 20px;
}
</style>

View File

@ -0,0 +1,27 @@
<template>
<demo-sort>
<basic />
<custom />
</demo-sort>
</template>
<script lang="ts">
import Basic from './basic.vue';
import Custom from './custom.vue';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
import { defineComponent } from 'vue';
export default defineComponent({
CN,
US,
components: {
Basic,
Custom,
},
setup() {
return {};
},
});
</script>

Some files were not shown because too many files have changed in this diff Show More