Commit 0bd9c2e0 authored by Sendya's avatar Sendya

fix: layout top-nav-header

parent f6904415
...@@ -58,7 +58,7 @@ const BaseMenuDemo = { ...@@ -58,7 +58,7 @@ const BaseMenuDemo = {
<div class="demo" style="background: rgb(244,244,244);"> <div class="demo" style="background: rgb(244,244,244);">
<div class="container" style="width: 256px;"> <div class="container" style="width: 256px;">
<BaseMenu <BaseMenu
menus={menus} menuData={menus}
theme={state.theme} theme={state.theme}
mode={state.mode} mode={state.mode}
collapsed={menuState.collapsed} collapsed={menuState.collapsed}
......
import 'ant-design-vue/dist/antd.less'; import 'ant-design-vue/dist/antd.less';
import { createApp, defineComponent, reactive } from 'vue'; import { createApp, defineComponent, reactive } from 'vue';
import { RouterLink } from './mock-router'; 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 { default as ProLayout } from '../src/';
import { menus } from './menus'; import { menus } from './menus';
import { useMenuState } from '../src/SiderMenu/BaseMenu'; import { useMenuState } from '../src/SiderMenu/BaseMenu';
...@@ -34,24 +34,39 @@ const BasicLayout = defineComponent({ ...@@ -34,24 +34,39 @@ const BasicLayout = defineComponent({
{...attrs} {...attrs}
v-model={[menuState.collapsed, 'collapsed']} v-model={[menuState.collapsed, 'collapsed']}
title={'Pro Layout'} title={'Pro Layout'}
layout={'side'} layout={'mix'}
theme={'dark'} theme={'light'}
navTheme={'dark'}
i18n={(key: string) => key} i18n={(key: string) => key}
isMobile={false} isMobile={false}
menuData={menus} menuData={menus}
matchMenuKeys={[]} matchMenuKeys={[]}
contentWidth={'Fixed'} contentWidth={'Fixed'}
primaryColor={'#1890ff'} primaryColor={'#1890ff'}
contentStyle={{ minHeight: '500px' }}
siderWidth={208} siderWidth={208}
openKeys={menuState.openKeys} openKeys={menuState.openKeys}
selectedKeys={menuState.selectedKeys} selectedKeys={menuState.selectedKeys}
onOpenChange={$event => { {...{
'onUpdate:openKeys':$event => {
$event && (menuState.openKeys = $event); $event && (menuState.openKeys = $event);
}} },
onSelect={$event => { 'onUpdate:selectedKeys': $event => {
$event && (menuState.selectedKeys = $event); $event && (menuState.selectedKeys = $event);
}
}} }}
v-slots={{ 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: () => ( footerRender: () => (
<div>123</div> <div>123</div>
) )
......
...@@ -79,7 +79,6 @@ const App = defineComponent({ ...@@ -79,7 +79,6 @@ const App = defineComponent({
}} }}
tabActiveKey={state.tabActiveKey} tabActiveKey={state.tabActiveKey}
onTabChange={(key: string) => { onTabChange={(key: string) => {
console.log('onTabChange', key);
state.tabActiveKey = key; state.tabActiveKey = key;
}} }}
footer={[ footer={[
......
...@@ -55,9 +55,9 @@ const DemoComponent = { ...@@ -55,9 +55,9 @@ const DemoComponent = {
}} /> }} />
</div> </div>
) : null} ) : null}
menuFooterRender={(props) => ( menuFooterRender={(props) => props.collapsed ? undefined : (
<div style="color: #fff; padding: 8px 16px; overflow: hidden;"> <div style="color: #fff; padding: 8px 16px; overflow: hidden;">
<span>状态:{JSON.stringify(props.collapsed)}</span> <span>自定义页脚</span>
</div> </div>
)} )}
/> />
......
import { computed, FunctionalComponent, CSSProperties } from 'vue'; import { computed, FunctionalComponent, CSSProperties, VNodeChild } 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';
import { withInstall } from 'ant-design-vue/es/_util/type'; import { withInstall } from 'ant-design-vue/es/_util/type';
...@@ -6,13 +6,15 @@ import { default as ProProvider, ProProviderData } from './ProProvider'; ...@@ -6,13 +6,15 @@ import { default as ProProvider, ProProviderData } from './ProProvider';
import { default as GlobalFooter } from './GlobalFooter'; import { default as GlobalFooter } from './GlobalFooter';
import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu'; import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu';
import { WrapContent } from './WrapContent'; import { WrapContent } from './WrapContent';
import { default as Header, HeaderViewProps } from './Header';
import { RenderVNodeType, WithFalse } from './typings'; import { RenderVNodeType, WithFalse } from './typings';
import { getComponentOrSlot } from './utils'; import { getComponentOrSlot } from './utils';
import useMergedState from './hooks/useMergedState';
import './BasicLayout.less'; import './BasicLayout.less';
const defaultI18nRender = (key: string) => key; const defaultI18nRender = (key: string) => key;
export interface BasicLayoutProps { export type BasicLayoutProps = SiderMenuWrapperProps & HeaderViewProps & {
pure?: boolean; pure?: boolean;
/** /**
*@name logo url *@name logo url
...@@ -23,6 +25,8 @@ export interface BasicLayoutProps { ...@@ -23,6 +25,8 @@ export interface BasicLayoutProps {
i18n?: ProProviderData['i18n']; i18n?: ProProviderData['i18n'];
defaultCollapsed?: boolean;
onCollapse?: (collapsed: boolean) => void; onCollapse?: (collapsed: boolean) => void;
footerRender?: WithFalse< footerRender?: WithFalse<
...@@ -44,12 +48,28 @@ export interface BasicLayoutProps { ...@@ -44,12 +48,28 @@ export interface BasicLayoutProps {
* 兼用 content的 margin * 兼用 content的 margin
*/ */
disableContentMargin?: boolean; disableContentMargin?: boolean;
} };
export type ProLayoutProps = BasicLayoutProps & const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots, attrs }) => {
SiderMenuWrapperProps /* & HeaderProps & FooterProps */; 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) => { const handleCollapse = (collapsed: boolean) => {
emit('update:collapsed', collapsed); emit('update:collapsed', collapsed);
}; };
...@@ -72,37 +92,61 @@ const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots }) ...@@ -72,37 +92,61 @@ const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots })
}; };
}); });
const [collapsed, onCollapse] = useMergedState<boolean>(defaultCollapsed || false, {
value: props.collapsed,
onChange: propsOnCollapse,
});
const headerRender = ( const headerRender = (
props: BasicLayoutProps & { props: BasicLayoutProps & {
hasSiderMenu: boolean; hasSiderMenu: boolean;
customHeaderRender: VNodeChild | false;
rightContentRender: VNodeChild | false;
}, },
matchMenuKeys: string[] matchMenuKeys: string[]
): RenderVNodeType => { ): RenderVNodeType => {
if (props.headerRender === false || props.pure) { if (props.headerRender === false || props.pure) {
return null; 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 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 ( return (
<ProProvider i18n={defaultI18nRender}> <ProProvider i18n={defaultI18nRender}>
{ props.pure
? (slots.default?.())
: (
<div class={className.value}> <div class={className.value}>
<Layout class={baseClassName.value}> <Layout class={baseClassName.value}>
<SiderMenuWrapper { !isTop.value && (<SiderMenuWrapper
{...props} {...props}
menuHeaderRender={menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))}
onSelect={handleSelect} onSelect={handleSelect}
onOpenChange={handleOpenChange} onOpenChange={handleOpenChange}
onCollapse={handleCollapse} onCollapse={handleCollapse}
/> />)}
<Layout> <Layout>
<Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;"> {headerDom}
</Layout.Header>
<WrapContent style={props.contentStyle}> <WrapContent style={props.contentStyle}>
{slots.default?.()} {slots.default?.()}
</WrapContent> </WrapContent>
...@@ -138,6 +182,7 @@ const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots }) ...@@ -138,6 +182,7 @@ const ProLayout: FunctionalComponent<ProLayoutProps> = (props, { emit, slots })
</Layout> </Layout>
</Layout> </Layout>
</div> </div>
)}
</ProProvider> </ProProvider>
); );
}; };
...@@ -153,18 +198,54 @@ ProLayout.props = { ...@@ -153,18 +198,54 @@ ProLayout.props = {
title: String, title: String,
colSize: String, colSize: String,
isChildrenLayout: Boolean, isChildrenLayout: Boolean,
fixSiderbar: Boolean, isMobile: Boolean,
fixSiderbar: {
type: Boolean,
default: () => false,
},
fixedHeader: {
type: Boolean,
default: () => false,
},
layout: String, layout: String,
openKeys: Array, openKeys: Array,
selectedKeys: Array, selectedKeys: Array,
collapsed: Boolean, collapsed: Boolean,
menuData: Array, menuData: Array,
contentStyle: Object, contentStyle: Object,
headerRender: [Function, Boolean], theme: String,
footerRender: [Function, Boolean], headerTheme: {
menuRender: [Function, Boolean], type: String,
menuHeaderRender: [Function, Boolean], defualt: 'light',
rightContent: [Function, Boolean], },
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; } as any;
export default withInstall(ProLayout); export default withInstall(ProLayout);
import { computed, CSSProperties, FunctionalComponent, Ref } from 'vue'; import { computed, CSSProperties, FunctionalComponent, toRefs } from 'vue';
import { PureSettings } from '../defaultSettings'; import { PureSettings } from '../defaultSettings';
import { RenderVNodeType, MenuDataItem, WithFalse } from '../typings'; import { RenderVNodeType, MenuDataItem, WithFalse } from '../typings';
import { SiderMenuProps, PrivateSiderMenuProps, defaultRenderLogo, defaultRenderLogoAndTitle, defaultRenderCollapsedButton } from '../SiderMenu/SiderMenu'; import { SiderMenuProps, PrivateSiderMenuProps, defaultRenderLogo, defaultRenderLogoAndTitle, defaultRenderCollapsedButton } from '../SiderMenu/SiderMenu';
...@@ -48,18 +48,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM ...@@ -48,18 +48,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
menuHeaderRender, menuHeaderRender,
onMenuHeaderClick, onMenuHeaderClick,
className: propClassName, className: propClassName,
style,
layout, layout,
headerTheme = 'dark', headerTheme = 'dark',
splitMenus, splitMenus,
menuData, menuData,
prefixCls, prefixCls,
} = props; } = props;
const baseClassName = `${prefixCls}-global-header`; const baseClassName = computed(() => `${prefixCls}-global-header`);
const className = computed(() => { const className = computed(() => {
return { return {
[baseClassName]: true, [baseClassName.value]: true,
[`${baseClassName}-layout-${layout}`]: layout && headerTheme === 'dark', [`${baseClassName.value}-layout-${layout}`]: layout && headerTheme === 'dark',
} }
}); });
if (layout === 'mix' && !isMobile && splitMenus) { if (layout === 'mix' && !isMobile && splitMenus) {
...@@ -80,17 +79,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM ...@@ -80,17 +79,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
} }
const logoDom = ( const logoDom = (
<span class={`${baseClassName}-logo`} key="logo"> <span class={`${baseClassName.value}-logo`} key="logo">
<a>{defaultRenderLogo(logo)}</a> <a>{defaultRenderLogo(logo)}</a>
</span> </span>
); );
return ( return (
<div class={className} style={{ ...style }}> <div class={className.value}>
{isMobile && renderLogo(menuHeaderRender, logoDom)} {isMobile && renderLogo(menuHeaderRender, logoDom)}
{isMobile && collapsedButtonRender && ( {isMobile && collapsedButtonRender && (
<span <span
class={`${baseClassName}-collapsed-button`} class={`${baseClassName.value}-collapsed-button`}
onClick={() => { onClick={() => {
if (onCollapse) { if (onCollapse) {
onCollapse(!collapsed); onCollapse(!collapsed);
...@@ -102,13 +101,16 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM ...@@ -102,13 +101,16 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
)} )}
{layout === 'mix' && !isMobile && ( {layout === 'mix' && !isMobile && (
<> <>
<div class={`${baseClassName}-logo`} onClick={onMenuHeaderClick}> <div class={`${baseClassName.value}-logo`} onClick={onMenuHeaderClick}>
{defaultRenderLogoAndTitle({ ...props, collapsed: false }, 'headerTitleRender')} {defaultRenderLogoAndTitle({ ...props, collapsed: false }, 'headerTitleRender')}
</div> </div>
</> </>
)} )}
<div style={{ flex: 1 }}>{slots.default?.()}</div> <div style={{ flex: 1 }}>{slots.default?.()}</div>
{rightContentRender && rightContentRender(props)} { rightContentRender && typeof rightContentRender === 'function'
? rightContentRender(props)
: rightContentRender
}
</div> </div>
); );
} }
......
...@@ -29,10 +29,41 @@ export type HeaderViewProps = GlobalHeaderProps & { ...@@ -29,10 +29,41 @@ export type HeaderViewProps = GlobalHeaderProps & {
siderWidth?: number; siderWidth?: number;
hasSiderMenu?: boolean; hasSiderMenu?: boolean;
}; };
export const headerProps = [
'prefixCls',
'collapsed',
'onCollapse',
'openKeys',
'selectedKeys',
'isMobile',
'logo',
'title',
'menuRender',
'rightContentRender',
'menuData',
'menuHeaderRender',
'splitMenus',
'headerRender',
'headerTitleRender',
'headerContentRender',
'siderWidth',
'hasSiderMenu',
'fixedHeader',
'headerHeight',
'headerTheme',
'layout',
'navTheme',
'onSelect',
'onOpenChange',
]
export const HeaderView = defineComponent<HeaderViewProps>({ export const HeaderView = defineComponent({
setup(props) { inheritAttrs: false,
name: 'HeaderView',
props: headerProps,
setup(props: HeaderViewProps) {
const { prefixCls, headerRender, headerContentRender, isMobile, fixedHeader, hasSiderMenu, headerHeight, layout, navTheme, onCollapse } = toRefs(props); const { prefixCls, headerRender, headerContentRender, isMobile, fixedHeader, hasSiderMenu, headerHeight, layout, navTheme, onCollapse } = toRefs(props);
console.log('HeaderView', props)
const isTop = computed(() => props.layout === 'top'); const isTop = computed(() => props.layout === 'top');
const needFixedHeader = computed(() => fixedHeader.value || layout.value === 'mix'); const needFixedHeader = computed(() => fixedHeader.value || layout.value === 'mix');
const needSettingWidth = computed(() => needFixedHeader.value && hasSiderMenu.value && !isTop.value && !isMobile.value); const needSettingWidth = computed(() => needFixedHeader.value && hasSiderMenu.value && !isTop.value && !isMobile.value);
...@@ -42,11 +73,11 @@ export const HeaderView = defineComponent<HeaderViewProps>({ ...@@ -42,11 +73,11 @@ export const HeaderView = defineComponent<HeaderViewProps>({
[`${prefixCls.value}-fixed-header`]: needFixedHeader.value, [`${prefixCls.value}-fixed-header`]: needFixedHeader.value,
[`${prefixCls.value}-top-menu`]: isTop.value, [`${prefixCls.value}-top-menu`]: isTop.value,
} }
}) });
const renderContent = () => { const renderContent = () => {
let defaultDom = ( let defaultDom = (
<GlobalHeader {...props} onCollapse={onCollapse.value} menuData={clearMenuData.value}> <GlobalHeader {...props} onCollapse={onCollapse.value} menuData={clearMenuData.value}>
{headerContentRender.value && headerContentRender.value(props)} {headerContentRender && headerContentRender.value && headerContentRender.value(props)}
</GlobalHeader> </GlobalHeader>
); );
if (isTop.value && !isMobile.value) { if (isTop.value && !isMobile.value) {
...@@ -75,10 +106,9 @@ export const HeaderView = defineComponent<HeaderViewProps>({ ...@@ -75,10 +106,9 @@ export const HeaderView = defineComponent<HeaderViewProps>({
: '100%'; : '100%';
}); });
const right = computed(() => needFixedHeader.value ? 0 : undefined); const right = computed(() => needFixedHeader.value ? 0 : undefined);
return () => ( return () => (
<> <>
{needFixedHeader && ( {needFixedHeader.value && (
<Header <Header
style={{ style={{
height: headerHeight.value, height: headerHeight.value,
...@@ -90,13 +120,13 @@ export const HeaderView = defineComponent<HeaderViewProps>({ ...@@ -90,13 +120,13 @@ export const HeaderView = defineComponent<HeaderViewProps>({
<Header <Header
style={{ style={{
padding: 0, padding: 0,
height: headerHeight, height: `${headerHeight.value}px`,
lineHeight: `${headerHeight}px`, lineHeight: `${headerHeight.value}px`,
width, width: width.value,
zIndex: layout.value === 'mix' ? 100 : 19, zIndex: layout.value === 'mix' ? 100 : 19,
right, right: right.value,
}} }}
class={className} class={className.value}
> >
{renderContent()} {renderContent()}
</Header> </Header>
......
...@@ -16,11 +16,12 @@ import { ...@@ -16,11 +16,12 @@ import {
} from 'vue'; } from 'vue';
import { createFromIconfontCN } from '@ant-design/icons-vue'; import { createFromIconfontCN } from '@ant-design/icons-vue';
import 'ant-design-vue/es/menu/style'; import 'ant-design-vue/es/menu/style';
import Menu, { MenuProps } from 'ant-design-vue/es/menu'; import Menu from 'ant-design-vue/es/menu';
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 { MenuDataItem, MenuTheme, FormatMessage, WithFalse } from '../typings'; import { MenuDataItem, MenuTheme, FormatMessage, WithFalse } from '../typings';
import { PrivateSiderMenuProps } from './SiderMenu';
import './index.less'; import './index.less';
export { MenuMode, SelectInfo, OpenEventHandler }; export { MenuMode, SelectInfo, OpenEventHandler };
...@@ -224,12 +225,13 @@ export default defineComponent({ ...@@ -224,12 +225,13 @@ export default defineComponent({
}): void => { }): void => {
emit('update:selectedKeys', params.selectedKeys); emit('update:selectedKeys', params.selectedKeys);
}; };
return () => ( return () => (
<Menu <Menu
key="Menu"
inlineCollapsed={(isInline.value && props.collapsed) || undefined} inlineCollapsed={(isInline.value && props.collapsed) || undefined}
inlineIndent={16}
mode={props.mode} mode={props.mode}
theme={props.theme} theme={props.theme as 'dark' | 'light'}
openKeys={props.openKeys || []} openKeys={props.openKeys || []}
selectedKeys={props.selectedKeys || []} selectedKeys={props.selectedKeys || []}
onOpenChange={handleOpenChange} onOpenChange={handleOpenChange}
......
...@@ -50,7 +50,7 @@ export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => { ...@@ -50,7 +50,7 @@ export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => {
export const defaultRenderLogoAndTitle = ( export const defaultRenderLogoAndTitle = (
props: SiderMenuProps, props: SiderMenuProps,
renderKey = 'menuHeaderRender', renderKey: string | undefined = 'menuHeaderRender',
): RenderVNodeType => { ): RenderVNodeType => {
const { const {
logo = 'https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg', logo = 'https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg',
...@@ -84,6 +84,7 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy ...@@ -84,6 +84,7 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy
const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) => { const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) => {
const { const {
theme,
menuData, menuData,
collapsed, collapsed,
siderWidth, siderWidth,
...@@ -173,7 +174,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) = ...@@ -173,7 +174,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
<Menu <Menu
class={`${baseClassName}-link-menu`} class={`${baseClassName}-link-menu`}
inlineIndent={16} inlineIndent={16}
theme={runtimeTheme.value} theme={theme}
selectedKeys={[]} selectedKeys={[]}
openKeys={[]} openKeys={[]}
mode="inline" mode="inline"
......
...@@ -7,7 +7,8 @@ import SiderMenu, { SiderMenuProps, PrivateSiderMenuProps } from './SiderMenu'; ...@@ -7,7 +7,8 @@ import SiderMenu, { SiderMenuProps, PrivateSiderMenuProps } from './SiderMenu';
export type SiderMenuWrapperProps = SiderMenuProps & Partial<PrivateSiderMenuProps>; export type SiderMenuWrapperProps = SiderMenuProps & Partial<PrivateSiderMenuProps>;
const SiderMenuWrapper: FunctionalComponent<SiderMenuWrapperProps> = props => { const SiderMenuWrapper: FunctionalComponent<SiderMenuWrapperProps> = (props, { attrs }) => {
console.log('SiderMenuWrapper', props, attrs)
return props.isMobile ? ( return props.isMobile ? (
<Drawer> <Drawer>
<SiderMenu {...props} /> <SiderMenu {...props} />
...@@ -18,5 +19,6 @@ const SiderMenuWrapper: FunctionalComponent<SiderMenuWrapperProps> = props => { ...@@ -18,5 +19,6 @@ const SiderMenuWrapper: FunctionalComponent<SiderMenuWrapperProps> = props => {
}; };
SiderMenuWrapper.inheritAttrs = false; SiderMenuWrapper.inheritAttrs = false;
SiderMenuWrapper.displayName = 'SiderMenuWrapper';
export default SiderMenuWrapper; export default SiderMenuWrapper;
@import '~ant-design-vue/es/style/themes/default.less';
@import '../BasicLayout.less';
@top-nav-header-prefix-cls: ~'@{ant-prefix}-pro-top-nav-header';
.@{top-nav-header-prefix-cls} {
position: relative;
width: 100%;
height: 100%;
box-shadow: 0 1px 4px 0 rgba(0, 21, 41, 0.12);
transition: background 0.3s, width 0.2s;
.@{ant-prefix}-menu {
background: transparent;
}
&.light {
background-color: @component-background;
.@{top-nav-header-prefix-cls}-logo {
h1 {
color: @heading-color;
}
}
.anticon {
color: inherit;
}
}
&-main {
display: flex;
height: 100%;
padding-left: 16px;
&-left {
display: flex;
min-width: 192px;
}
}
.anticon {
color: @btn-primary-color;
}
&-logo {
position: relative;
min-width: 165px;
height: 100%;
overflow: hidden;
img {
display: inline-block;
height: 32px;
vertical-align: middle;
}
h1 {
display: inline-block;
margin: 0 0 0 12px;
color: @btn-primary-color;
font-weight: 400;
font-size: 16px;
vertical-align: top;
}
}
&-menu {
min-width: 0;
.@{ant-prefix}-menu.@{ant-prefix}-menu-horizontal {
height: 100%;
border: none;
.@{ant-prefix}-menu-item {
height: 100%;
}
}
}
}
...@@ -31,29 +31,32 @@ const RightContent: FunctionalComponent<TopNavHeaderProps> = ({ rightContentRend ...@@ -31,29 +31,32 @@ const RightContent: FunctionalComponent<TopNavHeaderProps> = ({ rightContentRend
rightSize.value = width; rightSize.value = width;
}} }}
> >
{rightContentRender && ( {rightContentRender && typeof rightContentRender === 'function' ? (
<div> <div>
{rightContentRender({ {rightContentRender({
...props, ...props,
})} })}
</div> </div>
)} ) : rightContentRender}
</ResizeObserver> </ResizeObserver>
</div> </div>
</div> </div>
); );
}; };
export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => { export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props, { emit }) => {
const headerRef = ref(); const headerRef = ref();
const { const {
theme, prefixCls: propPrefixCls,
onMenuHeaderClick, onMenuHeaderClick,
contentWidth, contentWidth,
rightContentRender, rightContentRender,
layout, layout,
onOpenChange,
onSelect,
...restProps
} = props; } = props;
const prefixCls = `${props.prefixCls || 'ant-pro'}-top-nav-header`; const prefixCls = `${propPrefixCls || 'ant-pro'}-top-nav-header`;
const headerDom = defaultRenderLogoAndTitle( const headerDom = defaultRenderLogoAndTitle(
{ ...props, collapsed: false }, { ...props, collapsed: false },
layout === 'mix' ? 'headerTitleRender' : undefined, layout === 'mix' ? 'headerTitleRender' : undefined,
...@@ -61,11 +64,11 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => { ...@@ -61,11 +64,11 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => {
const className = computed(() => { const className = computed(() => {
return { return {
[prefixCls]: true, [prefixCls]: true,
light: theme === 'light', light: props.theme === 'light',
} }
}); });
return ( return (
<div class={className}> <div class={className.value}>
<div ref={headerRef} class={`${prefixCls}-main ${contentWidth === 'Fixed' ? 'wide' : ''}`}> <div ref={headerRef} class={`${prefixCls}-main ${contentWidth === 'Fixed' ? 'wide' : ''}`}>
{headerDom && ( {headerDom && (
<div class={`${prefixCls}-main-left`} onClick={onMenuHeaderClick}> <div class={`${prefixCls}-main-left`} onClick={onMenuHeaderClick}>
...@@ -75,7 +78,18 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => { ...@@ -75,7 +78,18 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => {
</div> </div>
)} )}
<div style={{ flex: 1 }} class={`${prefixCls}-menu`}> <div style={{ flex: 1 }} class={`${prefixCls}-menu`}>
<BaseMenu {...props} /> <BaseMenu
{...restProps}
class={{ 'top-nav-menu': props.mode === 'horizontal' }}
{...{
'onUpdate:openKeys': ($event: any) => {
onOpenChange && onOpenChange($event);
},
'onUpdate:selectedKeys': ($event: any) => {
onSelect && onSelect($event);
},
}}
/>
</div> </div>
{rightContentRender && <RightContent rightContentRender={rightContentRender} {...props} />} {rightContentRender && <RightContent rightContentRender={rightContentRender} {...props} />}
</div> </div>
......
export default function useControlledState<T, R = T>(
defaultStateValue: T | (() => T),
option?: {
defaultValue?: T | (() => T);
value?: T;
onChange?: (value: T, prevValue: T) => void;
postState?: (value: T) => T;
},
): [R, (value: T) => void] {
const triggerChange = () => {};
return [option.value, triggerChange];
}
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