fix: 完善大图 buttonList
This commit is contained in:
parent
4230353aea
commit
a3aefaf499
@ -1,54 +1,83 @@
|
|||||||
import React, {useState ,useMemo ,ReactNode} from 'react';
|
import React, { useState, useMemo, ReactNode, useRef, useEffect } from 'react';
|
||||||
|
import { Button, Col, Dropdown, Row } from 'antd';
|
||||||
|
import { Gutter } from 'antd/es/grid/row';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
import { Button, Col, Dropdown, Row } from 'antd/es';
|
|
||||||
import { Gutter } from '../grid/row';
|
|
||||||
|
|
||||||
type ButtonItem = {
|
|
||||||
|
export interface IButtonItem {
|
||||||
key: string;
|
key: string;
|
||||||
text: ReactNode;
|
text: ReactNode;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
children?: Array<ButtonItem>;
|
children?: Array<Omit<IButtonItem, 'weight'>>;
|
||||||
// 用于排序
|
// 用于排序
|
||||||
weight: number;
|
weight: number;
|
||||||
icon?: ReactNode
|
icon?: ReactNode
|
||||||
className?: string;
|
className?: string;
|
||||||
|
isCenter?: boolean;
|
||||||
};
|
};
|
||||||
|
export interface IButtonItemWithoutWeight extends Omit<IButtonItem, 'weight'> { }
|
||||||
type Props = {
|
export interface ButtonListProps {
|
||||||
buttons: Array<ButtonItem>
|
buttons: Array<IButtonItem>
|
||||||
customButton?: ButtonItem;
|
|
||||||
gutter?: Gutter;
|
gutter?: Gutter;
|
||||||
};
|
};
|
||||||
|
|
||||||
const componentName = 'zhst-button-list';
|
const componentName = 'zhst-button-list';
|
||||||
|
|
||||||
const ButtonList: React.FC<Props> = (Props) => {
|
const ButtonList: React.FC<ButtonListProps> = (Props) => {
|
||||||
const { buttons, customButton ,gutter} = Props
|
const { buttons, gutter } = Props
|
||||||
const [activeKey, setActiveKey] = useState<string | null>(null);
|
const [activeKey, setActiveKey] = useState<string | null>(null);
|
||||||
|
const buttonListRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [buttonListWrapMarginLeft, setButtonListWrapMarginLeft] = useState(0)
|
||||||
|
const centerButtonRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
|
||||||
const sortedButtons = useMemo(() => {
|
const sortedButtons = useMemo(() => {
|
||||||
let buttonList=[...buttons]
|
let buttonList = [...buttons]
|
||||||
|
|
||||||
if (customButton) {
|
|
||||||
buttonList = [...buttons,customButton]
|
|
||||||
}
|
|
||||||
|
|
||||||
return buttonList.sort((a, b) => a.weight - b.weight);
|
|
||||||
}, [buttons, customButton]);
|
|
||||||
|
|
||||||
const handleButtonClick = (key: string, item: ButtonItem) => {
|
return buttonList?.sort((a, b) => a.weight - b.weight);
|
||||||
|
}, [buttons]);
|
||||||
|
|
||||||
|
const handleButtonClick = (key: string, item: IButtonItem) => {
|
||||||
setActiveKey(activeKey === key ? null : key);
|
setActiveKey(activeKey === key ? null : key);
|
||||||
if (!item.children ) {
|
if (!item.children) {
|
||||||
item.onClick();
|
item.onClick();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 如果获取不到 需要居中的
|
||||||
|
if (!centerButtonRef) return
|
||||||
|
// 获取 buttonList 宽度
|
||||||
|
const buttonListWidth: number = buttonListRef.current?.offsetWidth as number;
|
||||||
|
// 获取 centerButton 宽度
|
||||||
|
const centerButtonWidth: number = centerButtonRef.current?.offsetWidth as number
|
||||||
|
// 获取 buttonList 相对视口左偏移量
|
||||||
|
const buttonListOffset: number = buttonListRef.current?.offsetLeft as number
|
||||||
|
// 获取 buttonList 中心点 距视口左边距离
|
||||||
|
const buttonListCenterOffset = buttonListOffset + buttonListWidth / 2
|
||||||
|
// 获取 centerButton 中心点 相对视口左偏移量
|
||||||
|
const centerButtonOffset: number = centerButtonRef.current?.offsetLeft as number + centerButtonWidth / 2
|
||||||
|
/*
|
||||||
|
计算 centerButton 修正距离
|
||||||
|
用 buttonList 中心点 距视口左边距离 - centerButton 中心点 相对视口左偏移量
|
||||||
|
作为 buttonListWrap marginLeft 修正距离
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 这里为什么要 * 2 由于 justify-content: center; marginLeft 需要 * 2才是 正确的值 具体原因 还在研究
|
||||||
|
const buttonListWrapMarginLeft = (buttonListCenterOffset - centerButtonOffset) * 2
|
||||||
|
setButtonListWrapMarginLeft(buttonListWrapMarginLeft)
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={componentName}>
|
<div className={componentName} ref={buttonListRef}>
|
||||||
<Row gutter={gutter}>
|
<Row gutter={gutter} className={`${componentName}-list-wrap`} style={{ marginLeft: buttonListWrapMarginLeft }} >
|
||||||
{sortedButtons.map((item) => (
|
{sortedButtons?.map((item) => (
|
||||||
<Col key={item.key} >
|
<Col key={item.key} ref={item?.isCenter ? centerButtonRef : undefined} >
|
||||||
{item.children ? (
|
{item.children ? (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{
|
menu={{
|
||||||
@ -59,15 +88,20 @@ const ButtonList: React.FC<Props> = (Props) => {
|
|||||||
})),
|
})),
|
||||||
}}
|
}}
|
||||||
open={activeKey === item.key}
|
open={activeKey === item.key}
|
||||||
onOpenChange={(visible:boolean) => {
|
onOpenChange={(visible: boolean) => {
|
||||||
if (!visible) setActiveKey(null);
|
if (!visible) setActiveKey(null);
|
||||||
}}
|
}}
|
||||||
trigger={['click']}
|
trigger={['click']}
|
||||||
>
|
>
|
||||||
<Button type="text" icon={item.icon} onClick={() => handleButtonClick(item.key, item)}>{item.text}</Button>
|
<Button type="text" icon={item.icon} onClick={() => handleButtonClick(item.key, item)}>{item.text}</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
) : (
|
) : (
|
||||||
<Button type="text" icon={item.icon} onClick={() => handleButtonClick(item.key, item)}>{item.text}</Button>
|
<Button type="text"
|
||||||
|
icon={item.icon}
|
||||||
|
onClick={() => handleButtonClick(item.key, item)}
|
||||||
|
>
|
||||||
|
{item.text}
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
))}
|
))}
|
||||||
|
69
packages/meta/src/ButtonList/demo/base.tsx
Normal file
69
packages/meta/src/ButtonList/demo/base.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React, { useState, useMemo } from 'react';
|
||||||
|
import { Space } from 'antd'
|
||||||
|
import { DownloadOutlined } from '@ant-design/icons';
|
||||||
|
import { ButtonList } from '@zhst/meta'
|
||||||
|
import { ButtonListProps } from '../ButtonList';
|
||||||
|
import "./index.less"
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [isPlay, setIsPlay] = useState(true);
|
||||||
|
|
||||||
|
const props: ButtonListProps = useMemo(() => {
|
||||||
|
return {
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
key: 'button1',
|
||||||
|
text: '一级按钮1',
|
||||||
|
onClick: () => console.log('一级按钮1被点击'),
|
||||||
|
children: [
|
||||||
|
{ key: 'subButton1-1', text: '二级按钮1-1', onClick: () => console.log('二级按钮1-1被点击'), icon: <DownloadOutlined /> },
|
||||||
|
{ key: 'subButton1-2', text: '二级按钮1-2', onClick: () => console.log('二级按钮1-2被点击') },
|
||||||
|
],
|
||||||
|
weight: 1,
|
||||||
|
// icon:<DownloadOutlined />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'button2',
|
||||||
|
text: '一级按钮2',
|
||||||
|
onClick: () => console.log('一级按钮2被点击'),
|
||||||
|
weight: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '播放',
|
||||||
|
text: isPlay ? '播放按钮' : '图片按钮',
|
||||||
|
onClick: () => { setIsPlay(!isPlay) },
|
||||||
|
weight: 3,
|
||||||
|
isCenter: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'button3',
|
||||||
|
text: '一级按钮3',
|
||||||
|
onClick: () => console.log('一级按钮3被点击'),
|
||||||
|
weight: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'button4',
|
||||||
|
text: '一级按钮4',
|
||||||
|
onClick: () => console.log('一级按钮4被点击'),
|
||||||
|
weight: 4,
|
||||||
|
// isCenter: true
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'button5',
|
||||||
|
text: '一级按钮5',
|
||||||
|
onClick: () => console.log('一级按钮5被点击'),
|
||||||
|
children: [
|
||||||
|
{ key: 'subButton5-1', text: '二级按钮5-1', onClick: () => console.log('二级按钮5-1被点击') },
|
||||||
|
],
|
||||||
|
weight: 5,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}, [isPlay])
|
||||||
|
return (
|
||||||
|
<Space size={[8, 16]} direction="vertical">
|
||||||
|
<ButtonList {...props} />
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
5
packages/meta/src/ButtonList/demo/index.less
Normal file
5
packages/meta/src/ButtonList/demo/index.less
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#buttonlist-demo-base {
|
||||||
|
.dumi-default-previewer-demo>div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.zhst-button-list {
|
.zhst-button-list {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
.ant-btn-text:hover{
|
.ant-btn-text:hover{
|
||||||
background: none !important;
|
background: none !important ;
|
||||||
color: #247fdb !important;
|
color: #247fdb !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,78 +7,7 @@ title: ButtonList 按钮列表组件
|
|||||||
|
|
||||||
# ButtonList 按钮列表组件
|
# ButtonList 按钮列表组件
|
||||||
|
|
||||||
```jsx
|
<code src="./demo/base.tsx"></code>
|
||||||
import React, { useState, useRef ,useMemo} from 'react';
|
|
||||||
import { Button, Space } from 'antd'
|
|
||||||
import { DownloadOutlined } from '@ant-design/icons';
|
|
||||||
import { ButtonList } from '@zhst/meta'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
const [isPlay,setIsPlay] = useState(true);
|
|
||||||
|
|
||||||
const props = useMemo(() => {
|
|
||||||
return {
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
key: 'button1',
|
|
||||||
text: '一级按钮1',
|
|
||||||
onClick: () => console.log('一级按钮1被点击'),
|
|
||||||
children: [
|
|
||||||
{ key: 'subButton1-1', text: '二级按钮1-1', onClick: () => console.log('二级按钮1-1被点击') , icon:<DownloadOutlined /> },
|
|
||||||
{ key: 'subButton1-2', text: '二级按钮1-2', onClick: () => console.log('二级按钮1-2被点击') },
|
|
||||||
],
|
|
||||||
weight: 1,
|
|
||||||
// icon:<DownloadOutlined />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'button2',
|
|
||||||
text: '一级按钮2',
|
|
||||||
onClick: () => console.log('一级按钮2被点击'),
|
|
||||||
children: null,
|
|
||||||
weight: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'button3',
|
|
||||||
text: '一级按钮3',
|
|
||||||
onClick: () => console.log('一级按钮3被点击'),
|
|
||||||
children: null,
|
|
||||||
weight: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'button4',
|
|
||||||
text: '一级按钮4',
|
|
||||||
onClick: () => console.log('一级按钮4被点击'),
|
|
||||||
weight: 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'button5',
|
|
||||||
text: '一级按钮5' ,
|
|
||||||
onClick: () => console.log('一级按钮5被点击'),
|
|
||||||
children: [
|
|
||||||
{ key: 'subButton5-1', text: '二级按钮5-1', onClick: () => console.log('二级按钮5-1被点击') },
|
|
||||||
],
|
|
||||||
weight: 5,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
customButton:
|
|
||||||
{
|
|
||||||
key: '播放',
|
|
||||||
text: isPlay ? '播放按钮' : '图片按钮',
|
|
||||||
onClick: () => {setIsPlay(!isPlay)},
|
|
||||||
weight: 3.5,
|
|
||||||
}
|
|
||||||
}},[isPlay])
|
|
||||||
return (
|
|
||||||
<Space size={[8, 16]} direction="vertical">
|
|
||||||
<ButtonList {...props}/>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user