Commit 80f3cfdd authored by Sendya's avatar Sendya

Merge branch 'dev/next/lint-check' into next

# Conflicts:
#	src/FooterToolbar/index.tsx
#	src/ProProvider/index.tsx
#	src/hooks/context/index.ts
parents e1885393 1dc50f77
...@@ -11,7 +11,8 @@ module.exports = { ...@@ -11,7 +11,8 @@ module.exports = {
'@vue/prettier/@typescript-eslint', '@vue/prettier/@typescript-eslint',
], ],
parserOptions: { parserOptions: {
ecmaVersion: 2020, // ecmaVersion: 2020,
parser: '@typescript-eslint/parser',
}, },
rules: { rules: {
'@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-explicit-any': 0,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"scripts": { "scripts": {
"clean": "cross-env TS_NODE_PROJECT=scripts/tsconfig.json node -r ts-node/register ./scripts/cleanup.ts", "clean": "cross-env TS_NODE_PROJECT=scripts/tsconfig.json node -r ts-node/register ./scripts/cleanup.ts",
"start": "vc-tools run server", "start": "vc-tools run server",
"lint": "eslint src/ --ext .tsx,.ts", "lint": "eslint src/ -c .eslintrc.js --ext .tsx,.ts",
"compile": "vc-tools run compile", "compile": "vc-tools run compile",
"test": "cross-env NODE_ENV=test jest --config .jest.js", "test": "cross-env NODE_ENV=test jest --config .jest.js",
"prepublishOnly": "npm run lint && npm run generate && npm run compile && npm run test", "prepublishOnly": "npm run lint && npm run generate && npm run compile && npm run test",
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
"vue": ">=3.0.0" "vue": ">=3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@ant-design-vue/tools": "^3.0.2", "@ant-design-vue/tools": "^3.0.3",
"@babel/runtime": "^7.11.2", "@babel/runtime": "^7.11.2",
"@types/fs-extra": "^9.0.2", "@types/fs-extra": "^9.0.2",
"@types/jest": "^24.0.17", "@types/jest": "^24.0.17",
...@@ -44,9 +44,7 @@ ...@@ -44,9 +44,7 @@
"@vue/eslint-config-prettier": "^6.0.0", "@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^5.0.2", "@vue/eslint-config-typescript": "^5.0.2",
"@vue/test-utils": "^2.0.0-beta.2", "@vue/test-utils": "^2.0.0-beta.2",
"babel-loader": "^8.1.0",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"css-loader": "^5.0.0",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-config-prettier": "^6.4.0", "eslint-config-prettier": "^6.4.0",
"eslint-plugin-prettier": "^3.1.3", "eslint-plugin-prettier": "^3.1.3",
...@@ -54,10 +52,7 @@ ...@@ -54,10 +52,7 @@
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"jest": "^25.4.0", "jest": "^25.4.0",
"jest-serializer-vue": "^2.0.2", "jest-serializer-vue": "^2.0.2",
"less-loader": "^7.0.2",
"postcss-loader": "^4.0.4",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"ts-loader": "^8.0.6",
"ts-node": "^8.10.2", "ts-node": "^8.10.2",
"typescript": "~3.9.3", "typescript": "~3.9.3",
"vue": "^3.0.0-0", "vue": "^3.0.0-0",
......
...@@ -8,7 +8,7 @@ import { default as ProProvider } from './ProProvider'; ...@@ -8,7 +8,7 @@ import { default as ProProvider } from './ProProvider';
import { createRouteContext } from './RouteContext'; import { createRouteContext } from './RouteContext';
import SiderMenuWrapper from './SiderMenu'; import SiderMenuWrapper from './SiderMenu';
const defaultI18nRender = (key: string) => key const defaultI18nRender = (key: string) => key;
const { state, provider: RouteContextProvider } = createRouteContext({ const { state, provider: RouteContextProvider } = createRouteContext({
isMobile: false, isMobile: false,
...@@ -16,18 +16,18 @@ const { state, provider: RouteContextProvider } = createRouteContext({ ...@@ -16,18 +16,18 @@ const { state, provider: RouteContextProvider } = createRouteContext({
sideWidth: 208, sideWidth: 208,
hasSideMenu: true, hasSideMenu: true,
hasHeader: true, hasHeader: true,
}) });
const BasicLayout = (props, { emit, slots }) => { const BasicLayout = (props, { emit, slots }) => {
const handleClick = () => { const handleClick = () => {
emit('update:collapsed', !props.collapsed) emit('update:collapsed', !props.collapsed);
} };
const handleOpenChange = (openKeys): void => { const handleOpenChange = (openKeys): void => {
emit('update:openKeys', openKeys) emit('update:openKeys', openKeys);
} };
const handleSelect = (selectedKeys: string[]): void => { const handleSelect = (selectedKeys: string[]): void => {
emit('update:selectedKeys', selectedKeys) emit('update:selectedKeys', selectedKeys);
} };
return ( return (
<ProProvider {...props} i18n={defaultI18nRender}> <ProProvider {...props} i18n={defaultI18nRender}>
<RouteContextProvider> <RouteContextProvider>
...@@ -35,24 +35,31 @@ const BasicLayout = (props, { emit, slots }) => { ...@@ -35,24 +35,31 @@ const BasicLayout = (props, { emit, slots }) => {
<SiderMenuWrapper {...props} /> <SiderMenuWrapper {...props} />
<Layout> <Layout>
<Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;"> <Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;">
{ {props.collapsed ? (
props.collapsed <MenuUnfoldOutlined class="trigger" onClick={handleClick} />
? <MenuUnfoldOutlined class="trigger" onClick={handleClick} /> ) : (
: <MenuFoldOutlined class="trigger" onClick={handleClick} /> <MenuFoldOutlined class="trigger" onClick={handleClick} />
} )}
</Layout.Header> </Layout.Header>
<Layout.Content style={{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }}> <Layout.Content
style={{
margin: '24px 16px',
padding: '24px',
background: '#fff',
minHeight: '280px',
}}
>
{slots.default && slots.default()} {slots.default && slots.default()}
</Layout.Content> </Layout.Content>
</Layout> </Layout>
</Layout> </Layout>
</RouteContextProvider> </RouteContextProvider>
</ProProvider> </ProProvider>
) );
}; };
BasicLayout.install = function (app: App) { BasicLayout.install = function(app: App) {
app.component('pro-layout', BasicLayout) app.component('pro-layout', BasicLayout);
}; };
export default BasicLayout export default BasicLayout;
...@@ -4,13 +4,13 @@ import { WithFalse } from '../typings'; ...@@ -4,13 +4,13 @@ import { WithFalse } from '../typings';
import { defineComponent, PropType, SetupContext, VNodeChild } from 'vue'; import { defineComponent, PropType, SetupContext, VNodeChild } from 'vue';
export type Links = WithFalse< export type Links = WithFalse<
{ {
key?: string; key?: string;
title: VNodeChild | JSX.Element; title: VNodeChild | JSX.Element;
href: string; href: string;
blankTarget?: boolean; blankTarget?: boolean;
}[] }[]
> >;
export interface GlobalFooterProps { export interface GlobalFooterProps {
links?: Links; links?: Links;
...@@ -25,12 +25,14 @@ export default defineComponent({ ...@@ -25,12 +25,14 @@ export default defineComponent({
copyright: [Object, Function] as PropType<VNodeChild | JSX.Element>, copyright: [Object, Function] as PropType<VNodeChild | JSX.Element>,
prefixCls: { prefixCls: {
type: String, type: String,
default: 'ant-pro' default: 'ant-pro',
} },
}, },
setup (props: GlobalFooterProps, { slots }: SetupContext) { setup(props: GlobalFooterProps, { slots }: SetupContext) {
if ( if (
(props.links == null || props.links === false || (Array.isArray(props.links) && props.links.length === 0)) && (props.links == null ||
props.links === false ||
(Array.isArray(props.links) && props.links.length === 0)) &&
(props.copyright == null || props.copyright === false) (props.copyright == null || props.copyright === false)
) { ) {
return null; return null;
...@@ -58,5 +60,5 @@ export default defineComponent({ ...@@ -58,5 +60,5 @@ export default defineComponent({
{props.copyright && <div class={`${baseClassName}-copyright`}>{copyright}</div>} {props.copyright && <div class={`${baseClassName}-copyright`}>{copyright}</div>}
</footer> </footer>
); );
} },
}); });
import './GridContent.less'; import './GridContent.less';
import { SetupContext, CSSProperties } from 'vue' import { SetupContext, CSSProperties } from 'vue';
import { PureSettings } from '../defaultSettings'; import { PureSettings } from '../defaultSettings';
interface GridContentProps { interface GridContentProps {
...@@ -9,7 +9,10 @@ interface GridContentProps { ...@@ -9,7 +9,10 @@ interface GridContentProps {
style?: CSSProperties; style?: CSSProperties;
} }
const GridContent = ({ prefixCls = 'ant-pro', contentWidth }: GridContentProps, { slots }: SetupContext) => { const GridContent = (
{ prefixCls = 'ant-pro', contentWidth }: GridContentProps,
{ slots }: SetupContext,
) => {
return ( return (
<div <div
class={{ class={{
......
...@@ -16,9 +16,9 @@ export const defaultProProviderProps: ProProviderData = { ...@@ -16,9 +16,9 @@ export const defaultProProviderProps: ProProviderData = {
}, },
i18n: (t: string): string => t, i18n: (t: string): string => t,
contentWidth: 'Fluid', contentWidth: 'Fluid',
} };
export const injectProConfigKey: InjectionKey<ProProviderData> = Symbol() export const injectProConfigKey: InjectionKey<ProProviderData> = Symbol();
const ProProvider = defineComponent({ const ProProvider = defineComponent({
name: 'ProProvider', name: 'ProProvider',
...@@ -36,26 +36,26 @@ const ProProvider = defineComponent({ ...@@ -36,26 +36,26 @@ const ProProvider = defineComponent({
default: (t: string): string => t, default: (t: string): string => t,
}, },
}, },
setup (props, { slots }: SetupContext) { setup(props, { slots }: SetupContext) {
const { prefixCls, i18n, contentWidth } = toRefs(props) const { prefixCls, i18n, contentWidth } = toRefs(props);
const getPrefixCls = (suffixCls?: string, customizePrefixCls?: string): string => { const getPrefixCls = (suffixCls?: string, customizePrefixCls?: string): string => {
if (customizePrefixCls) return customizePrefixCls; if (customizePrefixCls) return customizePrefixCls;
return suffixCls ? `${prefixCls.value}-${suffixCls}` : prefixCls.value; return suffixCls ? `${prefixCls.value}-${suffixCls}` : prefixCls.value;
} };
const proConfigProvider = reactive({ const proConfigProvider = reactive({
i18n, i18n,
contentWidth, contentWidth,
getPrefixCls, getPrefixCls,
}) });
provide(injectProConfigKey, proConfigProvider) provide(injectProConfigKey, proConfigProvider);
return () => slots.default && slots.default() return () => slots.default && slots.default();
}, },
}) });
ProProvider.install = function (app: App) { ProProvider.install = function(app: App) {
app.component(ProProvider.name, ProProvider) app.component(ProProvider.name, ProProvider);
} };
export default ProProvider export default ProProvider;
import './index.less'; import './index.less';
import { defineComponent, h, resolveDynamicComponent, resolveComponent, VNode, ref, reactive, computed, Ref, watch, ComputedRef, VNodeChild, WatchStopHandle, PropType, isVNode, toRefs, defineAsyncComponent, Component } from 'vue'; import {
defineComponent,
h,
ref,
reactive,
computed,
Ref,
watch,
ComputedRef,
VNodeChild,
VNode,
WatchStopHandle,
PropType,
isVNode,
toRefs,
} from 'vue';
// import * as Icon from '@ant-design/icons-vue'; // import * as Icon from '@ant-design/icons-vue';
import { createFromIconfontCN } from '@ant-design/icons-vue'; import { createFromIconfontCN } from '@ant-design/icons-vue';
...@@ -10,11 +25,11 @@ import { createFromIconfontCN } from '@ant-design/icons-vue'; ...@@ -10,11 +25,11 @@ import { createFromIconfontCN } from '@ant-design/icons-vue';
import { Menu } from 'ant-design-vue'; import { Menu } from 'ant-design-vue';
import defaultSettings, { PureSettings } from '../defaultSettings'; import defaultSettings, { PureSettings } from '../defaultSettings';
import { isImg, isUrl } from '../utils' import { isImg, isUrl } from '../utils';
import { MenuMode, SelectInfo, OpenEventHandler } from './typings'; import { MenuMode, SelectInfo, OpenEventHandler } from './typings';
import { RouteProps, MenuTheme, WithFalse } from '../typings'; import { RouteProps, MenuTheme, WithFalse } from '../typings';
export { MenuMode, SelectInfo, OpenEventHandler } export { MenuMode, SelectInfo, OpenEventHandler };
export interface MenuState { export interface MenuState {
collapsed?: boolean | false; collapsed?: boolean | false;
...@@ -33,31 +48,38 @@ export interface MenuStateWatched { ...@@ -33,31 +48,38 @@ export interface MenuStateWatched {
watchRef: WatchStopHandle; watchRef: WatchStopHandle;
} }
export function useMenuState ({ collapsed = false, openKeys = [] as string[], selectedKeys = [] as string[], }: MenuState): MenuStateWatched { export function useMenuState({
collapsed = false,
openKeys = [] as string[],
selectedKeys = [] as string[],
}: MenuState): MenuStateWatched {
const state = reactive<MenuStated>({ const state = reactive<MenuStated>({
collapsed, collapsed,
selectedKeys, selectedKeys,
openKeys, openKeys,
}) });
const cachedOpenKeys: Ref<string[]> = ref([] as string[]) const cachedOpenKeys: Ref<string[]> = ref([] as string[]);
const watchRef = watch(() => state.collapsed, (collapsed) => { const watchRef = watch(
() => state.collapsed,
collapsed => {
if (collapsed) { if (collapsed) {
cachedOpenKeys.value = state.openKeys.concat() cachedOpenKeys.value = state.openKeys.concat();
state.openKeys = [] state.openKeys = [];
} else { } else {
state.openKeys = cachedOpenKeys.value.concat() state.openKeys = cachedOpenKeys.value.concat();
} }
}) },
);
return { return {
state, state,
watchRef, watchRef,
} };
} }
export function useRootSubmenuKeys (menus: RouteProps[]): ComputedRef<string[]> { export function useRootSubmenuKeys(menus: RouteProps[]): ComputedRef<string[]> {
return computed(() => menus.map(it => it.path)) return computed(() => menus.map(it => it.path));
} }
// ts typo // ts typo
...@@ -86,7 +108,7 @@ export const VueBaseMenuProps = { ...@@ -86,7 +108,7 @@ export const VueBaseMenuProps = {
default: 'inline', default: 'inline',
}, },
theme: { theme: {
type: String as PropType<MenuTheme | 'realDark'>, type: String as PropType<MenuTheme>,
default: 'dark', default: 'dark',
}, },
collapsed: { collapsed: {
...@@ -101,46 +123,24 @@ export const VueBaseMenuProps = { ...@@ -101,46 +123,24 @@ export const VueBaseMenuProps = {
type: Array as PropType<WithFalse<string[]>>, type: Array as PropType<WithFalse<string[]>>,
required: true, required: true,
}, },
} };
const renderMenu = (item, i18nRender) => {
if (item && !item.hidden) {
const hasChild = item.children && !item.hideChildrenInMenu
return hasChild ? renderSubMenu(item, i18nRender) : renderMenuItem(item, i18nRender)
}
return null
}
const renderSubMenu = (item, i18nRender) => { const renderTitle = (title, i18nRender) => {
const renderMenuContent = ( return <span>{(i18nRender && i18nRender(title)) || title}</span>;
<span> };
<LazyIcon icon={item.meta.icon} />
<span>{renderTitle(item.meta.title, i18nRender)}</span>
</span>
)
return (
<Menu.SubMenu
key={item.path}
// @ts-ignore
title={renderMenuContent}
>
{!item.hideChildrenInMenu && item.children.map(cd => renderMenu(cd, i18nRender))}
</Menu.SubMenu>
)
}
const renderMenuItem = (item, i18nRender) => { const renderMenuItem = (item, i18nRender) => {
const meta = Object.assign({}, item.meta) const meta = Object.assign({}, item.meta);
const target = meta.target || null const target = meta.target || null;
const CustomTag = target && 'a' || 'router-link' const CustomTag = (target && 'a') || 'router-link';
const props = { to: { name: item.name }, href: item.path, target: target } const props = { to: { name: item.name }, href: item.path, target: target };
if (item.children && item.hideChildrenInMenu) { if (item.children && item.hideChildrenInMenu) {
// 把有子菜单的 并且 父菜单是要隐藏子菜单的 // 把有子菜单的 并且 父菜单是要隐藏子菜单的
// 都给子菜单增加一个 hidden 属性 // 都给子菜单增加一个 hidden 属性
// 用来给刷新页面时, selectedKeys 做控制用 // 用来给刷新页面时, selectedKeys 做控制用
item.children.forEach(cd => { item.children.forEach(cd => {
cd.meta = Object.assign(cd.meta || {}, { hidden: true }) cd.meta = Object.assign(cd.meta || {}, { hidden: true });
}) });
} }
return ( return (
<Menu.Item key={item.path}> <Menu.Item key={item.path}>
...@@ -149,14 +149,36 @@ const renderMenuItem = (item, i18nRender) => { ...@@ -149,14 +149,36 @@ const renderMenuItem = (item, i18nRender) => {
{renderTitle(meta.title, i18nRender)} {renderTitle(meta.title, i18nRender)}
</CustomTag> </CustomTag>
</Menu.Item> </Menu.Item>
) );
} };
const renderSubMenu = (item, i18nRender) => {
const renderMenuContent = (
<span>
<LazyIcon icon={item.meta.icon} />
<span>{renderTitle(item.meta.title, i18nRender)}</span>
</span>
) as string & VNode;
return (
<Menu.SubMenu key={item.path} title={renderMenuContent}>
{/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}
{!item.hideChildrenInMenu && item.children.map(cd => renderMenu(cd, i18nRender))}
</Menu.SubMenu>
);
};
const renderMenu = (item, i18nRender) => {
if (item && !item.hidden) {
const hasChild = item.children && !item.hideChildrenInMenu;
return hasChild ? renderSubMenu(item, i18nRender) : renderMenuItem(item, i18nRender);
}
return null;
};
let IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: defaultSettings.iconfontUrl, scriptUrl: defaultSettings.iconfontUrl,
}); });
// const LazyIcon = (props, _) => { // const LazyIcon = (props, _) => {
// const { icon } = toRefs(props) // const { icon } = toRefs(props)
// if (typeof icon.value === 'string' && icon.value !== '') { // if (typeof icon.value === 'string' && icon.value !== '') {
...@@ -173,61 +195,54 @@ let IconFont = createFromIconfontCN({ ...@@ -173,61 +195,54 @@ let IconFont = createFromIconfontCN({
// const IconComponent = resolveComponent(`${icon.value}`) // const IconComponent = resolveComponent(`${icon.value}`)
// return h(IconComponent) // return h(IconComponent)
// } // }
const LazyIcon = defineComponent({ const LazyIcon = props => {
props: { const { icon } = toRefs(props);
icon: {
type: [String, Function, Object] as PropType<string|Function|VNodeChild|JSX.Element>,
}
},
setup(props, _) {
const { icon } = toRefs(props)
if (typeof icon.value === 'string' && icon.value !== '') { if (typeof icon.value === 'string' && icon.value !== '') {
if (isUrl(icon.value) || isImg(icon.value)) { if (isUrl(icon.value) || isImg(icon.value)) {
return <img src={icon.value} alt="icon" class="ant-pro-sider-menu-icon" /> return <img src={icon.value} alt="icon" class="ant-pro-sider-menu-icon" />;
} }
if (icon.value.startsWith('icon-')) { if (icon.value.startsWith('icon-')) {
return <IconFont type={icon.value} /> return <IconFont type={icon.value} />;
} }
} }
if (isVNode(icon.value)) { if (isVNode(icon.value)) {
return icon.value return icon.value;
} }
const ALazyIcon = resolveComponent(`${icon.value}`) // const ALazyIcon = resolveComponent(`${icon.value}`);
// return ALazyIcon && ALazyIcon // return ALazyIcon && ALazyIcon
return ALazyIcon && (() => ( return h(icon.value);
// @ts-ignore };
<ALazyIcon />
)) || null
}
})
const renderTitle = (title, i18nRender) => {
return <span>{ i18nRender && i18nRender(title) || title }</span>
}
LazyIcon.icon = {
type: [String, Function, Object] as PropType<string | Function | VNodeChild | JSX.Element>,
};
export default defineComponent({ export default defineComponent({
name: 'BaseMenu', name: 'BaseMenu',
props: Object.assign({}, { props: Object.assign(
{},
{
i18n: { i18n: {
type: Function, type: Function,
default: (t: string): string => t, default: (t: string): string => t,
}, },
}, VueBaseMenuProps), },
VueBaseMenuProps,
),
emits: ['update:openKeys', 'update:selectedKeys'], emits: ['update:openKeys', 'update:selectedKeys'],
setup (props, { emit } ) { setup(props, { emit }) {
const { mode } = toRefs(props); const { mode } = toRefs(props);
const isInline = computed(() => mode.value === 'inline') const isInline = computed(() => mode.value === 'inline');
const handleOpenChange: OpenEventHandler = (openKeys): void => { const handleOpenChange: OpenEventHandler = (openKeys): void => {
emit('update:openKeys', openKeys) emit('update:openKeys', openKeys);
} };
const handleSelect = ({ selectedKeys }: SelectInfo): void => { const handleSelect = ({ selectedKeys }: SelectInfo): void => {
emit('update:selectedKeys', selectedKeys) emit('update:selectedKeys', selectedKeys);
} };
return () => ( return () => (
<Menu <Menu
inlineCollapsed={isInline.value && props.collapsed || undefined} inlineCollapsed={(isInline.value && props.collapsed) || undefined}
mode={props.mode} mode={props.mode}
theme={props.theme} theme={props.theme}
openKeys={props.openKeys} openKeys={props.openKeys}
...@@ -235,13 +250,14 @@ export default defineComponent({ ...@@ -235,13 +250,14 @@ export default defineComponent({
onOpenChange={handleOpenChange} onOpenChange={handleOpenChange}
onSelect={handleSelect} onSelect={handleSelect}
> >
{props.menus && props.menus.map(menu => { {props.menus &&
props.menus.map(menu => {
if (menu.hidden) { if (menu.hidden) {
return null return null;
} }
return renderMenu(menu, props.i18n) return renderMenu(menu, props.i18n);
})} })}
</Menu> </Menu>
) );
} },
}) });
import './index.less'; import './index.less';
import { computed, ref, VNodeChild, SetupContext, inject } from 'vue'; import { computed, ref, VNodeChild, inject } from 'vue';
// import 'ant-design-vue/es/layout/style'; // import 'ant-design-vue/es/layout/style';
// import Layout from 'ant-design-vue/es/layout'; // import Layout from 'ant-design-vue/es/layout';
...@@ -16,15 +16,22 @@ export type PrivateSiderMenuProps = { ...@@ -16,15 +16,22 @@ export type PrivateSiderMenuProps = {
matchMenuKeys: string[]; matchMenuKeys: string[];
}; };
export interface SiderMenuProps extends Pick<BaseMenuProps, Exclude<keyof BaseMenuProps, ['onCollapse']>> { export interface SiderMenuProps
extends Pick<BaseMenuProps, Exclude<keyof BaseMenuProps, ['onCollapse']>> {
logo?: VNodeChild | JSX.Element; logo?: VNodeChild | JSX.Element;
siderWidth?: number; siderWidth?: number;
collapsedWidth?: number; collapsedWidth?: number;
menuHeaderRender?: WithFalse< menuHeaderRender?: WithFalse<
(logo: VNodeChild | JSX.Element, title: VNodeChild | JSX.Element, props?: SiderMenuProps) => VNodeChild (
logo: VNodeChild | JSX.Element,
title: VNodeChild | JSX.Element,
props?: SiderMenuProps,
) => VNodeChild
>; >;
menuFooterRender?: WithFalse<(props?: SiderMenuProps) => VNodeChild>; menuFooterRender?: WithFalse<(props?: SiderMenuProps) => VNodeChild>;
menuContentRender?: WithFalse<(props: SiderMenuProps, defaultDom: VNodeChild | JSX.Element) => VNodeChild>; menuContentRender?: WithFalse<
(props: SiderMenuProps, defaultDom: VNodeChild | JSX.Element) => VNodeChild
>;
menuExtraRender?: WithFalse<(props: SiderMenuProps) => VNodeChild>; menuExtraRender?: WithFalse<(props: SiderMenuProps) => VNodeChild>;
collapsedButtonRender?: WithFalse<(collapsed?: boolean) => VNodeChild>; collapsedButtonRender?: WithFalse<(collapsed?: boolean) => VNodeChild>;
breakpoint?: SiderProps['breakpoint'] | false; breakpoint?: SiderProps['breakpoint'] | false;
...@@ -43,7 +50,7 @@ export const defaultRenderLogo = (logo: VNodeChild | JSX.Element): VNodeChild | ...@@ -43,7 +50,7 @@ export const defaultRenderLogo = (logo: VNodeChild | JSX.Element): VNodeChild |
return logo(); return logo();
} }
return logo; return logo;
} };
export const defaultRenderLogoAndTitle = ( export const defaultRenderLogoAndTitle = (
props: SiderMenuProps, props: SiderMenuProps,
...@@ -53,7 +60,7 @@ export const defaultRenderLogoAndTitle = ( ...@@ -53,7 +60,7 @@ export const defaultRenderLogoAndTitle = (
logo = 'https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg', logo = 'https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg',
title, title,
layout, layout,
} = props } = props;
const renderFunction = props[renderKey || '']; const renderFunction = props[renderKey || ''];
if (renderFunction === false) { if (renderFunction === false) {
return null; return null;
...@@ -73,41 +80,31 @@ export const defaultRenderLogoAndTitle = ( ...@@ -73,41 +80,31 @@ export const defaultRenderLogoAndTitle = (
{props.collapsed ? null : titleDom} {props.collapsed ? null : titleDom}
</a> </a>
); );
} };
export const defaultRenderCollapsedButton = (collapsed?: boolean) => export const defaultRenderCollapsedButton = (collapsed?: boolean) =>
collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />; collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />;
const SiderMenu = (props: SiderMenuProps, context: SetupContext) => { const SiderMenu = (props: SiderMenuProps) => {
const { const {
menuData, menuData,
collapsed, collapsed,
fixSiderbar,
menuFooterRender,
onCollapse,
theme,
siderWidth, siderWidth,
isMobile,
onMenuHeaderClick,
breakpoint = 'lg',
layout,
menuExtraRender = false, menuExtraRender = false,
collapsedButtonRender = defaultRenderCollapsedButton,
menuContentRender,
prefixCls,
onOpenChange, onOpenChange,
onSelect, onSelect,
headerHeight,
collapsedWidth = 48, collapsedWidth = 48,
} = props; } = props;
console.log('props', props) console.log('props', props);
const { getPrefixCls } = inject(injectProConfigKey, defaultProProviderProps) const { getPrefixCls } = inject(injectProConfigKey, defaultProProviderProps);
const baseClassName = getPrefixCls('sider'); const baseClassName = getPrefixCls('sider');
const isMix = computed(() => props.layout === 'mix'); const isMix = computed(() => props.layout === 'mix');
const fixed = computed(() => props.fixed); const fixed = computed(() => props.fixed);
const runtimeTheme = computed(() => props.layout === 'mix' && 'light' || 'dark'); const runtimeTheme = computed(() => (props.layout === 'mix' && 'light') || 'dark');
const runtimeSideWidth = computed(() => props.collapsed ? props.collapsedWidth : props.siderWidth); const runtimeSideWidth = computed(() =>
props.collapsed ? props.collapsedWidth : props.siderWidth,
);
const classNames = ref({ const classNames = ref({
[baseClassName]: true, [baseClassName]: true,
...@@ -122,14 +119,17 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => { ...@@ -122,14 +119,17 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => {
return ( return (
<> <>
{ fixed.value && (<div style={{ {fixed.value && (
<div
style={{
width: `${runtimeSideWidth.value}px`, width: `${runtimeSideWidth.value}px`,
overflow: 'hidden', overflow: 'hidden',
flex: `0 0 ${runtimeSideWidth.value}px`, flex: `0 0 ${runtimeSideWidth.value}px`,
maxWidth: `${runtimeSideWidth.value}px`, maxWidth: `${runtimeSideWidth.value}px`,
minWidth: `${runtimeSideWidth.value}px`, minWidth: `${runtimeSideWidth.value}px`,
}} }}
/>)} />
)}
<Sider <Sider
class={classNames.value} class={classNames.value}
width={siderWidth} width={siderWidth}
...@@ -137,9 +137,7 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => { ...@@ -137,9 +137,7 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => {
collapsible={false} collapsible={false}
collapsedWidth={collapsedWidth} collapsedWidth={collapsedWidth}
> >
<div class="ant-pro-sider-logo"> <div class="ant-pro-sider-logo">{headerDom}</div>
{headerDom}
</div>
<div style="flex: 1 1 0%; overflow: hidden auto;"> <div style="flex: 1 1 0%; overflow: hidden auto;">
<BaseMenu <BaseMenu
menus={menuData} menus={menuData}
...@@ -158,7 +156,7 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => { ...@@ -158,7 +156,7 @@ const SiderMenu = (props: SiderMenuProps, context: SetupContext) => {
}, },
'onUpdate:selectedKeys': $event => { 'onUpdate:selectedKeys': $event => {
onSelect($event); onSelect($event);
} },
}} }}
/> />
</div> </div>
......
import { FunctionalComponent, toRefs } from "vue" import { FunctionalComponent, toRefs } from 'vue';
import 'ant-design-vue/es/drawer/style'; import 'ant-design-vue/es/drawer/style';
import Drawer from 'ant-design-vue/es/drawer'; import Drawer from 'ant-design-vue/es/drawer';
import SiderMenu, { SiderMenuProps, PrivateSiderMenuProps } from './SiderMenu'; import SiderMenu, { SiderMenuProps, PrivateSiderMenuProps } from './SiderMenu';
const SiderMenuWrapper: FunctionalComponent<SiderMenuProps & PrivateSiderMenuProps> = const SiderMenuWrapper: FunctionalComponent<SiderMenuProps & PrivateSiderMenuProps> = (
(props, ctx) => { props,
ctx,
) => {
return props.isMobile ? ( return props.isMobile ? (
<Drawer> <Drawer>
<SiderMenu <SiderMenu {...props} />
{...props}
/>
</Drawer> </Drawer>
) : ( ) : (
<SiderMenu <SiderMenu {...props} />
{...props} );
/>
)
}; };
SiderMenuWrapper.inheritAttrs = false SiderMenuWrapper.inheritAttrs = false;
export default SiderMenuWrapper; export default SiderMenuWrapper;
...@@ -6,12 +6,12 @@ export interface MenuInfo { ...@@ -6,12 +6,12 @@ export interface MenuInfo {
key: string; key: string;
keyPath: string[]; keyPath: string[];
item: VNodeChild; item: VNodeChild;
domEvent?: MouseEvent, domEvent?: MouseEvent;
}; }
export interface SelectInfo extends MenuInfo { export interface SelectInfo extends MenuInfo {
selectedKeys?: string[]; selectedKeys?: string[];
}; }
export type OpenEventHandler = ( export type OpenEventHandler = (
keys: keys:
...@@ -24,7 +24,6 @@ export type OpenEventHandler = ( ...@@ -24,7 +24,6 @@ export type OpenEventHandler = (
}, },
) => void; ) => void;
export type CollapseType = 'clickTrigger' | 'responsive'; export type CollapseType = 'clickTrigger' | 'responsive';
export type SiderTheme = 'light' | 'dark'; export type SiderTheme = 'light' | 'dark';
......
import { MenuTheme, ContentWidth } from './typings' import { MenuTheme, ContentWidth } from './typings';
export interface RenderSetting { export interface RenderSetting {
headerRender?: false; headerRender?: false;
......
...@@ -18,10 +18,10 @@ export interface CreateContext<T> { ...@@ -18,10 +18,10 @@ export interface CreateContext<T> {
state: UnwrapRef<T> | T; state: UnwrapRef<T> | T;
} }
export const createContext = <T>(context: ContextType<T>, export const createContext = <T>(
context: ContextType<T>,
contextInjectKey: InjectionKey<ContextType<T>> = Symbol(), contextInjectKey: InjectionKey<ContextType<T>> = Symbol(),
): CreateContext<T> => { ): CreateContext<T> => {
const state = reactive<ContextType<T>>({ const state = reactive<ContextType<T>>({
...context, ...context,
}); });
...@@ -41,8 +41,11 @@ export const createContext = <T>(context: ContextType<T>, ...@@ -41,8 +41,11 @@ export const createContext = <T>(context: ContextType<T>,
}; };
}; };
export const useContext = <T>(contextInjectKey: InjectionKey<ContextType<T>> = Symbol(), defaultValue?: ContextType<T>): T => { export const useContext = <T>(
return readonly(inject(contextInjectKey, defaultValue || {} as T)); contextInjectKey: InjectionKey<ContextType<T>> = Symbol(),
defaultValue?: ContextType<T>,
): T => {
return readonly(inject(contextInjectKey, defaultValue || ({} as T)));
}; };
// :: examples :: // :: examples ::
......
import { VNodeChild } from 'vue' import { VNodeChild } from 'vue';
export type MenuTheme = 'dark' | 'light'; export type MenuTheme = 'dark' | 'light';
......
import isUrl from './isUrl';
import isImg from './isImg';
import isNil from './isNil';
import { nextTick, h } from 'vue'; import { nextTick, h } from 'vue';
import { AbstractNode, IconDefinition } from '@ant-design/icons-svg/lib/types'; import { AbstractNode, IconDefinition } from '@ant-design/icons-svg/lib/types';
import { generate as generateColor } from '@ant-design/colors'; import { generate as generateColor } from '@ant-design/colors';
import insertCss from '../insert-css'; import insertCss from '../insert-css';
export { default as isUrl } from './isUrl';
export { default as isImg } from './isImg';
export { default as isNil } from './isNil';
export function warn(valid: boolean, message: string) { export function warn(valid: boolean, message: string) {
// Support uglify // Support uglify
if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) { if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) {
...@@ -164,9 +164,3 @@ export const useInsertStyles = (styleStr: string = iconStyles) => { ...@@ -164,9 +164,3 @@ export const useInsertStyles = (styleStr: string = iconStyles) => {
} }
}); });
}; };
export {
isUrl,
isImg,
isNil,
}
// source by https://github.com/ant-design/pro-components/blob/master/packages/utils // source by https://github.com/ant-design/pro-components/blob/master/packages/utils
/* eslint no-useless-escape:0 import/prefer-default-export:0 */ /* eslint no-useless-escape:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
const isUrl = (path: string): boolean => reg.test(path); const isUrl = (path: string): boolean => reg.test(path);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment