Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pro-layout
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
packages
pro-layout
Commits
0bd9c2e0
Commit
0bd9c2e0
authored
Dec 10, 2020
by
Sendya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: layout top-nav-header
parent
f6904415
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
346 additions
and
111 deletions
+346
-111
base-menu.tsx
examples/base-menu.tsx
+1
-1
index.tsx
examples/index.tsx
+23
-8
page-container.tsx
examples/page-container.tsx
+0
-1
side-menu.tsx
examples/side-menu.tsx
+3
-3
BasicLayout.tsx
src/BasicLayout.tsx
+144
-63
index.tsx
src/GlobalHeader/index.tsx
+12
-10
Header.tsx
src/Header.tsx
+41
-11
BaseMenu.tsx
src/SiderMenu/BaseMenu.tsx
+5
-3
SiderMenu.tsx
src/SiderMenu/SiderMenu.tsx
+3
-2
index.tsx
src/SiderMenu/index.tsx
+3
-1
index.less
src/TopNavHeader/index.less
+77
-0
index.tsx
src/TopNavHeader/index.tsx
+22
-8
useMergedState.ts
src/hooks/useMergedState.ts
+12
-0
No files found.
examples/base-menu.tsx
View file @
0bd9c2e0
...
...
@@ -58,7 +58,7 @@ const BaseMenuDemo = {
<
div
class=
"demo"
style=
"background: rgb(244,244,244);"
>
<
div
class=
"container"
style=
"width: 256px;"
>
<
BaseMenu
menu
s
=
{
menus
}
menu
Data
=
{
menus
}
theme=
{
state
.
theme
}
mode=
{
state
.
mode
}
collapsed=
{
menuState
.
collapsed
}
...
...
examples/index.tsx
View file @
0bd9c2e0
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'
;
...
...
@@ -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
>
)
...
...
examples/page-container.tsx
View file @
0bd9c2e0
...
...
@@ -79,7 +79,6 @@ const App = defineComponent({
}
}
tabActiveKey=
{
state
.
tabActiveKey
}
onTabChange=
{
(
key
:
string
)
=>
{
console
.
log
(
'onTabChange'
,
key
);
state
.
tabActiveKey
=
key
;
}
}
footer=
{
[
...
...
examples/side-menu.tsx
View file @
0bd9c2e0
...
...
@@ -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
>
)
}
/>
...
...
src/BasicLayout.tsx
View file @
0bd9c2e0
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'
;
...
...
@@ -6,13 +6,15 @@ 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
...
...
@@ -23,6 +25,8 @@ export interface BasicLayoutProps {
i18n
?:
ProProviderData
[
'i18n'
];
defaultCollapsed
?:
boolean
;
onCollapse
?:
(
collapsed
:
boolean
)
=>
void
;
footerRender
?:
WithFalse
<
...
...
@@ -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
);
};
...
...
@@ -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, 'head
erRender');
const
footerRender
=
getComponentOrSlot
(
props
,
slots
,
'foot
erRender'
);
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
>
);
};
...
...
@@ -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
);
src/GlobalHeader/index.tsx
View file @
0bd9c2e0
import
{
computed
,
CSSProperties
,
FunctionalComponent
,
Ref
}
from
'vue'
;
import
{
computed
,
CSSProperties
,
FunctionalComponent
,
toRefs
}
from
'vue'
;
import
{
PureSettings
}
from
'../defaultSettings'
;
import
{
RenderVNodeType
,
MenuDataItem
,
WithFalse
}
from
'../typings'
;
import
{
SiderMenuProps
,
PrivateSiderMenuProps
,
defaultRenderLogo
,
defaultRenderLogoAndTitle
,
defaultRenderCollapsedButton
}
from
'../SiderMenu/SiderMenu'
;
...
...
@@ -48,18 +48,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
menuHeaderRender
,
onMenuHeaderClick
,
className
:
propClassName
,
style
,
layout
,
headerTheme
=
'dark'
,
splitMenus
,
menuData
,
prefixCls
,
}
=
props
;
const
baseClassName
=
`
${
prefixCls
}
-global-header`
;
const
baseClassName
=
computed
(()
=>
`
${
prefixCls
}
-global-header`
)
;
const
className
=
computed
(()
=>
{
return
{
[
baseClassName
]:
true
,
[
`
${
baseClassName
}
-layout-
${
layout
}
`
]:
layout
&&
headerTheme
===
'dark'
,
[
baseClassName
.
value
]:
true
,
[
`
${
baseClassName
.
value
}
-layout-
${
layout
}
`
]:
layout
&&
headerTheme
===
'dark'
,
}
});
if
(
layout
===
'mix'
&&
!
isMobile
&&
splitMenus
)
{
...
...
@@ -80,17 +79,17 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
}
const
logoDom
=
(
<
span
class=
{
`${baseClassName}-logo`
}
key=
"logo"
>
<
span
class=
{
`${baseClassName
.value
}-logo`
}
key=
"logo"
>
<
a
>
{
defaultRenderLogo
(
logo
)
}
</
a
>
</
span
>
);
return
(
<
div
class=
{
className
}
style=
{
{
...
style
}
}
>
<
div
class=
{
className
.
value
}
>
{
isMobile
&&
renderLogo
(
menuHeaderRender
,
logoDom
)
}
{
isMobile
&&
collapsedButtonRender
&&
(
<
span
class=
{
`${baseClassName}-collapsed-button`
}
class=
{
`${baseClassName
.value
}-collapsed-button`
}
onClick=
{
()
=>
{
if
(
onCollapse
)
{
onCollapse
(
!
collapsed
);
...
...
@@ -102,13 +101,16 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
)
}
{
layout
===
'mix'
&&
!
isMobile
&&
(
<>
<
div
class=
{
`${baseClassName}-logo`
}
onClick=
{
onMenuHeaderClick
}
>
<
div
class=
{
`${baseClassName
.value
}-logo`
}
onClick=
{
onMenuHeaderClick
}
>
{
defaultRenderLogoAndTitle
({
...
props
,
collapsed
:
false
},
'headerTitleRender'
)
}
</
div
>
</>
)
}
<
div
style=
{
{
flex
:
1
}
}
>
{
slots
.
default
?.()
}
</
div
>
{
rightContentRender
&&
rightContentRender
(
props
)
}
{
rightContentRender
&&
typeof
rightContentRender
===
'function'
?
rightContentRender
(
props
)
:
rightContentRender
}
</
div
>
);
}
...
...
src/Header.tsx
View file @
0bd9c2e0
...
...
@@ -29,10 +29,41 @@ export type HeaderViewProps = GlobalHeaderProps & {
siderWidth
?:
number
;
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
>
({
setup
(
props
)
{
export
const
HeaderView
=
defineComponent
({
inheritAttrs
:
false
,
name
:
'HeaderView'
,
props
:
headerProps
,
setup
(
props
:
HeaderViewProps
)
{
const
{
prefixCls
,
headerRender
,
headerContentRender
,
isMobile
,
fixedHeader
,
hasSiderMenu
,
headerHeight
,
layout
,
navTheme
,
onCollapse
}
=
toRefs
(
props
);
console
.
log
(
'HeaderView'
,
props
)
const
isTop
=
computed
(()
=>
props
.
layout
===
'top'
);
const
needFixedHeader
=
computed
(()
=>
fixedHeader
.
value
||
layout
.
value
===
'mix'
);
const
needSettingWidth
=
computed
(()
=>
needFixedHeader
.
value
&&
hasSiderMenu
.
value
&&
!
isTop
.
value
&&
!
isMobile
.
value
);
...
...
@@ -42,11 +73,11 @@ export const HeaderView = defineComponent<HeaderViewProps>({
[
`
${
prefixCls
.
value
}
-fixed-header`
]:
needFixedHeader
.
value
,
[
`
${
prefixCls
.
value
}
-top-menu`
]:
isTop
.
value
,
}
})
})
;
const
renderContent
=
()
=>
{
let
defaultDom
=
(
<
GlobalHeader
{
...
props
}
onCollapse=
{
onCollapse
.
value
}
menuData=
{
clearMenuData
.
value
}
>
{
headerContentRender
.
value
&&
headerContentRender
.
value
(
props
)
}
{
headerContentRender
&&
headerContentRender
.
value
&&
headerContentRender
.
value
(
props
)
}
</
GlobalHeader
>
);
if
(
isTop
.
value
&&
!
isMobile
.
value
)
{
...
...
@@ -75,10 +106,9 @@ export const HeaderView = defineComponent<HeaderViewProps>({
:
'100%'
;
});
const
right
=
computed
(()
=>
needFixedHeader
.
value
?
0
:
undefined
);
return
()
=>
(
<>
{
needFixedHeader
&&
(
{
needFixedHeader
.
value
&&
(
<
Header
style=
{
{
height
:
headerHeight
.
value
,
...
...
@@ -90,13 +120,13 @@ export const HeaderView = defineComponent<HeaderViewProps>({
<
Header
style=
{
{
padding
:
0
,
height
:
headerHeight
,
lineHeight
:
`${headerHeight}px`
,
width
,
height
:
`${headerHeight.value}px`
,
lineHeight
:
`${headerHeight
.value
}px`
,
width
:
width
.
value
,
zIndex
:
layout
.
value
===
'mix'
?
100
:
19
,
right
,
right
:
right
.
value
,
}
}
class=
{
className
}
class=
{
className
.
value
}
>
{
renderContent
()
}
</
Header
>
...
...
src/SiderMenu/BaseMenu.tsx
View file @
0bd9c2e0
...
...
@@ -16,11 +16,12 @@ import {
}
from
'vue'
;
import
{
createFromIconfontCN
}
from
'@ant-design/icons-vue'
;
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
{
isImg
,
isUrl
}
from
'../utils'
;
import
{
MenuMode
,
SelectInfo
,
OpenEventHandler
}
from
'./typings'
;
import
{
MenuDataItem
,
MenuTheme
,
FormatMessage
,
WithFalse
}
from
'../typings'
;
import
{
PrivateSiderMenuProps
}
from
'./SiderMenu'
;
import
'./index.less'
;
export
{
MenuMode
,
SelectInfo
,
OpenEventHandler
};
...
...
@@ -224,12 +225,13 @@ export default defineComponent({
}):
void
=>
{
emit
(
'update:selectedKeys'
,
params
.
selectedKeys
);
};
return
()
=>
(
<
Menu
key=
"Menu"
inlineCollapsed=
{
(
isInline
.
value
&&
props
.
collapsed
)
||
undefined
}
inlineIndent=
{
16
}
mode=
{
props
.
mode
}
theme=
{
props
.
theme
}
theme=
{
props
.
theme
as
'dark'
|
'light'
}
openKeys=
{
props
.
openKeys
||
[]
}
selectedKeys=
{
props
.
selectedKeys
||
[]
}
onOpenChange=
{
handleOpenChange
}
...
...
src/SiderMenu/SiderMenu.tsx
View file @
0bd9c2e0
...
...
@@ -50,7 +50,7 @@ export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => {
export
const
defaultRenderLogoAndTitle
=
(
props
:
SiderMenuProps
,
renderKey
=
'menuHeaderRender'
,
renderKey
:
string
|
undefined
=
'menuHeaderRender'
,
):
RenderVNodeType
=>
{
const
{
logo
=
'https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg'
,
...
...
@@ -84,6 +84,7 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy
const
SiderMenu
:
FunctionalComponent
<
SiderMenuProps
>
=
(
props
:
SiderMenuProps
)
=>
{
const
{
theme
,
menuData
,
collapsed
,
siderWidth
,
...
...
@@ -173,7 +174,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
<
Menu
class=
{
`${baseClassName}-link-menu`
}
inlineIndent=
{
16
}
theme=
{
runtimeTheme
.
valu
e
}
theme=
{
them
e
}
selectedKeys=
{
[]
}
openKeys=
{
[]
}
mode=
"inline"
...
...
src/SiderMenu/index.tsx
View file @
0bd9c2e0
...
...
@@ -7,7 +7,8 @@ import SiderMenu, { SiderMenuProps, PrivateSiderMenuProps } from './SiderMenu';
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
?
(
<
Drawer
>
<
SiderMenu
{
...
props
}
/>
...
...
@@ -18,5 +19,6 @@ const SiderMenuWrapper: FunctionalComponent<SiderMenuWrapperProps> = props => {
};
SiderMenuWrapper
.
inheritAttrs
=
false
;
SiderMenuWrapper
.
displayName
=
'SiderMenuWrapper'
;
export
default
SiderMenuWrapper
;
src/TopNavHeader/index.less
0 → 100644
View file @
0bd9c2e0
@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%;
}
}
}
}
src/TopNavHeader/index.tsx
View file @
0bd9c2e0
...
...
@@ -31,29 +31,32 @@ const RightContent: FunctionalComponent<TopNavHeaderProps> = ({ rightContentRend
rightSize
.
value
=
width
;
}
}
>
{
rightContentRender
&&
(
{
rightContentRender
&&
typeof
rightContentRender
===
'function'
?
(
<
div
>
{
rightContentRender
({
...
props
,
})
}
</
div
>
)
}
)
:
rightContentRender
}
</
ResizeObserver
>
</
div
>
</
div
>
);
};
export
const
TopNavHeader
:
FunctionalComponent
<
TopNavHeaderProps
>
=
(
props
)
=>
{
export
const
TopNavHeader
:
FunctionalComponent
<
TopNavHeaderProps
>
=
(
props
,
{
emit
}
)
=>
{
const
headerRef
=
ref
();
const
{
theme
,
prefixCls
:
propPrefixCls
,
onMenuHeaderClick
,
contentWidth
,
rightContentRender
,
layout
,
onOpenChange
,
onSelect
,
...
restProps
}
=
props
;
const
prefixCls
=
`
${
prop
s
.
p
refixCls
||
'ant-pro'
}
-top-nav-header`
;
const
prefixCls
=
`
${
prop
P
refixCls
||
'ant-pro'
}
-top-nav-header`
;
const
headerDom
=
defaultRenderLogoAndTitle
(
{
...
props
,
collapsed
:
false
},
layout
===
'mix'
?
'headerTitleRender'
:
undefined
,
...
...
@@ -61,11 +64,11 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => {
const
className
=
computed
(()
=>
{
return
{
[
prefixCls
]:
true
,
light
:
theme
===
'light'
,
light
:
props
.
theme
===
'light'
,
}
});
return
(
<
div
class=
{
className
}
>
<
div
class=
{
className
.
value
}
>
<
div
ref=
{
headerRef
}
class=
{
`${prefixCls}-main ${contentWidth === 'Fixed' ? 'wide' : ''}`
}
>
{
headerDom
&&
(
<
div
class=
{
`${prefixCls}-main-left`
}
onClick=
{
onMenuHeaderClick
}
>
...
...
@@ -75,7 +78,18 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props) => {
</
div
>
)
}
<
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
>
{
rightContentRender
&&
<
RightContent
rightContentRender=
{
rightContentRender
}
{
...
props
}
/>
}
</
div
>
...
...
src/hooks/useMergedState.ts
0 → 100644
View file @
0bd9c2e0
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
];
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment