From 22ecb2bbca154f51356010633fcc2020c7ea2fd7 Mon Sep 17 00:00:00 2001
From: LuckyFBB <976060700@qq.com>
Date: Wed, 6 Mar 2024 20:25:13 +0800
Subject: [PATCH 1/3] feat(slidepane): support tab control
---
src/slidePane/demos/tabs.tsx | 3 +-
src/slidePane/demos/tabsControl.tsx | 44 +++++++++++++++++++++++++++++
src/slidePane/index.md | 25 ++++++++--------
src/slidePane/index.tsx | 29 +++++++++++++++----
4 files changed, 83 insertions(+), 18 deletions(-)
create mode 100644 src/slidePane/demos/tabsControl.tsx
diff --git a/src/slidePane/demos/tabs.tsx b/src/slidePane/demos/tabs.tsx
index b5f21b51e..ceae0d040 100644
--- a/src/slidePane/demos/tabs.tsx
+++ b/src/slidePane/demos/tabs.tsx
@@ -24,7 +24,8 @@ export default () => {
},
] as const
}
- activeKey="changelog"
+ defaultKey="changelog"
+ onChange={(key) => console.log('currentKey', key)}
>
{(key) => {
switch (key) {
diff --git a/src/slidePane/demos/tabsControl.tsx b/src/slidePane/demos/tabsControl.tsx
new file mode 100644
index 000000000..a20c3dd36
--- /dev/null
+++ b/src/slidePane/demos/tabsControl.tsx
@@ -0,0 +1,44 @@
+import React, { useState } from 'react';
+import { Button } from 'antd';
+import { SlidePane } from 'dt-react-component';
+
+export default () => {
+ const [visible, setVisible] = useState(false);
+ const [activeKey, setActiveKey] = useState<'basicInfo' | 'changelog'>('changelog');
+
+ return (
+ <>
+
+ setVisible(false)}
+ title={'Title'}
+ tabs={
+ [
+ {
+ key: 'basicInfo',
+ title: '基本信息',
+ },
+ {
+ key: 'changelog',
+ title: '变更记录',
+ },
+ ] as const
+ }
+ activeKey={activeKey}
+ onChange={(key) => setActiveKey(key)}
+ >
+ {(key) => {
+ switch (key) {
+ case 'basicInfo':
+ return 基本信息
;
+ case 'changelog':
+ return 变更记录
;
+ default:
+ break;
+ }
+ }}
+
+ >
+ );
+};
diff --git a/src/slidePane/index.md b/src/slidePane/index.md
index 3bd24d131..f3a13e93a 100644
--- a/src/slidePane/index.md
+++ b/src/slidePane/index.md
@@ -21,6 +21,7 @@ demo:
+
@@ -31,17 +32,19 @@ demo:
[AlertProps](https://4x-ant-design.antgroup.com/components/alert-cn/#API)
-| 参数 | 说明 | 类型 | 默认值 |
-| ------------- | ------------------------------ | ----------------------------------------------------- | --------- |
-| activeKeys | 右侧面板的内容的 Tabs 的选中项 | `string` | - |
-| banner | 提示 | `React.ReactNode \| AlertProps` | - |
-| bodyClassName | 内容容器的类名 | `string` | - |
-| bodyStyle | 内容容器的样式 | `CSSProperties` | - |
-| children | 右侧面板展示内容 | `(key: string) => React.ReactNode \| React.ReactNode` | - |
-| footer | 右侧面板的底部内容 | `React.ReactNode` | - |
-| size | 尺寸 | `'small' \| 'default' \| 'large'` | `default` |
-| tabs | 右侧面板的内容的 Tabs | `{ key: string; title: React.ReactNode }[]` | - |
-| title | 右侧面板的 title | `React.ReactNode` | - |
+| 参数 | 说明 | 类型 | 默认值 |
+| ------------- | ---------------------------------- | ----------------------------------------------------- | --------- |
+| activeKey | 右侧面板的内容的 Tabs 的选中项 | `string` | - |
+| banner | 提示 | `React.ReactNode \| AlertProps` | - |
+| bodyClassName | 内容容器的类名 | `string` | - |
+| bodyStyle | 内容容器的样式 | `CSSProperties` | - |
+| children | 右侧面板展示内容 | `(key: string) => React.ReactNode \| React.ReactNode` | - |
+| defaultKey | 右侧面板的内容的 Tabs 的默认选中项 | `string` | - |
+| footer | 右侧面板的底部内容 | `React.ReactNode` | - |
+| size | 尺寸 | `small \| default \| large` | `default` |
+| tabs | 右侧面板的内容的 Tabs | `{ key: string; title: React.ReactNode }[]` | - |
+| title | 右侧面板的 title | `React.ReactNode` | - |
+| onChange | 右侧面板的 Tabs 切换回调 | `(key: string) => void` | - |
:::info
其余属性继承 [antd4.x 的 Drawer](https://4x.ant.design/components/drawer-cn/#API)
diff --git a/src/slidePane/index.tsx b/src/slidePane/index.tsx
index 2e0c080f0..4e1cf0811 100644
--- a/src/slidePane/index.tsx
+++ b/src/slidePane/index.tsx
@@ -30,14 +30,24 @@ interface NormalSlidePane extends Omit {
interface TabsSlidePane extends Omit {
tabs?: T;
+ defaultKey?: TabKey;
activeKey?: TabKey;
children?: (key: TabKey) => React.ReactNode;
+ onChange?: (key: TabKey) => void;
}
function isFunction(props: any): props is TabsSlidePane {
return typeof props.children === 'function';
}
+function isTabMode(props: any): props is TabsSlidePane {
+ return props.tabs !== 'undefined';
+}
+
+function isControlled(props: any): props is TabsSlidePane {
+ return props.activeKey !== undefined;
+}
+
export type SlidePaneProps = TabsSlidePane | NormalSlidePane;
const getWidthFromSize = (size: NormalSlidePane['size']) => {
@@ -74,14 +84,16 @@ const SlidePane = (props: SlidePaneProps) => {
const composeOpen = open || visible;
const finalWidth = width ?? getWidthFromSize(size);
- const [tabKey, setTabKey] = useState('');
+ const [internalTabKey, setInternalTabKey] = useState('');
useEffect(() => {
composeOpen &&
- isFunction(props) &&
- setTabKey(props.activeKey || props.tabs?.[0]?.key || '');
+ isTabMode(props) &&
+ setInternalTabKey(props.defaultKey ?? props.tabs?.[0]?.key ?? '');
}, [composeOpen]);
+ const currentKey = isControlled(props) ? props.activeKey : internalTabKey;
+
const renderButton = () => {
return (
(props: SlidePaneProps) => {
);
};
+ const handleChangeKey = (key: TabKey) => {
+ !isControlled(props) && setInternalTabKey(key);
+ isTabMode(props) && props.onChange?.(key);
+ };
+
return (
(props: SlidePaneProps) => {
{isFunction(props) && (
{props.tabs?.map((tab: { key: string; title: React.ReactNode }) => (
@@ -130,7 +147,7 @@ const SlidePane = (props: SlidePaneProps) => {
className={classNames(`${slidePrefixCls}-body`, bodyClassName)}
style={bodyStyle}
>
- {typeof children === 'function' ? children(tabKey) : children}
+ {typeof children === 'function' ? children(currentKey ?? '') : children}
{footer ? (
{footer}
From 34418aa2819e0963d153d1a6a6090dde5597ba5b Mon Sep 17 00:00:00 2001
From: LuckyFBB <976060700@qq.com>
Date: Fri, 26 Apr 2024 10:42:18 +0800
Subject: [PATCH 2/3] fix(slidepane): update isTabMode judge
---
src/slidePane/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/slidePane/index.tsx b/src/slidePane/index.tsx
index 4e1cf0811..398cf6e9c 100644
--- a/src/slidePane/index.tsx
+++ b/src/slidePane/index.tsx
@@ -41,7 +41,7 @@ function isFunction(props: any): props is TabsSlidePane {
}
function isTabMode(props: any): props is TabsSlidePane {
- return props.tabs !== 'undefined';
+ return typeof props.tabs !== 'undefined';
}
function isControlled(props: any): props is TabsSlidePane {
From ee3538873f0701fa4029542bc8ef3c235f906f07 Mon Sep 17 00:00:00 2001
From: LuckyFBB <976060700@qq.com>
Date: Thu, 29 Aug 2024 18:38:45 +0800
Subject: [PATCH 3/3] fix(slidepane): change ts judge
---
src/slidePane/index.tsx | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/slidePane/index.tsx b/src/slidePane/index.tsx
index 398cf6e9c..a0d7f8f74 100644
--- a/src/slidePane/index.tsx
+++ b/src/slidePane/index.tsx
@@ -36,16 +36,16 @@ interface TabsSlidePane extends Omit) => void;
}
-function isFunction(props: any): props is TabsSlidePane {
+function isFunction(props: SlidePaneProps): props is TabsSlidePane {
return typeof props.children === 'function';
}
-function isTabMode(props: any): props is TabsSlidePane {
- return typeof props.tabs !== 'undefined';
+function isTabMode(props: SlidePaneProps): props is TabsSlidePane {
+ return 'tabs' in props;
}
-function isControlled(props: any): props is TabsSlidePane {
- return props.activeKey !== undefined;
+function isControlled(props: SlidePaneProps): props is TabsSlidePane {
+ return 'activeKey' in props;
}
export type SlidePaneProps = TabsSlidePane | NormalSlidePane;
@@ -74,7 +74,6 @@ const SlidePane = (props: SlidePaneProps) => {
title,
width,
size = 'default',
- children,
footer,
banner,
onClose,
@@ -131,7 +130,7 @@ const SlidePane = (props: SlidePaneProps) => {
{...(isValidBanner(banner) ? {} : omit(banner, 'message'))}
/>
)}
- {isFunction(props) && (
+ {isTabMode(props) && (
(props: SlidePaneProps) => {
className={classNames(`${slidePrefixCls}-body`, bodyClassName)}
style={bodyStyle}
>
- {typeof children === 'function' ? children(currentKey ?? '') : children}
+ {isFunction(props) ? props.children?.(currentKey ?? '') : props.children}
{footer ? (
{footer}