mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 03:58:05 +08:00
refactor: breadcrumb button by ts
This commit is contained in:
parent
1503364d6b
commit
d7426e11d4
@ -1,10 +1,17 @@
|
||||
import { inject, cloneVNode } from 'vue';
|
||||
import { inject, cloneVNode, defineComponent, PropType } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { filterEmpty, getComponent, getSlot } from '../_util/props-util';
|
||||
import warning from '../_util/warning';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import Menu from '../menu';
|
||||
import { Omit, VueNode } from '../_util/type';
|
||||
|
||||
export interface Route {
|
||||
path: string;
|
||||
breadcrumbName: string;
|
||||
children?: Omit<Route, 'children'>[];
|
||||
}
|
||||
|
||||
const Route = PropTypes.shape({
|
||||
path: PropTypes.string,
|
||||
@ -14,13 +21,20 @@ const Route = PropTypes.shape({
|
||||
|
||||
const BreadcrumbProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
routes: PropTypes.arrayOf(Route),
|
||||
routes: {type: Array as PropType<Route[]>},
|
||||
params: PropTypes.any,
|
||||
separator: PropTypes.any,
|
||||
itemRender: PropTypes.func,
|
||||
separator: PropTypes.VNodeChild,
|
||||
itemRender: {
|
||||
type: Function as PropType<(
|
||||
route: Route,
|
||||
params: any,
|
||||
routes: Array<Route>,
|
||||
paths: Array<string>,
|
||||
) => VueNode>
|
||||
},
|
||||
};
|
||||
|
||||
function getBreadcrumbName(route, params) {
|
||||
function getBreadcrumbName(route: Route, params: any) {
|
||||
if (!route.breadcrumbName) {
|
||||
return null;
|
||||
}
|
||||
@ -31,8 +45,14 @@ function getBreadcrumbName(route, params) {
|
||||
);
|
||||
return name;
|
||||
}
|
||||
function defaultItemRender(opt: {route: Route, params: any, routes: Route[], paths: string[]}): VueNode {
|
||||
const { route, params, routes, paths } = opt
|
||||
const isLastItem = routes.indexOf(route) === routes.length - 1;
|
||||
const name = getBreadcrumbName(route, params);
|
||||
return isLastItem ? <span>{name}</span> : <a href={`#/${paths.join('/')}`}>{name}</a>;
|
||||
}
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'ABreadcrumb',
|
||||
props: BreadcrumbProps,
|
||||
setup() {
|
||||
@ -41,12 +61,7 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
defaultItemRender({ route, params, routes, paths }) {
|
||||
const isLastItem = routes.indexOf(route) === routes.length - 1;
|
||||
const name = getBreadcrumbName(route, params);
|
||||
return isLastItem ? <span>{name}</span> : <a href={`#/${paths.join('/')}`}>{name}</a>;
|
||||
},
|
||||
getPath(path, params) {
|
||||
getPath(path: string, params: any) {
|
||||
path = (path || '').replace(/^\//, '');
|
||||
Object.keys(params).forEach(key => {
|
||||
path = path.replace(`:${key}`, params[key]);
|
||||
@ -54,7 +69,7 @@ export default {
|
||||
return path;
|
||||
},
|
||||
|
||||
addChildPath(paths, childPath, params) {
|
||||
addChildPath(paths: string[], childPath: string = '', params: any) {
|
||||
const originalPaths = [...paths];
|
||||
const path = this.getPath(childPath, params);
|
||||
if (path) {
|
||||
@ -63,9 +78,9 @@ export default {
|
||||
return originalPaths;
|
||||
},
|
||||
|
||||
genForRoutes({ routes = [], params = {}, separator, itemRender = this.defaultItemRender }) {
|
||||
genForRoutes({ routes = [], params = {}, separator, itemRender = defaultItemRender }: any) {
|
||||
const paths = [];
|
||||
return routes.map(route => {
|
||||
return routes.map((route: Route) => {
|
||||
const path = this.getPath(route.path, params);
|
||||
|
||||
if (path) {
|
||||
@ -104,14 +119,14 @@ export default {
|
||||
},
|
||||
},
|
||||
render() {
|
||||
let crumbs;
|
||||
let crumbs: VueNode[];
|
||||
const { prefixCls: customizePrefixCls, routes, params = {}, $slots } = this;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
|
||||
const children = filterEmpty(getSlot(this));
|
||||
const separator = getComponent(this, 'separator');
|
||||
const itemRender = this.itemRender || $slots.itemRender || this.defaultItemRender;
|
||||
const itemRender = this.itemRender || $slots.itemRender || defaultItemRender;
|
||||
if (routes && routes.length > 0) {
|
||||
// generated by route
|
||||
crumbs = this.genForRoutes({
|
||||
@ -133,4 +148,4 @@ export default {
|
||||
}
|
||||
return <div class={prefixCls}>{crumbs}</div>;
|
||||
},
|
||||
};
|
||||
});
|
@ -1,18 +1,18 @@
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { hasProp, getComponent, getSlot } from '../_util/props-util';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import DropDown from '../dropdown/dropdown';
|
||||
import DownOutlined from '@ant-design/icons-vue/DownOutlined';
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'ABreadcrumbItem',
|
||||
__ANT_BREADCRUMB_ITEM: true,
|
||||
props: {
|
||||
prefixCls: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
separator: PropTypes.any.def('/'),
|
||||
overlay: PropTypes.any,
|
||||
separator: PropTypes.VNodeChild.def('/'),
|
||||
overlay: PropTypes.VNodeChild,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
@ -24,7 +24,7 @@ export default {
|
||||
* if overlay is have
|
||||
* Wrap a DropDown
|
||||
*/
|
||||
renderBreadcrumbNode(breadcrumbItem, prefixCls) {
|
||||
renderBreadcrumbNode(breadcrumbItem: any, prefixCls: string) {
|
||||
const overlay = getComponent(this, 'overlay');
|
||||
if (overlay) {
|
||||
return (
|
||||
@ -65,4 +65,4 @@ export default {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
});
|
@ -1,9 +1,9 @@
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { getSlot } from '../_util/props-util';
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'ABreadcrumbSeparator',
|
||||
__ANT_BREADCRUMB_SEPARATOR: true,
|
||||
props: {
|
||||
@ -22,4 +22,4 @@ export default {
|
||||
const children = getSlot(this);
|
||||
return <span class={`${prefixCls}-separator`}>{children || '/'}</span>;
|
||||
},
|
||||
};
|
||||
});
|
@ -1,3 +1,4 @@
|
||||
import { App } from 'vue';
|
||||
import Breadcrumb from './Breadcrumb';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
@ -6,7 +7,7 @@ Breadcrumb.Item = BreadcrumbItem;
|
||||
Breadcrumb.Separator = BreadcrumbSeparator;
|
||||
|
||||
/* istanbul ignore next */
|
||||
Breadcrumb.install = function(app) {
|
||||
Breadcrumb.install = function(app: App) {
|
||||
app.component(Breadcrumb.name, Breadcrumb);
|
||||
app.component(BreadcrumbItem.name, BreadcrumbItem);
|
||||
app.component(BreadcrumbSeparator.name, BreadcrumbSeparator);
|
@ -1,18 +1,15 @@
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { filterEmpty, getSlot } from '../_util/props-util';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
const ButtonGroupProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
size: {
|
||||
validator(value) {
|
||||
return ['small', 'large', 'default'].includes(value);
|
||||
},
|
||||
},
|
||||
size: PropTypes.oneOf(tuple('small', 'large', 'default')),
|
||||
};
|
||||
export { ButtonGroupProps };
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'AButtonGroup',
|
||||
props: ButtonGroupProps,
|
||||
setup() {
|
||||
@ -53,4 +50,4 @@ export default {
|
||||
};
|
||||
return <div class={classes}>{filterEmpty(getSlot(this))}</div>;
|
||||
},
|
||||
};
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { inject, Text } from 'vue';
|
||||
import { defineComponent, inject, Text, VNode } from 'vue';
|
||||
import Wave from '../_util/wave';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import buttonTypes from './buttonTypes';
|
||||
@ -8,7 +8,7 @@ import { defaultConfigProvider } from '../config-provider';
|
||||
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
|
||||
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
|
||||
const props = buttonTypes();
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'AButton',
|
||||
inheritAttrs: false,
|
||||
__ANT_BUTTON: true,
|
||||
@ -16,11 +16,12 @@ export default {
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', defaultConfigProvider),
|
||||
children: [],
|
||||
iconCom: undefined,
|
||||
delayTimeout: undefined
|
||||
};
|
||||
},
|
||||
data() {
|
||||
this.children = [];
|
||||
this.iconCom = undefined;
|
||||
return {
|
||||
sizeMap: {
|
||||
large: 'lg',
|
||||
@ -67,7 +68,7 @@ export default {
|
||||
ghost,
|
||||
block,
|
||||
$attrs,
|
||||
} = this;
|
||||
} = this
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('btn', customizePrefixCls);
|
||||
const autoInsertSpace = this.configProvider.autoInsertSpaceInButton !== false;
|
||||
@ -87,7 +88,7 @@ export default {
|
||||
}
|
||||
const iconType = sLoading ? 'loading' : this.iconCom;
|
||||
return {
|
||||
[$attrs.class]: $attrs.class,
|
||||
[$attrs.class as string]: $attrs.class,
|
||||
[`${prefixCls}`]: true,
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
[`${prefixCls}-${shape}`]: shape,
|
||||
@ -101,7 +102,7 @@ export default {
|
||||
},
|
||||
fixTwoCNChar() {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
const node = this.$refs.buttonNode;
|
||||
const node = this.$refs.buttonNode as HTMLElement;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
@ -114,17 +115,17 @@ export default {
|
||||
this.hasTwoCNChar = false;
|
||||
}
|
||||
},
|
||||
handleClick(event) {
|
||||
handleClick(event: Event) {
|
||||
const { sLoading } = this.$data;
|
||||
if (sLoading) {
|
||||
return;
|
||||
}
|
||||
this.$emit('click', event);
|
||||
},
|
||||
insertSpace(child, needInserted) {
|
||||
insertSpace(child: VNode, needInserted: boolean) {
|
||||
const SPACE = needInserted ? ' ' : '';
|
||||
if (child.type === Text) {
|
||||
let text = child.children.trim();
|
||||
let text = (child.children as string).trim();
|
||||
if (isTwoCNChar(text)) {
|
||||
text = text.split('').join(SPACE);
|
||||
}
|
||||
@ -179,4 +180,4 @@ export default {
|
||||
|
||||
return <Wave ref="wave">{buttonNode}</Wave>;
|
||||
},
|
||||
};
|
||||
});
|
@ -1,15 +0,0 @@
|
||||
import PropTypes, { withUndefined } from '../_util/vue-types';
|
||||
export default () => ({
|
||||
prefixCls: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']).def('button'),
|
||||
// icon: PropTypes.string,
|
||||
shape: PropTypes.oneOf(['circle', 'circle-outline', 'round']),
|
||||
size: PropTypes.oneOf(['small', 'large', 'default']).def('default'),
|
||||
loading: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.object])),
|
||||
disabled: PropTypes.looseBool,
|
||||
ghost: PropTypes.looseBool,
|
||||
block: PropTypes.looseBool,
|
||||
icon: PropTypes.any,
|
||||
onClick: PropTypes.func,
|
||||
});
|
26
components/button/buttonTypes.ts
Normal file
26
components/button/buttonTypes.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { tuple } from '../_util/type';
|
||||
import PropTypes, { withUndefined } from '../_util/vue-types';
|
||||
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'danger', 'link');
|
||||
export type ButtonType = typeof ButtonTypes[number];
|
||||
const ButtonShapes = tuple('circle', 'circle-outline', 'round');
|
||||
export type ButtonShape = typeof ButtonShapes[number];
|
||||
const ButtonSizes = tuple('large', 'default', 'small');
|
||||
export type ButtonSize = typeof ButtonSizes[number];
|
||||
const ButtonHTMLTypes = tuple('submit', 'button', 'reset');
|
||||
export type ButtonHTMLType = typeof ButtonHTMLTypes[number];
|
||||
|
||||
export default () => ({
|
||||
prefixCls: PropTypes.string,
|
||||
type: PropTypes.oneOf(ButtonTypes),
|
||||
htmlType: PropTypes.oneOf(ButtonHTMLTypes).def('button'),
|
||||
// icon: PropTypes.string,
|
||||
shape: PropTypes.oneOf(ButtonShapes),
|
||||
size: PropTypes.oneOf(ButtonSizes).def('default'),
|
||||
loading: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.object])),
|
||||
disabled: PropTypes.looseBool,
|
||||
ghost: PropTypes.looseBool,
|
||||
block: PropTypes.looseBool,
|
||||
icon: PropTypes.VNodeChild,
|
||||
onClick: PropTypes.func,
|
||||
});
|
@ -1,10 +1,11 @@
|
||||
import { App } from 'vue';
|
||||
import Button from './button';
|
||||
import ButtonGroup from './button-group';
|
||||
|
||||
Button.Group = ButtonGroup;
|
||||
|
||||
/* istanbul ignore next */
|
||||
Button.install = function(app) {
|
||||
Button.install = function(app: App) {
|
||||
app.component(Button.name, Button);
|
||||
app.component(ButtonGroup.name, ButtonGroup);
|
||||
};
|
@ -142,7 +142,7 @@ const ConfigProvider = defineComponent({
|
||||
|
||||
const renderProvider = (legacyLocale: Locale) => {
|
||||
return (
|
||||
<LocaleProvider locale={props.locale || legacyLocale} _ANT_MARK__={ANT_MARK}>
|
||||
<LocaleProvider locale={props.locale || legacyLocale} ANT_MARK__={ANT_MARK}>
|
||||
{slots.default?.()}
|
||||
</LocaleProvider>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { provide, inject, cloneVNode } from 'vue';
|
||||
import { provide, inject, cloneVNode, defineComponent } from 'vue';
|
||||
import RcDropdown from '../vc-dropdown/src/index';
|
||||
import DropdownButton from './dropdown-button';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
@ -16,7 +16,7 @@ import { defaultConfigProvider } from '../config-provider';
|
||||
import RightOutlined from '@ant-design/icons-vue/RightOutlined';
|
||||
|
||||
const DropdownProps = getDropdownProps();
|
||||
const Dropdown = {
|
||||
const Dropdown = defineComponent({
|
||||
name: 'ADropdown',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
@ -107,7 +107,7 @@ const Dropdown = {
|
||||
};
|
||||
return <RcDropdown {...dropdownProps}>{dropdownTrigger}</RcDropdown>;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Dropdown.Button = DropdownButton;
|
||||
export default Dropdown;
|
||||
|
@ -22,7 +22,7 @@ export interface Locale {
|
||||
export interface LocaleProviderProps {
|
||||
locale: Locale;
|
||||
children?: VNode | VNode[];
|
||||
_ANT_MARK__?: string;
|
||||
ANT_MARK__?: string;
|
||||
}
|
||||
|
||||
export const ANT_MARK = 'internalMark';
|
||||
@ -41,11 +41,11 @@ const LocaleProvider = defineComponent({
|
||||
locale: {
|
||||
type: Object,
|
||||
},
|
||||
_ANT_MARK__: PropTypes.string,
|
||||
ANT_MARK__: PropTypes.string,
|
||||
},
|
||||
data() {
|
||||
warning(
|
||||
this._ANT_MARK__ === ANT_MARK,
|
||||
this.ANT_MARK__ === ANT_MARK,
|
||||
'LocaleProvider',
|
||||
'`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead',
|
||||
);
|
||||
@ -58,7 +58,7 @@ const LocaleProvider = defineComponent({
|
||||
},
|
||||
setup(props) {
|
||||
warning(
|
||||
props._ANT_MARK__ === ANT_MARK,
|
||||
props.ANT_MARK__ === ANT_MARK,
|
||||
'LocaleProvider',
|
||||
'`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead',
|
||||
);
|
||||
@ -67,7 +67,7 @@ const LocaleProvider = defineComponent({
|
||||
...props.locale,
|
||||
exist: true,
|
||||
},
|
||||
_ANT_MARK__: ANT_MARK,
|
||||
ANT_MARK__: ANT_MARK,
|
||||
};
|
||||
provide('localeData', data);
|
||||
return data;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { Item, itemProps } from '../vc-menu';
|
||||
import { getOptionProps, getSlot } from '../_util/props-util';
|
||||
import Tooltip from '../tooltip';
|
||||
function noop() {}
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'MenuItem',
|
||||
inheritAttrs: false,
|
||||
props: itemProps,
|
||||
@ -56,4 +56,4 @@ export default {
|
||||
const item = <Item {...itemProps}>{children}</Item>;
|
||||
return <Tooltip {...toolTipProps}>{item}</Tooltip>;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { inject, provide, toRef } from 'vue';
|
||||
import { defineComponent, inject, provide, toRef } from 'vue';
|
||||
import omit from 'omit.js';
|
||||
import VcMenu, { Divider, ItemGroup } from '../vc-menu';
|
||||
import SubMenu from './SubMenu';
|
||||
@ -47,7 +47,7 @@ export const menuProps = {
|
||||
'onUpdate:openKeys': PropTypes.func,
|
||||
};
|
||||
|
||||
const Menu = {
|
||||
const Menu = defineComponent({
|
||||
name: 'AMenu',
|
||||
inheritAttrs: false,
|
||||
props: menuProps,
|
||||
@ -294,7 +294,7 @@ const Menu = {
|
||||
|
||||
return <VcMenu {...menuProps} class={menuClassName} />;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
Menu.install = function(app) {
|
||||
|
Loading…
Reference in New Issue
Block a user