fix: use open, remove visible

pull/6293/head^2
tangjinzhou 2023-02-23 11:58:23 +08:00
parent 1b51e6ffb3
commit 37b5d02b6d
27 changed files with 232 additions and 204 deletions

4
.gitignore vendored
View File

@ -59,6 +59,7 @@ jspm_packages/
dist dist
lib lib
es es
/locale
_site _site
yarn.lock yarn.lock
package-lock.json package-lock.json
@ -78,5 +79,8 @@ report.html
site/src/router/demoRoutes.js site/src/router/demoRoutes.js
components/version/version.ts
components/version/version.tsx components/version/version.tsx
components/version/token.json
components/version/token-meta.json
~component-api.json ~component-api.json

View File

@ -1,4 +1,4 @@
// import hash from '@emotion/hash'; import hash from '@emotion/hash';
import type * as CSS from 'csstype'; import type * as CSS from 'csstype';
// @ts-ignore // @ts-ignore
import unitless from '@emotion/unitless'; import unitless from '@emotion/unitless';
@ -10,22 +10,22 @@ import type { Linter } from '../linters';
import { contentQuotesLinter, hashedAnimationLinter } from '../linters'; import { contentQuotesLinter, hashedAnimationLinter } from '../linters';
import type { HashPriority } from '../StyleContext'; import type { HashPriority } from '../StyleContext';
import { import {
// useStyleInject, useStyleInject,
// ATTR_DEV_CACHE_PATH, ATTR_DEV_CACHE_PATH,
ATTR_MARK, ATTR_MARK,
ATTR_TOKEN, ATTR_TOKEN,
// CSS_IN_JS_INSTANCE, CSS_IN_JS_INSTANCE,
// CSS_IN_JS_INSTANCE_ID, CSS_IN_JS_INSTANCE_ID,
} from '../StyleContext'; } from '../StyleContext';
import { supportLayer } from '../util'; import { supportLayer } from '../util';
// import useGlobalCache from './useGlobalCache'; import useGlobalCache from './useGlobalCache';
// import canUseDom from '../../canUseDom'; import canUseDom from '../../canUseDom';
// import { removeCSS, updateCSS } from '../../../vc-util/Dom/dynamicCSS'; import { removeCSS, updateCSS } from '../../../vc-util/Dom/dynamicCSS';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
// import { computed } from 'vue'; import { computed } from 'vue';
import type { VueNode } from '../../type'; import type { VueNode } from '../../type';
// const isClientSide = canUseDom(); const isClientSide = canUseDom();
const SKIP_CHECK = '_skip_check_'; const SKIP_CHECK = '_skip_check_';
@ -275,9 +275,9 @@ export const parseStyle = (
// ============================================================================ // ============================================================================
// == Register == // == Register ==
// ============================================================================ // ============================================================================
// function uniqueHash(path: (string | number)[], styleStr: string) { function uniqueHash(path: (string | number)[], styleStr: string) {
// return hash(`${path.join('%')}${styleStr}`); return hash(`${path.join('%')}${styleStr}`);
// } }
// function Empty() { // function Empty() {
// return null; // return null;
@ -287,90 +287,88 @@ export const parseStyle = (
* Register a style to the global style sheet. * Register a style to the global style sheet.
*/ */
export default function useStyleRegister( export default function useStyleRegister(
// eslint-disable-next-line @typescript-eslint/no-unused-vars info: Ref<{
_info: Ref<{
theme: Theme<any, any>; theme: Theme<any, any>;
token: any; token: any;
path: string[]; path: string[];
hashId?: string; hashId?: string;
layer?: string; layer?: string;
}>, }>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars styleFn: () => CSSInterpolation,
_styleFn: () => CSSInterpolation,
) { ) {
// const styleContext = useStyleInject(); const styleContext = useStyleInject();
// const tokenKey = computed(() => info.value.token._tokenKey as string); const tokenKey = computed(() => info.value.token._tokenKey as string);
// const fullPath = computed(() => [tokenKey.value, ...info.value.path]); const fullPath = computed(() => [tokenKey.value, ...info.value.path]);
// Check if need insert style // Check if need insert style
// let isMergedClientSide = isClientSide; let isMergedClientSide = isClientSide;
// if (process.env.NODE_ENV !== 'production' && styleContext.mock !== undefined) { if (process.env.NODE_ENV !== 'production' && styleContext.mock !== undefined) {
// isMergedClientSide = styleContext.mock === 'client'; isMergedClientSide = styleContext.mock === 'client';
// } }
// const [cacheStyle[0], cacheStyle[1], cacheStyle[2]] // const [cacheStyle[0], cacheStyle[1], cacheStyle[2]]
// const cacheStyle = useGlobalCache( useGlobalCache(
// 'style', 'style',
// fullPath, fullPath,
// // Create cache if needed // Create cache if needed
// () => { () => {
// const styleObj = styleFn(); const styleObj = styleFn();
// const { hashPriority, container, transformers, linters } = styleContext; const { hashPriority, container, transformers, linters } = styleContext;
// const { path, hashId, layer } = info.value; const { path, hashId, layer } = info.value;
// const [parsedStyle, effectStyle] = parseStyle(styleObj, { const [parsedStyle, effectStyle] = parseStyle(styleObj, {
// hashId, hashId,
// hashPriority, hashPriority,
// layer, layer,
// path: path.join('-'), path: path.join('-'),
// transformers, transformers,
// linters, linters,
// }); });
// const styleStr = normalizeStyle(parsedStyle); const styleStr = normalizeStyle(parsedStyle);
// const styleId = uniqueHash(fullPath.value, styleStr); const styleId = uniqueHash(fullPath.value, styleStr);
// if (isMergedClientSide) { if (isMergedClientSide) {
// const style = updateCSS(styleStr, styleId, { const style = updateCSS(styleStr, styleId, {
// mark: ATTR_MARK, mark: ATTR_MARK,
// prepend: 'queue', prepend: 'queue',
// attachTo: container, attachTo: container,
// }); });
// (style as any)[CSS_IN_JS_INSTANCE] = CSS_IN_JS_INSTANCE_ID; (style as any)[CSS_IN_JS_INSTANCE] = CSS_IN_JS_INSTANCE_ID;
// // Used for `useCacheToken` to remove on batch when token removed // Used for `useCacheToken` to remove on batch when token removed
// style.setAttribute(ATTR_TOKEN, tokenKey.value); style.setAttribute(ATTR_TOKEN, tokenKey.value);
// // Dev usage to find which cache path made this easily // Dev usage to find which cache path made this easily
// if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
// style.setAttribute(ATTR_DEV_CACHE_PATH, fullPath.value.join('|')); style.setAttribute(ATTR_DEV_CACHE_PATH, fullPath.value.join('|'));
// } }
// // Inject client side effect style // Inject client side effect style
// Object.keys(effectStyle).forEach(effectKey => { Object.keys(effectStyle).forEach(effectKey => {
// if (!globalEffectStyleKeys.has(effectKey)) { if (!globalEffectStyleKeys.has(effectKey)) {
// globalEffectStyleKeys.add(effectKey); globalEffectStyleKeys.add(effectKey);
// // Inject // Inject
// updateCSS(normalizeStyle(effectStyle[effectKey]), `_effect-${effectKey}`, { updateCSS(normalizeStyle(effectStyle[effectKey]), `_effect-${effectKey}`, {
// mark: ATTR_MARK, mark: ATTR_MARK,
// prepend: 'queue', prepend: 'queue',
// attachTo: container, attachTo: container,
// }); });
// } }
// }); });
// } }
// return [styleStr, tokenKey.value, styleId]; return [styleStr, tokenKey.value, styleId];
// }, },
// // Remove cache if no need // Remove cache if no need
// ([, , styleId], fromHMR) => { ([, , styleId], fromHMR) => {
// if ((fromHMR || styleContext.autoClear) && isClientSide) { if ((fromHMR || styleContext.autoClear) && isClientSide) {
// removeCSS(styleId, { mark: ATTR_MARK }); removeCSS(styleId, { mark: ATTR_MARK });
// } }
// }, },
// ); );
return (node: VueNode) => { return (node: VueNode) => {
return node; return node;

View File

@ -111,15 +111,15 @@ const Affix = defineComponent({
status: AffixStatus.None, status: AffixStatus.None,
} as AffixState; } as AffixState;
const targetRect = getTargetRect(targetNode); const targetRect = getTargetRect(targetNode);
const placeholderReact = getTargetRect(placeholderNode.value as HTMLElement); const placeholderRect = getTargetRect(placeholderNode.value as HTMLElement);
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop.value); const fixedTop = getFixedTop(placeholderRect, targetRect, offsetTop.value);
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom.value); const fixedBottom = getFixedBottom(placeholderRect, targetRect, offsetBottom.value);
if ( if (
placeholderReact.top === 0 && placeholderRect.top === 0 &&
placeholderReact.left === 0 && placeholderRect.left === 0 &&
placeholderReact.width === 0 && placeholderRect.width === 0 &&
placeholderReact.height === 0 placeholderRect.height === 0
) { ) {
return; return;
} }

View File

@ -226,7 +226,7 @@ Components which support rtl direction are listed here, you can toggle the direc
<a-divider orientation="left">Modal example</a-divider> <a-divider orientation="left">Modal example</a-divider>
<div> <div>
<a-button type="primary" @click="showModal">Open Modal</a-button> <a-button type="primary" @click="showModal">Open Modal</a-button>
<a-modal v-model:visible="state.modalVisible" title="پنچره ساده"> <a-modal v-model:open="state.modalVisible" title="پنچره ساده">
<p>نگاشتههای خود را اینجا قراردهید</p> <p>نگاشتههای خود را اینجا قراردهید</p>
<p>نگاشتههای خود را اینجا قراردهید</p> <p>نگاشتههای خود را اینجا قراردهید</p>
<p>نگاشتههای خود را اینجا قراردهید</p> <p>نگاشتههای خود را اینجا قراردهید</p>

View File

@ -54,7 +54,7 @@ Components which need localization support are listed here, you can toggle the l
<div class="example"> <div class="example">
<a-table :data-source="[]" :columns="columns" /> <a-table :data-source="[]" :columns="columns" />
</div> </div>
<a-modal v-model:visible="visible" title="Locale Modal"> <a-modal v-model:open="visible" title="Locale Modal">
<p>Locale Modal</p> <p>Locale Modal</p>
</a-modal> </a-modal>
</div> </div>

View File

@ -29,6 +29,10 @@ import type { InputStatus } from '../../_util/statusUtils';
const DataPickerPlacements = ['bottomLeft', 'bottomRight', 'topLeft', 'topRight'] as const; const DataPickerPlacements = ['bottomLeft', 'bottomRight', 'topLeft', 'topRight'] as const;
type DataPickerPlacement = (typeof DataPickerPlacements)[number]; type DataPickerPlacement = (typeof DataPickerPlacements)[number];
type RangeShowTimeObject<DateType> = Omit<SharedTimeProps<DateType>, 'defaultValue'> & {
defaultValue?: DateType[];
};
function commonProps<DateType = any>() { function commonProps<DateType = any>() {
return { return {
id: String, id: String,
@ -205,6 +209,7 @@ function rangePickerProps<DateType>() {
format: String, format: String,
renderExtraFooter: functionType<() => VueNode>(), renderExtraFooter: functionType<() => VueNode>(),
separator: { type: String }, separator: { type: String },
showTime: someType<boolean | RangeShowTimeObject<DateType>>([Boolean, Object]),
ranges: ranges:
objectType< objectType<
Record< Record<
@ -250,6 +255,7 @@ export interface RangePickerProps<DateType> {
format?: string; format?: string;
renderExtraFooter?: () => VueNode; renderExtraFooter?: () => VueNode;
separator?: string; separator?: string;
showTime?: boolean | RangeShowTimeObject<DateType>;
ranges?: Record< ranges?: Record<
string, string,
Exclude<RangeValue<DateType>, null> | (() => Exclude<RangeValue<DateType>, null>) Exclude<RangeValue<DateType>, null> | (() => Exclude<RangeValue<DateType>, null>)

View File

@ -17,7 +17,7 @@ The default is to close the menu when you click on menu items, this feature can
</docs> </docs>
<template> <template>
<a-dropdown v-model:visible="visible"> <a-dropdown v-model:open="visible">
<a class="ant-dropdown-link" @click.prevent> <a class="ant-dropdown-link" @click.prevent>
Hover me Hover me
<DownOutlined /> <DownOutlined />

View File

@ -1,7 +1,7 @@
import { useInjectFormItemPrefix } from './context'; import { useInjectFormItemPrefix } from './context';
import type { VueNode } from '../_util/type'; import type { VueNode } from '../_util/type';
import { computed, defineComponent, ref, Transition, watch } from 'vue'; import { computed, defineComponent, ref, Transition, watch, TransitionGroup } from 'vue';
import { getTransitionGroupProps, getTransitionProps, TransitionGroup } from '../_util/transition'; import { getTransitionGroupProps, getTransitionProps } from '../_util/transition';
import collapseMotion from '../_util/collapseMotion'; import collapseMotion from '../_util/collapseMotion';
import useStyle from './style'; import useStyle from './style';
@ -37,19 +37,15 @@ export default defineComponent({
`${prefixCls.value}-show-help-item`, `${prefixCls.value}-show-help-item`,
colMItem, colMItem,
); );
(transitionGroupProps as any).role = 'alert';
(transitionGroupProps as any).class = [hashId.value, baseClassName.value, attrs.class];
return ( return (
<Transition <Transition
{...getTransitionProps(`${prefixCls.value}-show-help`)} {...getTransitionProps(`${prefixCls.value}-show-help`)}
onAfterEnter={() => props.onErrorVisibleChanged(true)} onAfterEnter={() => props.onErrorVisibleChanged(true)}
onAfterLeave={() => props.onErrorVisibleChanged(false)} onAfterLeave={() => props.onErrorVisibleChanged(false)}
> >
<TransitionGroup <TransitionGroup {...transitionGroupProps} tag="div" v-show={!!props.errors?.length}>
{...transitionGroupProps}
tag="div"
role="alert"
v-show={!!props.errors?.length}
class={[hashId.value, baseClassName.value, attrs.class]}
>
{props.errors?.map((error: any, index: number) => ( {props.errors?.map((error: any, index: number) => (
<div <div
key={index} key={index}

View File

@ -52,7 +52,7 @@ In this case, submit button is in the Modal which is out of Form. You can use `f
<a-button html-type="button" style="margin: 0 8px" @click="visible = true">Add User</a-button> <a-button html-type="button" style="margin: 0 8px" @click="visible = true">Add User</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
<a-modal v-model:visible="visible" title="Basic Drawer" @ok="onOk"> <a-modal v-model:open="visible" title="Basic Drawer" @ok="onOk">
<a-form ref="modalFormRef" :model="modalFormState" layout="vertical" name="userForm"> <a-form ref="modalFormRef" :model="modalFormState" layout="vertical" name="userForm">
<a-form-item name="name" label="User Name" :rules="[{ required: true }]"> <a-form-item name="name" label="User Name" :rules="[{ required: true }]">
<a-input v-model:value="modalFormState.name" /> <a-input v-model:value="modalFormState.name" />

View File

@ -19,7 +19,7 @@ When user visit a page with a list of items, and want to create a new item. The
<div> <div>
<a-button type="primary" @click="visible = true">New Collection</a-button> <a-button type="primary" @click="visible = true">New Collection</a-button>
<a-modal <a-modal
v-model:visible="visible" v-model:open="visible"
title="Create a new collection" title="Create a new collection"
ok-text="Create" ok-text="Create"
cancel-text="Cancel" cancel-text="Cancel"

View File

@ -36,7 +36,7 @@ Set label width by labelCol.style
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<a-form-item label="Activity form"> <a-form-item label="Activity form">
<a-input v-model:value="formState.desc" type="textarea" /> <a-textarea v-model:value="formState.desc" />
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> <a-form-item :wrapper-col="{ span: 14, offset: 4 }">
<a-button type="primary" @click="onSubmit">Create</a-button> <a-button type="primary" @click="onSubmit">Create</a-button>

View File

@ -44,21 +44,41 @@ Use the single file method to recursively generate menus.
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue'; import { defineComponent, ref, PropType } from 'vue';
import { import {
MenuFoldOutlined, MenuFoldOutlined,
MenuUnfoldOutlined, MenuUnfoldOutlined,
PieChartOutlined, PieChartOutlined,
MailOutlined, MailOutlined,
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
const list = [
{
key: '1',
title: 'Option 1',
},
{
key: '2',
title: 'Navigation 2',
children: [
{
key: '2.1',
title: 'Navigation 3',
children: [{ key: '2.1.1', title: 'Option 2.1.1' }],
},
],
},
];
// you can rewrite it to a single file component, if not, you should config vue alias to vue/dist/vue.esm-bundler.js // you can rewrite it to a single file component, if not, you should config vue alias to vue/dist/vue.esm-bundler.js
const SubMenu = { const SubMenu = defineComponent({
name: 'SubMenu', name: 'SubMenu',
components: {
PieChartOutlined,
MailOutlined,
},
props: { props: {
menuInfo: { menuInfo: {
type: Object, type: Object as PropType<(typeof list)[number]>,
default: () => ({}), default: () => ({} as (typeof list)[number]),
}, },
}, },
template: ` template: `
@ -80,28 +100,8 @@ const SubMenu = {
</template> </template>
</a-sub-menu> </a-sub-menu>
`, `,
components: { });
PieChartOutlined,
MailOutlined,
},
};
const list = [
{
key: '1',
title: 'Option 1',
},
{
key: '2',
title: 'Navigation 2',
children: [
{
key: '2.1',
title: 'Navigation 3',
children: [{ key: '2.1.1', title: 'Option 2.1.1' }],
},
],
},
];
export default defineComponent({ export default defineComponent({
components: { components: {
'sub-menu': SubMenu, 'sub-menu': SubMenu,

View File

@ -198,7 +198,7 @@ export default defineComponent({
tooltipProps.title = null; tooltipProps.title = null;
// Reset `visible` to fix control mode tooltip display not correct // Reset `visible` to fix control mode tooltip display not correct
// ref: https://github.com/ant-design/ant-design/issues/16742 // ref: https://github.com/ant-design/ant-design/issues/16742
tooltipProps.visible = false; tooltipProps.open = false;
} }
// ============================ Render ============================ // ============================ Render ============================

View File

@ -20,10 +20,10 @@ Make it pop up under some conditions.
<div> <div>
<a-popconfirm <a-popconfirm
title="Are you sure delete this task?" title="Are you sure delete this task?"
:visible="visible" :open="visible"
ok-text="Yes" ok-text="Yes"
cancel-text="No" cancel-text="No"
@visibleChange="handleVisibleChange" @openChange="handleVisibleChange"
@confirm="confirm" @confirm="confirm"
@cancel="cancel" @cancel="cancel"
> >

View File

@ -21,6 +21,7 @@ import omit from '../_util/omit';
import { tooltipDefaultProps } from '../tooltip/Tooltip'; import { tooltipDefaultProps } from '../tooltip/Tooltip';
import ActionButton from '../_util/ActionButton'; import ActionButton from '../_util/ActionButton';
import usePopconfirmStyle from './style'; import usePopconfirmStyle from './style';
import warning from '../_util/warning';
export const popconfirmProps = () => ({ export const popconfirmProps = () => ({
...abstractTooltipProps(), ...abstractTooltipProps(),
@ -67,6 +68,11 @@ const Popconfirm = defineComponent({
// emits: ['update:open', 'visibleChange'], // emits: ['update:open', 'visibleChange'],
setup(props: PopconfirmProps, { slots, emit, expose, attrs }) { setup(props: PopconfirmProps, { slots, emit, expose, attrs }) {
const rootRef = ref(); const rootRef = ref();
warning(
props.visible === undefined,
'Popconfirm',
`\`visible\` will be removed in next major version, please use \`open\` instead.`,
);
expose({ expose({
getPopupDomNode: () => { getPopupDomNode: () => {
return rootRef.value?.getPopupDomNode?.(); return rootRef.value?.getPopupDomNode?.();

View File

@ -16,7 +16,7 @@ Use `visible` prop to control the display of the card.
</docs> </docs>
<template> <template>
<a-popover v-model:visible="visible" title="Title" trigger="click"> <a-popover v-model:open="visible" title="Title" trigger="click">
<template #content> <template #content>
<a @click="hide">Close</a> <a @click="hide">Close</a>
</template> </template>

View File

@ -20,18 +20,13 @@ The following example shows how to create a popover which can be hovered and cli
style="width: 500px" style="width: 500px"
title="Hover title" title="Hover title"
trigger="hover" trigger="hover"
:visible="hovered" :open="hovered"
@visibleChange="handleHoverChange" @openChange="handleHoverChange"
> >
<template #content> <template #content>
<div>This is hover content.</div> <div>This is hover content.</div>
</template> </template>
<a-popover <a-popover title="Click title" trigger="click" :open="clicked" @openChange="handleClickChange">
title="Click title"
trigger="click"
:visible="clicked"
@visibleChange="handleClickChange"
>
<template #content> <template #content>
<div> <div>
<div>This is click content.</div> <div>This is click content.</div>

View File

@ -10,6 +10,7 @@ import { getTransitionName } from '../_util/transition';
import { tooltipDefaultProps } from '../tooltip/Tooltip'; import { tooltipDefaultProps } from '../tooltip/Tooltip';
import useStyle from './style'; import useStyle from './style';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import warning from '../_util/warning';
export const popoverProps = () => ({ export const popoverProps = () => ({
...abstractTooltipProps(), ...abstractTooltipProps(),
@ -33,7 +34,11 @@ const Popover = defineComponent({
}), }),
setup(props, { expose, slots, attrs }) { setup(props, { expose, slots, attrs }) {
const tooltipRef = ref(); const tooltipRef = ref();
warning(
props.visible === undefined,
'popover',
`\`visible\` will be removed in next major version, please use \`open\` instead.`,
);
expose({ expose({
getPopupDomNode: () => { getPopupDomNode: () => {
return tooltipRef.value?.getPopupDomNode?.(); return tooltipRef.value?.getPopupDomNode?.();

View File

@ -5,7 +5,7 @@ import useConfigInject from '../../config-provider/hooks/useConfigInject';
import { initDefaultProps } from '../../_util/props-util'; import { initDefaultProps } from '../../_util/props-util';
import useStyle from '../style'; import useStyle from '../style';
import type { VueNode } from '../../_util/type'; import type { VueNode } from '../../_util/type';
import { someType, arrayType, booleanType, stringType } from '../../_util/type'; import { functionType, someType, arrayType, booleanType, stringType } from '../../_util/type';
import type { ChangeEvent } from '../../_util/EventInterface'; import type { ChangeEvent } from '../../_util/EventInterface';
import MotionThumb from './MotionThumb'; import MotionThumb from './MotionThumb';
export type SegmentedValue = string | number; export type SegmentedValue = string | number;
@ -46,14 +46,29 @@ export const segmentedProps = () => {
size: stringType<segmentedSize>(), size: stringType<segmentedSize>(),
value: { ...someType<SegmentedValue>([String, Number]), required: true }, value: { ...someType<SegmentedValue>([String, Number]), required: true },
motionName: String, motionName: String,
onChange: functionType<(val: SegmentedValue) => void>(),
'onUpdate:value': functionType<(val: SegmentedValue) => void>(),
}; };
}; };
export type SegmentedProps = Partial<ExtractPropTypes<ReturnType<typeof segmentedProps>>>; export type SegmentedProps = Partial<ExtractPropTypes<ReturnType<typeof segmentedProps>>>;
const SegmentedOption: FunctionalComponent< const SegmentedOption: FunctionalComponent<
SegmentedOption & { prefixCls: string; checked: boolean } SegmentedOption & {
> = (props, { slots, emit, attrs }) => { prefixCls: string;
const { value, disabled, payload, title, prefixCls, label = slots.label, checked } = props; checked: boolean;
onChange: (_event: ChangeEvent, val: SegmentedValue) => void;
}
> = (props, { slots, emit }) => {
const {
value,
disabled,
payload,
title,
prefixCls,
label = slots.label,
checked,
className,
} = props;
const handleChange = (event: InputEvent) => { const handleChange = (event: InputEvent) => {
if (disabled) { if (disabled) {
return; return;
@ -68,7 +83,7 @@ const SegmentedOption: FunctionalComponent<
{ {
[`${prefixCls}-item-disabled`]: disabled, [`${prefixCls}-item-disabled`]: disabled,
}, },
attrs.class, className,
)} )}
> >
<input <input
@ -100,7 +115,6 @@ export default defineComponent({
options: [], options: [],
motionName: 'thumb-motion', motionName: 'thumb-motion',
}), }),
emits: ['change', 'update:value'],
slots: ['label'], slots: ['label'],
setup(props, { emit, slots, attrs }) { setup(props, { emit, slots, attrs }) {
const { prefixCls, direction, size } = useConfigInject('segmented', props); const { prefixCls, direction, size } = useConfigInject('segmented', props);
@ -154,13 +168,13 @@ export default defineComponent({
<SegmentedOption <SegmentedOption
key={segmentedOption.value} key={segmentedOption.value}
prefixCls={pre} prefixCls={pre}
class={classNames(segmentedOption.className, `${pre}-item`, {
[`${pre}-item-selected`]:
segmentedOption.value === props.value && !thumbShow.value,
})}
checked={segmentedOption.value === props.value} checked={segmentedOption.value === props.value}
onChange={handleChange} onChange={handleChange}
{...segmentedOption} {...segmentedOption}
className={classNames(segmentedOption.className, `${pre}-item`, {
[`${pre}-item-selected`]:
segmentedOption.value === props.value && !thumbShow.value,
})}
disabled={!!props.disabled || !!segmentedOption.disabled} disabled={!!props.disabled || !!segmentedOption.disabled}
v-slots={slots} v-slots={slots}
/> />

View File

@ -18,7 +18,7 @@ Wrap
<template> <template>
<a-space :size="[8, 16]" wrap> <a-space :size="[8, 16]" wrap>
<template v-for="index in 20" :key="index"> <template v-for="_i in 20" :key="_i">
<a-button>Button</a-button> <a-button>Button</a-button>
</template> </template>
</a-space> </a-space>

View File

@ -160,9 +160,9 @@ export default defineComponent({
<Dropdown <Dropdown
prefixCls={dropdownPrefix} prefixCls={dropdownPrefix}
trigger={['hover']} trigger={['hover']}
open={open.value} visible={open.value}
transitionName={moreTransitionName} transitionName={moreTransitionName}
onOpenChange={setOpen} onVisibleChange={setOpen}
overlayClassName={overlayClassName} overlayClassName={overlayClassName}
mouseEnterDelay={0.1} mouseEnterDelay={0.1}
mouseLeaveDelay={0.1} mouseLeaveDelay={0.1}

View File

@ -5,20 +5,20 @@ import mountTest from '../../../tests/shared/mountTest';
describe('Tooltip', () => { describe('Tooltip', () => {
mountTest(Tooltip); mountTest(Tooltip);
it('check `onVisibleChange` arguments', async () => { it('check `onOpenChange` arguments', async () => {
const onVisibleChange = jest.fn(); const onOpenChange = jest.fn();
const wrapper = mount( const wrapper = mount(
{ {
props: ['title', 'visible'], props: ['title', 'open'],
render() { render() {
const props = { const props = {
title: this.title || '', title: this.title || '',
mouseEnterDelay: 0, mouseEnterDelay: 0,
mouseLeaveDelay: 0, mouseLeaveDelay: 0,
onVisibleChange, onOpenChange,
}; };
if (this.visible !== undefined) { if (this.open !== undefined) {
props.visible = this.visible; props.open = this.open;
} }
return ( return (
<Tooltip ref="tooltip" {...props}> <Tooltip ref="tooltip" {...props}>
@ -38,15 +38,15 @@ describe('Tooltip', () => {
div.dispatchEvent(new MouseEvent('mouseenter')); div.dispatchEvent(new MouseEvent('mouseenter'));
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange).not.toHaveBeenCalled(); expect(onOpenChange).not.toHaveBeenCalled();
expect(wrapper.vm.$refs.tooltip.visible).toBe(false); expect(wrapper.vm.$refs.tooltip.open).toBe(false);
}); });
await asyncExpect(() => { await asyncExpect(() => {
div.dispatchEvent(new MouseEvent('mouseleave')); div.dispatchEvent(new MouseEvent('mouseleave'));
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange).not.toHaveBeenCalled(); expect(onOpenChange).not.toHaveBeenCalled();
expect(wrapper.vm.$refs.tooltip.visible).toBe(false); expect(wrapper.vm.$refs.tooltip.open).toBe(false);
}); });
await asyncExpect(() => { await asyncExpect(() => {
// update `title` value. // update `title` value.
@ -56,35 +56,35 @@ describe('Tooltip', () => {
document.getElementById('hello').dispatchEvent(new MouseEvent('mouseenter')); document.getElementById('hello').dispatchEvent(new MouseEvent('mouseenter'));
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange).toHaveBeenLastCalledWith(true); expect(onOpenChange).toHaveBeenLastCalledWith(true);
expect(wrapper.vm.$refs.tooltip.visible).toBe(true); expect(wrapper.vm.$refs.tooltip.open).toBe(true);
}, 0); }, 0);
await asyncExpect(() => { await asyncExpect(() => {
document.getElementById('hello').dispatchEvent(new MouseEvent('mouseleave')); document.getElementById('hello').dispatchEvent(new MouseEvent('mouseleave'));
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange).toHaveBeenLastCalledWith(false); expect(onOpenChange).toHaveBeenLastCalledWith(false);
expect(wrapper.vm.$refs.tooltip.visible).toBe(false); expect(wrapper.vm.$refs.tooltip.open).toBe(false);
}); });
await asyncExpect(() => { await asyncExpect(() => {
// add `visible` props. // add `open` props.
wrapper.setProps({ visible: false }); wrapper.setProps({ open: false });
}); });
await asyncExpect(() => { await asyncExpect(() => {
document.getElementById('hello').dispatchEvent(new MouseEvent('mouseenter')); document.getElementById('hello').dispatchEvent(new MouseEvent('mouseenter'));
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange).toHaveBeenLastCalledWith(true); expect(onOpenChange).toHaveBeenLastCalledWith(true);
expect(wrapper.vm.$refs.tooltip.visible).toBe(false); expect(wrapper.vm.$refs.tooltip.open).toBe(false);
}); });
await asyncExpect(() => { await asyncExpect(() => {
// always trigger onVisibleChange // always trigger onOpenChange
document.getElementById('hello').dispatchEvent(new MouseEvent('mouseleave')); document.getElementById('hello').dispatchEvent(new MouseEvent('mouseleave'));
lastCount = onVisibleChange.mock.calls.length; lastCount = onOpenChange.mock.calls.length;
}); });
await asyncExpect(() => { await asyncExpect(() => {
expect(onVisibleChange.mock.calls.length).toBe(lastCount); // no change with lastCount expect(onOpenChange.mock.calls.length).toBe(lastCount); // no change with lastCount
expect(wrapper.vm.$refs.tooltip.visible).toBe(false); expect(wrapper.vm.$refs.tooltip.open).toBe(false);
}); });
}); });
}); });

View File

@ -28,7 +28,7 @@ After users upload picture, the thumbnail will be shown in list. The upload butt
<div style="margin-top: 8px">Upload</div> <div style="margin-top: 8px">Upload</div>
</div> </div>
</a-upload> </a-upload>
<a-modal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel"> <a-modal :open="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" /> <img alt="example" style="width: 100%" :src="previewImage" />
</a-modal> </a-modal>
</div> </div>

View File

@ -2,6 +2,7 @@ import type { ExtractPropTypes, PropType } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import type { SizeType } from '../config-provider'; import type { SizeType } from '../config-provider';
import type { VueNode } from '../_util/type'; import type { VueNode } from '../_util/type';
import { stringType } from '../_util/type';
import type { import type {
ChangeEventHandler, ChangeEventHandler,
CompositionEventHandler, CompositionEventHandler,
@ -54,33 +55,30 @@ export const inputProps = () => ({
type: [String, Number] as PropType<string | number>, type: [String, Number] as PropType<string | number>,
}, },
autocomplete: String, autocomplete: String,
type: { type: stringType<
type: String as PropType< | 'button'
| 'button' | 'checkbox'
| 'checkbox' | 'color'
| 'color' | 'date'
| 'date' | 'datetime-local'
| 'datetime-local' | 'email'
| 'email' | 'file'
| 'file' | 'hidden'
| 'hidden' | 'image'
| 'image' | 'month'
| 'month' | 'number'
| 'number' | 'password'
| 'password' | 'radio'
| 'radio' | 'range'
| 'range' | 'reset'
| 'reset' | 'search'
| 'search' | 'submit'
| 'submit' | 'tel'
| 'tel' | 'text'
| 'text' | 'time'
| 'time' | 'url'
| 'url' | 'week'
| 'week' >('text'),
>,
default: 'text',
},
name: String, name: String,
size: { type: String as PropType<SizeType> }, size: { type: String as PropType<SizeType> },
autofocus: { type: Boolean, default: undefined }, autofocus: { type: Boolean, default: undefined },

View File

@ -22,7 +22,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<a-modal v-model:visible="visible" title="成为赞助商" @ok="visible = false"> <a-modal v-model:open="visible" title="成为赞助商" @ok="visible = false">
如果您有品牌推广活动推广招聘推广社区合作等需求欢迎联系我们成为赞助商 如果您有品牌推广活动推广招聘推广社区合作等需求欢迎联系我们成为赞助商
<br /> <br />
您的广告将出现在 And Design Vue 文档所有子页面及 GitHub Readme 等页面 您的广告将出现在 And Design Vue 文档所有子页面及 GitHub Readme 等页面

View File

@ -389,6 +389,12 @@ export default {
type: 'Layout', type: 'Layout',
title: 'Space', title: 'Space',
}, },
segmented: {
category: 'Components',
subtitle: '分段控制器',
type: 'Data Display',
title: 'Segmented',
},
// colorPicker: { // colorPicker: {
// category: 'Components', // category: 'Components',
// subtitle: '取色器', // subtitle: '取色器',

View File

@ -23,7 +23,7 @@
<CloseOutlined class="close-icon" @click="visibleAlertBanner = false" /> <CloseOutlined class="close-icon" @click="visibleAlertBanner = false" />
</div> </div>
<a-popover <a-popover
v-model:visible="menuVisible" v-model:open="menuVisible"
overlay-class-name="popover-menu" overlay-class-name="popover-menu"
placement="bottomRight" placement="bottomRight"
trigger="click" trigger="click"