Skip to content

Commit

Permalink
Merge pull request #26 from js-tool-pack/pop-confirm
Browse files Browse the repository at this point in the history
PopConfirm
  • Loading branch information
mengxinssfd authored Jul 11, 2023
2 parents 95d146e + fd7e519 commit c506ef4
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/components/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
@import './resizer';
@import './word-balloon';
@import './tooltip';
@import './pop-confirm';
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export { PLACEMENTS, PLACEMENTS_8, PLACEMENTS_12 } from '@pkg/shared';
export * from './resizer';
export * from './word-balloon';
export * from './tooltip';
export * from './pop-confirm';
109 changes: 109 additions & 0 deletions packages/components/src/pop-confirm/PopConfirm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React, { useCallback, useEffect, useState } from 'react';
import type { PopConfirmProps } from './pop-confirm.types';
import { getComponentClass } from '@pkg/shared';
import type { RequiredPart } from '@tool-pack/types';
import { getClassNames, isPromiseLike } from '@tool-pack/basic';
import { Tooltip } from '../tooltip';
import { Layout, Footer, Main } from '../layouts';
import { Button } from '../button';
import { Space } from '../space';
import { Icon } from '../icon';
import { CircleInfoFill } from '@pkg/icons';

const rootName = getComponentClass('pop-confirm');

export const PopConfirm: React.FC<PopConfirmProps> = (props) => {
const {
icon,
onConfirm,
confirmText,
onCancel,
cancelText,
children,
content,
className,
...rest
} = props as RequiredPart<PopConfirmProps, keyof typeof defaultProps>;

const [visible, setVisible] = useState<boolean | undefined>();

useEffect(() => {
visible !== undefined && setVisible(undefined);
}, [visible]);

const handleCallback = (
res: ReturnType<Required<PopConfirmProps>['onConfirm']>,
) => {
const hide = () => setVisible(false);

if (isPromiseLike(res)) {
res.then(hide).catch();
return;
}
if (res === undefined || res) hide();
};

const _onCancel = useCallback(() => {
handleCallback(onCancel?.());
}, [onCancel]);
const _onConfirm = useCallback(() => {
handleCallback(onConfirm?.());
}, [onConfirm]);

const Content = (
<Layout vertical>
<Main className={`${rootName}__main`}>
<Space>
{icon !== null &&
(icon || (
<Icon className={`${rootName}__icon`}>
<CircleInfoFill />
</Icon>
))}
{content}
</Space>
</Main>
<Footer className={`${rootName}__footer`}>
<Space>
{cancelText !== null && (
<Button
type="info"
plain
className={`${rootName}__cancel`}
size="small"
onClick={_onCancel}>
{cancelText}
</Button>
)}
{confirmText !== null && (
<Button
type="primary"
className={`${rootName}__confirm`}
size="small"
onClick={_onConfirm}>
{confirmText}
</Button>
)}
</Space>
</Footer>
</Layout>
);

return (
<Tooltip
{...rest}
visible={visible}
className={getClassNames(rootName, className)}
title={Content}>
{children}
</Tooltip>
);
};

const defaultProps = {
trigger: 'click',
confirmText: '确认',
cancelText: '取消',
} satisfies Partial<PopConfirmProps>;
PopConfirm.defaultProps = defaultProps;
PopConfirm.displayName = 'PopConfirm';
17 changes: 17 additions & 0 deletions packages/components/src/pop-confirm/demo/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* title: 基础用法
* description: PopConfirm 基础用法。
*/

import React from 'react';
import { Button, PopConfirm } from '@tool-pack/react-ui';

const App: React.FC = () => {
return (
<PopConfirm content="确认要删除?">
<Button>删除</Button>
</PopConfirm>
);
};

export default App;
27 changes: 27 additions & 0 deletions packages/components/src/pop-confirm/demo/callback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* title: 事件回调
*/

import React from 'react';
import { Button, PopConfirm, useMessage } from '@tool-pack/react-ui';

const App: React.FC = () => {
const message = useMessage();
return (
<PopConfirm
content="确认要删除?"
onCancel={() => message.info('点击取消')}
onConfirm={() => {
message.info('确认删除,稍等...');
const p = new Promise<void>((resolve) => {
setTimeout(resolve, 1500);
});
p.then(() => message.success('删除成功!'));
return p;
}}>
<Button>删除</Button>
</PopConfirm>
);
};

export default App;
29 changes: 29 additions & 0 deletions packages/components/src/pop-confirm/demo/icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* title: icon
* description: 自定义 icon 或去除 icon。
*/

import React from 'react';
import { Button, Icon, Icons, PopConfirm, Space } from '@tool-pack/react-ui';

