Skip to content

Commit

Permalink
fix: layout top-nav-header
Browse files Browse the repository at this point in the history
  • Loading branch information
sendya committed Dec 10, 2020
1 parent f690441 commit 0bd9c2e
Show file tree
Hide file tree
Showing 13 changed files with 346 additions and 111 deletions.
2 changes: 1 addition & 1 deletion examples/base-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const BaseMenuDemo = {
<div class="demo" style="background: rgb(244,244,244);">
<div class="container" style="width: 256px;">
<BaseMenu
menus={menus}
menuData={menus}
theme={state.theme}
mode={state.mode}
collapsed={menuState.collapsed}
Expand Down
31 changes: 23 additions & 8 deletions examples/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'ant-design-vue/dist/antd.less';
import { createApp, defineComponent, reactive } from 'vue';
import { RouterLink } from './mock-router';
import { Button, message } from 'ant-design-vue';
import { Button, Avatar, message } from 'ant-design-vue';
import { default as ProLayout } from '../src/';
import { menus } from './menus';
import { useMenuState } from '../src/SiderMenu/BaseMenu';
Expand Down Expand Up @@ -34,24 +34,39 @@ const BasicLayout = defineComponent({
{...attrs}
v-model={[menuState.collapsed, 'collapsed']}
title={'Pro Layout'}
layout={'side'}
theme={'dark'}
layout={'mix'}
theme={'light'}
navTheme={'dark'}
i18n={(key: string) => key}
isMobile={false}
menuData={menus}
matchMenuKeys={[]}
contentWidth={'Fixed'}
primaryColor={'#1890ff'}
contentStyle={{ minHeight: '500px' }}
siderWidth={208}
openKeys={menuState.openKeys}
selectedKeys={menuState.selectedKeys}
onOpenChange={$event => {
$event && (menuState.openKeys = $event);
}}
onSelect={$event => {
$event && (menuState.selectedKeys = $event);
{...{
'onUpdate:openKeys':$event => {
$event && (menuState.openKeys = $event);
},
'onUpdate:selectedKeys': $event => {
$event && (menuState.selectedKeys = $event);
}
}}
v-slots={{
rightContentRender: () => (
<div style="color: #FFF;margin-right: 16px;">
<Avatar icon={(<Icon.UserOutlined />)} /> Sendya
</div>
),
menuHeaderRender: () => (
<a>
<img src="https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg" />
{menuState.collapsed ? null : (<h1>Pro Layout</h1>)}
</a>
),
footerRender: () => (
<div>123</div>
)
Expand Down
1 change: 0 additions & 1 deletion examples/page-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ const App = defineComponent({
}}
tabActiveKey={state.tabActiveKey}
onTabChange={(key: string) => {
console.log('onTabChange', key);
state.tabActiveKey = key;
}}
footer={[
Expand Down
6 changes: 3 additions & 3 deletions examples/side-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ const DemoComponent = {
}} />
</div>
) : null}
menuFooterRender={(props) => (
<div style="color: #fff; padding: 8px 16px; overflow: hidden;">
<span>状态:{JSON.stringify(props.collapsed)}</span>
menuFooterRender={(props) => props.collapsed ? undefined : (
<div style="color: #fff; padding: 8px 16px; overflow: hidden;">
<span>自定义页脚</span>
</div>
)}
/>
Expand Down
207 changes: 144 additions & 63 deletions src/BasicLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { computed, FunctionalComponent, CSSProperties } from 'vue';
import { computed, FunctionalComponent, CSSProperties, VNodeChild } from 'vue';
import 'ant-design-vue/es/layout/style';
import Layout from 'ant-design-vue/es/layout';
import { withInstall } from 'ant-design-vue/es/_util/type';
import { default as ProProvider, ProProviderData } from './ProProvider';
import { default as GlobalFooter } from './GlobalFooter';
import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu';
import { WrapContent } from './WrapContent';
import { default as Header, HeaderViewProps } from './Header';
import { RenderVNodeType, WithFalse } from './typings';
import { getComponentOrSlot } from './utils';
import useMergedState from './hooks/useMergedState';
import './BasicLayout.less';

const defaultI18nRender = (key: string) => key;

export interface BasicLayoutProps {
export type BasicLayoutProps = SiderMenuWrapperProps & HeaderViewProps & {
pure?: boolean;
/**
*@name logo url
Expand All @@ -23,6 +25,8 @@ export interface BasicLayoutProps {

i18n?: ProProviderData['i18n'];

defaultCollapsed?: boolean;

onCollapse?: (collapsed: boolean) => void;

footerRender?: WithFalse<
Expand All @@ -44,12 +48,28 @@ export interface BasicLayoutProps {
* 兼用 content的 margin
*/
disableContentMargin?: boolean;
}
};

export type ProLayoutProps = BasicLayoutProps &
SiderMenuWrapperProps /* & HeaderProps & FooterProps */;
const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots, attrs }) => {
const {
onCollapse: propsOnCollapse,
contentStyle,
disableContentMargin,
siderWidth = 208,
menu,
isChildrenLayout: propsIsChildrenLayout,
loading,
layout,
matchMenuKeys,
navTheme,
menuData,
isMobile,
defaultCollapsed,
} = props;
const isTop = computed(() => layout === 'top');
const isSide = computed(() => layout === 'side');
const isMix = computed(() => layout === 'mix');

const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots }) => {
const handleCollapse = (collapsed: boolean) => {
emit('update:collapsed', collapsed);
};
Expand All @@ -72,72 +92,97 @@ const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots })
};
});

const [collapsed, onCollapse] = useMergedState<boolean>(defaultCollapsed || false, {
value: props.collapsed,
onChange: propsOnCollapse,
});
const headerRender = (
props: BasicLayoutProps & {
hasSiderMenu: boolean;
customHeaderRender: VNodeChild | false;
rightContentRender: VNodeChild | false;
},
matchMenuKeys: string[]
): RenderVNodeType => {
if (props.headerRender === false || props.pure) {
return null;
}
return <Header matchMenuKeys={matchMenuKeys} {...props} />;
return <Header matchMenuKeys={matchMenuKeys} {...props} headerHeight={48} />;
}
const footerRender = getComponentOrSlot(props, slots, 'footerRender');
const rightContentRender = getComponentOrSlot(props, slots, 'rightContentRender');
const customHeaderRender = getComponentOrSlot(props, slots, 'headerRender');;
const headerDom = headerRender({
...props,
hasSiderMenu: isTop.value,
menuData,
isMobile,
collapsed,
onCollapse,
onSelect: handleSelect,
onOpenChange: handleOpenChange,
customHeaderRender,
rightContentRender,
theme: (navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light',
}, matchMenuKeys);

// const headerRender = getComponentOrSlot(props, slots, 'headerRender');
const footerRender = getComponentOrSlot(props, slots, 'footerRender');
const menuRender = getComponentOrSlot(props, slots, 'menuRender');
const menuHeaderRender = getComponentOrSlot(props, slots, 'menuHeaderRender');

// const menuHeaderRender = getComponentOrSlot(props, slots, 'menuHeaderRender');
const menuHeaderRenderFunc = props['menuHeaderRender'];
const menuHeaderRenderSlot = slots['menuHeaderRender'];

return (
<ProProvider i18n={defaultI18nRender}>
<div class={className.value}>
<Layout class={baseClassName.value}>
<SiderMenuWrapper
{...props}
onSelect={handleSelect}
onOpenChange={handleOpenChange}
onCollapse={handleCollapse}
/>
<Layout>
<Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;">
</Layout.Header>
<WrapContent style={props.contentStyle}>
{slots.default?.()}
</WrapContent>
{ footerRender && footerRender || footerRender !== false && (
<GlobalFooter
links={[
{
key: '1',
title: 'Pro Layout',
href: 'https://www.github.com/vueComponent/pro-layout',
blankTarget: true,
},
{
key: '2',
title: 'Github',
href: 'https://www.github.com/vueComponent/ant-design-vue-pro',
blankTarget: true,
},
{
key: '3',
title: '@Sendya',
href: 'https://www.github.com/sendya/',
blankTarget: true,
},
]}
copyright={
<a href="https://github.com/vueComponent" target="_blank">
vueComponent
</a>
}
/>
)}
</Layout>
</Layout>
</div>
{ props.pure
? (slots.default?.())
: (
<div class={className.value}>
<Layout class={baseClassName.value}>
{ !isTop.value && (<SiderMenuWrapper
{...props}
menuHeaderRender={menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))}
onSelect={handleSelect}
onOpenChange={handleOpenChange}
onCollapse={handleCollapse}
/>)}
<Layout>
{headerDom}
<WrapContent style={props.contentStyle}>
{slots.default?.()}
</WrapContent>
{ footerRender && footerRender || footerRender !== false && (
<GlobalFooter
links={[
{
key: '1',
title: 'Pro Layout',
href: 'https://www.github.com/vueComponent/pro-layout',
blankTarget: true,
},
{
key: '2',
title: 'Github',
href: 'https://www.github.com/vueComponent/ant-design-vue-pro',
blankTarget: true,
},
{
key: '3',
title: '@Sendya',
href: 'https://www.github.com/sendya/',
blankTarget: true,
},
]}
copyright={
<a href="https://github.com/vueComponent" target="_blank">
vueComponent
</a>
}
/>
)}
</Layout>
</Layout>
</div>
)}
</ProProvider>
);
};
Expand All @@ -153,18 +198,54 @@ ProLayout.props = {
title: String,
colSize: String,
isChildrenLayout: Boolean,
fixSiderbar: Boolean,
isMobile: Boolean,
fixSiderbar: {
type: Boolean,
default: () => false,
},
fixedHeader: {
type: Boolean,
default: () => false,
},
layout: String,
openKeys: Array,
selectedKeys: Array,
collapsed: Boolean,
menuData: Array,
contentStyle: Object,
headerRender: [Function, Boolean],
footerRender: [Function, Boolean],
menuRender: [Function, Boolean],
menuHeaderRender: [Function, Boolean],
rightContent: [Function, Boolean],
theme: String,
headerTheme: {
type: String,
defualt: 'light',
},
navTheme: {
type: String,
default: 'light',
},
headerRender: {
type: [Function, Boolean],
default: () => undefined,
},
footerRender: {
type: [Function, Boolean],
default: () => undefined,
},
menuRender: {
type: [Function, Boolean],
default: () => undefined,
},
menuHeaderRender: {
type: [Function, Boolean],
default: () => undefined,
},
rightContentRender: {
type: [Function, Boolean],
default: () => undefined,
},
rightContent: {
type: [Function, Boolean],
default: () => undefined,
},
} as any;

export default withInstall(ProLayout);
Loading

0 comments on commit 0bd9c2e

Please sign in to comment.