const App: React.FC = () => {
return (
<Space>
<PopConfirm
icon={
<Icon color="red">
<Icons.CircleWarningFill />
</Icon>
}
content="确认要删除?">
<Button>自定义图标</Button>
</PopConfirm>

<PopConfirm icon={null} content="确认要删除?">
<Button>无图标</Button>
</PopConfirm>
</Space>
);
};

export default App;
30 changes: 30 additions & 0 deletions packages/components/src/pop-confirm/demo/text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* title: 按钮
* description: 自定义按钮文本或去除按钮。
*/

import React from 'react';
import { Button, PopConfirm, Space } from '@tool-pack/react-ui';

const App: React.FC = () => {
return (
<Space>
<PopConfirm
confirmText="confirm"
cancelText="cancel"
content="确认要删除?">
<Button>自定义文案</Button>
</PopConfirm>

<PopConfirm cancelText={null} content="确认要删除?">
<Button>只有确认</Button>
</PopConfirm>

<PopConfirm confirmText={null} content="确认要删除?">
<Button>只有取消</Button>
</PopConfirm>
</Space>
);
};

export default App;
17 changes: 17 additions & 0 deletions packages/components/src/pop-confirm/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@import '../scss.variable';

$r: '#{$prefix}pop-confirm';
$space: '#{$prefix}space';

.#{$r} {
width: 180px;
&__icon {
color: var(--t-color-warning);
}
&__footer {
margin-top: 12px;
.#{$space} {
justify-content: flex-end;
}
}
}
2 changes: 2 additions & 0 deletions packages/components/src/pop-confirm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { PopConfirmProps } from './pop-confirm.types';
export * from './PopConfirm';
42 changes: 42 additions & 0 deletions packages/components/src/pop-confirm/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
category: Components
title: PopConfirm 气泡确认框
atomId: PopConfirm
demo:
cols: 2
group:
title: 反馈
---

PopConfirm 气泡确认框。

## 代码演示

<!-- prettier-ignore -->
<code src="./demo/basic.tsx"></code>
<code src="./demo/icon.tsx"></code>
<code src="./demo/text.tsx"></code>
<code src="./demo/callback.tsx"></code>

## API

PopConfirm 的属性说明如下:

content?: React.ReactNode;
confirmText?: string | null;
onConfirm?: () => boolean | Promise<void> | void;
cancelText?: string | null;
onCancel?: () => boolean | Promise<void> | void;
icon?: React.ReactNode;

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| ----------- | ----------------------------------------------------------------------------------------- | -------------------------------------- | ------- | ---- |
| content | 内容 | React.ReactNode | -- | -- |
| confirmText | 确认按钮文案,当值为 null 时,不显示确认按钮 | string \| null | '确认' | -- |
| onConfirm | 点击确认按钮时的回调,当回调返回值是 false 或者返回的 promise 的值是 false 则停止关闭窗体 | () => boolean \| Promise<void> \| void | -- | -- |
| cancelText | 取消按钮文案,当值为 null 时,不显示取消按钮 | string \| null | '取消' | -- |
| onCancel | 点击取消按钮时的回调,当回调返回值是 false 或者返回的 promise 的值是 false 则停止关闭窗体 | () => boolean \| Promise<void> \| void | -- | -- |
| icon | 自定义 icon,如果为 null 则不显示 icon | React.ReactNode | -- | -- |
| trigger |[tooltip](./tooltip#api) | -- | 'click' | -- |

更多说明见[tooltip](./tooltip#api)
15 changes: 15 additions & 0 deletions packages/components/src/pop-confirm/pop-confirm.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { TooltipProps } from '../tooltip';

export type PopConfirmProps = Omit<
React.HTMLAttributes<HTMLElement>,
'children'
> &
TooltipProps & {
content?: React.ReactNode;
confirmText?: string | null;
onConfirm?: () => boolean | Promise<void> | void;
cancelText?: string | null;
onCancel?: () => boolean | Promise<void> | void;
icon?: React.ReactNode;
};
2 changes: 1 addition & 1 deletion packages/components/src/tooltip/Tooltip.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export function useShowController(
cancellers.forEach((i) => i());
cancellers.length = 0;
};
}, [children, trigger, disabled]);
}, [children, trigger, disabled, visible]);

const cancelListRef = useRef<Array<() => void>>([]);

Expand Down
2 changes: 1 addition & 1 deletion scripts/new-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const rootName = getComponentClass('${config.name}');
export const ${componentName}: React.FC<${props}> = (props) => {
const { children, className, ...rest } = props as RequiredPart<
TooltipProps,
${props},
keyof typeof defaultProps
>;
return (
Expand Down

0 comments on commit c506ef4

Please sign in to comment.