Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dialog): 增加关闭按钮 #1872

Merged
merged 13 commits into from
Jan 19, 2024
38 changes: 38 additions & 0 deletions src/packages/dialog/__test__/dialog.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,41 @@ test('dialog cancelText confirmText', async () => {
expect(footerOkEle).toHaveTextContent('确定文案自定义')
expect(footerCancelEle).toHaveTextContent('取消文案自定义')
})

test('dialog closeIcon equals true', async () => {
const { container } = render(
<Dialog
visible
cancelText="取消文案自定义"
confirmText="确定文案自定义"
closeIcon
/>
)

const closeBtn = container.querySelector('.nut-dialog-close')
expect(closeBtn).toBeInTheDocument()
})

test('dialog close icon position adjustment', async () => {
const onClose = jest.fn()
const onCancel = jest.fn()
const { container } = render(
<Dialog
visible
cancelText="取消文案自定义"
confirmText="确定文案自定义"
closeIcon
closeIconPosition="top-left"
onClose={onClose}
onCancel={onCancel}
/>
)

const closeBtn = container.querySelector(
'.nut-dialog-close-top-left'
) as HTMLElement
expect(closeBtn).toBeInTheDocument()
fireEvent.click(closeBtn)
expect(onClose).toBeCalled()
expect(onCancel).toBeCalled()
})
16 changes: 10 additions & 6 deletions src/packages/dialog/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export type DialogConfigType = {
simple?: boolean
}

export interface BasicDialogProps extends BasicComponent {
export type DialogCloseIconPositionType = 'top-right' | 'top-left'

export interface DialogBasicProps extends BasicComponent {
visible?: boolean
title?: ReactNode
content?: ReactNode
Expand All @@ -22,6 +24,8 @@ export interface BasicDialogProps extends BasicComponent {
closeOnOverlayClick?: boolean
footerDirection?: string
lockScroll?: boolean
closeIconPosition?: DialogCloseIconPositionType
closeIcon?: boolean | ReactNode
beforeClose?: () => boolean
beforeCancel?: () => boolean
onClose?: () => void
Expand All @@ -32,21 +36,21 @@ export interface BasicDialogProps extends BasicComponent {
}

export type DialogReturnProps = {
update: (newConfig: ConfirmProps) => void
update: (newConfig: DialogConfirmProps) => void
close: () => void
}

export interface ConfirmProps extends BasicDialogProps {
export interface DialogConfirmProps extends DialogBasicProps {
content?: ReactNode
icon?: ReactNode | null
isNotice?: boolean
noticeType?: string
}

export interface DialogComponent
extends ForwardRefExoticComponent<PropsWithChildren<BasicDialogProps>> {
confirm: (props: ConfirmProps) => DialogReturnProps
alert: (props: ConfirmProps) => DialogReturnProps
extends ForwardRefExoticComponent<PropsWithChildren<DialogBasicProps>> {
confirm: (props: DialogConfirmProps) => DialogReturnProps
alert: (props: DialogConfirmProps) => DialogReturnProps
config: (config: DialogConfigType) => void
destroyAll: () => void
}
Expand Down
18 changes: 10 additions & 8 deletions src/packages/dialog/confirm.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react'
import { Dialog } from './dialog'
import { destroyList, ConfirmProps, DialogReturnProps } from './config'
import { destroyList, DialogConfirmProps, DialogReturnProps } from './config'
import { render as reactRender, unmount } from '@/utils/render'

function ConfirmDialog(props: ConfirmProps) {
function ConfirmDialog(props: DialogConfirmProps) {
return <Dialog {...props}>{props.content}</Dialog>
}

// 如果是消息提示型弹出框,那么只有确认按钮
export const normalizeConfig = (config: ConfirmProps): ConfirmProps => {
export const normalizeConfig = (
config: DialogConfirmProps
): DialogConfirmProps => {
if (config.isNotice) {
let { icon } = config
if (!icon && icon !== null) {
Expand All @@ -26,18 +28,18 @@ export const normalizeConfig = (config: ConfirmProps): ConfirmProps => {
}

const confirm = (
config: ConfirmProps,
renderFunc?: (props: ConfirmProps) => void
config: DialogConfirmProps,
renderFunc?: (props: DialogConfirmProps) => void
): DialogReturnProps => {
const div = document.createElement('div')
document.body.appendChild(div)

let dialogConfig: ConfirmProps = {
let dialogConfig: DialogConfirmProps = {
...config,
visible: false,
}

const render = (props: ConfirmProps, callback?: () => any) => {
const render = (props: DialogConfirmProps, callback?: () => any) => {
reactRender(<ConfirmDialog {...props} onCancel={() => onCancel()} />, div)
callback && callback()
}
Expand Down Expand Up @@ -95,7 +97,7 @@ const confirm = (
})
}

const update = (newConfig: ConfirmProps) => {
const update = (newConfig: DialogConfirmProps) => {
dialogConfig = {
...dialogConfig,
title: config.title, // 避免 newConfig 未传递 title 时,icon 出现多个的问题
Expand Down
15 changes: 13 additions & 2 deletions src/packages/dialog/content.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface ContentProps extends BasicComponent {
title: ReactNode
header: ReactNode
footer: ReactNode
close: ReactNode
footerDirection: string
onClick: (event: ITouchEvent) => void
}
Expand All @@ -16,10 +17,19 @@ export const Content: FunctionComponent<
Partial<ContentProps> &
Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'title'>
> = (props) => {
const { visible, title, header, footer, footerDirection, onClick, children } =
props
const {
visible,
title,
header,
footer,
close,
footerDirection,
onClick,
children,
} = props

const classPrefix = 'nut-dialog'

const renderHeader = () => {
return title ? <div className={`${classPrefix}-header`}>{title}</div> : null
}
Expand All @@ -46,6 +56,7 @@ export const Content: FunctionComponent<
style={props.style}
onClick={(e) => handleClick(e)}
>
{close}
{header}
<div
className={classPrefix}
Expand Down
14 changes: 12 additions & 2 deletions src/packages/dialog/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ interface ContentProps {
title: ReactNode
header: ReactNode
footer: ReactNode
close: ReactNode
footerDirection: string
}

export const Content: FunctionComponent<
Partial<ContentProps> & HTMLAttributes<HTMLDivElement>
> = (props) => {
const { visible, title, header, footer, footerDirection, onClick, children } =
props
const {
visible,
title,
header,
footer,
close,
footerDirection,
onClick,
children,
} = props

const classPrefix = 'nut-dialog'

Expand Down Expand Up @@ -43,6 +52,7 @@ export const Content: FunctionComponent<
style={props.style}
onClick={(e) => handleClick(e)}
>
{close}
{header}
<div
className={classPrefix}
Expand Down
48 changes: 48 additions & 0 deletions src/packages/dialog/demo.taro.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react'
import Taro from '@tarojs/taro'
import { ArrowCornerLeft } from '@nutui/icons-react-taro'
import { Dialog, Cell, Image } from '@/packages/nutui.react.taro'
import { useTranslate } from '@/sites/assets/locale/taro'
import Header from '@/sites/components/header'
Expand All @@ -20,6 +21,8 @@ interface T {
confirmText: string
cancelText: string
header: string
closeIcon: string
customClose: string
}

const DialogDemo = () => {
Expand All @@ -40,6 +43,8 @@ const DialogDemo = () => {
confirmText: '确定',
cancelText: '取消',
header: '顶部带插图',
closeIcon: '顶部带关闭按钮',
customClose: '自定义顶部关闭按钮',
},
'en-US': {
basic: 'Basic Usage',
Expand All @@ -58,6 +63,8 @@ const DialogDemo = () => {
confirmText: 'confirm',
cancelText: 'cancel',
header: 'Top with illustration',
closeIcon: 'Top with close button',
customClose: 'Customize the top close button',
},
})

Expand All @@ -69,6 +76,9 @@ const DialogDemo = () => {
const [visible6, setVisible6] = useState(false)
const [visible7, setVisible7] = useState(false)
const [visible8, setVisible8] = useState(false)
const [visible9, setVisible9] = useState(false)
const [visible10, setVisible10] = useState(false)

return (
<>
<Header />
Expand Down Expand Up @@ -191,6 +201,44 @@ const DialogDemo = () => {
>
{translated.content}
</Dialog>
<Cell
title={translated.closeIcon}
onClick={() => {
setVisible9(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.closeIcon}
visible={visible9}
closeIcon
onConfirm={() => setVisible9(false)}
onCancel={() => setVisible9(false)}
>
{translated.content}
</Dialog>
<Cell
title={translated.customClose}
onClick={() => {
setVisible10(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.customClose}
visible={visible10}
closeIcon={<ArrowCornerLeft width="16px" height="16px" />}
closeIconPosition="top-left"
onConfirm={() => setVisible10(false)}
onCancel={() => setVisible10(false)}
style={{
'--nutui-dialog-close-top': '10px',
'--nutui-dialog-close-left': '10px',
'--nutui-dialog-close-color': 'red',
}}
>
{translated.content}
</Dialog>
</div>
</>
)
Expand Down
47 changes: 47 additions & 0 deletions src/packages/dialog/demo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react'
import { ArrowCornerLeft } from '@nutui/icons-react'
import { Dialog } from './dialog'
import Cell from '../cell'
import { useTranslate } from '@/sites/assets/locale'
Expand All @@ -21,6 +22,8 @@ interface T {
confirmText: string
cancelText: string
header: string
closeIcon: string
customClose: string
}

const DialogDemo = () => {
Expand All @@ -42,6 +45,8 @@ const DialogDemo = () => {
confirmText: '确定',
cancelText: '取消',
header: '顶部带插图',
closeIcon: '顶部带关闭按钮',
customClose: '自定义顶部关闭按钮',
},
'en-US': {
funUse: 'Function use',
Expand All @@ -61,6 +66,8 @@ const DialogDemo = () => {
confirmText: 'confirm',
cancelText: 'cancel',
header: 'Top with illustration',
closeIcon: 'Top with close button',
customClose: 'Customize the top close button',
},
})

Expand All @@ -71,6 +78,8 @@ const DialogDemo = () => {
const [visible5, setVisible5] = useState(false)
const [visible6, setVisible6] = useState(false)
const [visible7, setVisible7] = useState(false)
const [visible8, setVisible8] = useState(false)
const [visible9, setVisible9] = useState(false)

return (
<>
Expand Down Expand Up @@ -264,6 +273,44 @@ const DialogDemo = () => {
>
{translated.content}
</Dialog>
<Cell
title={translated.closeIcon}
onClick={() => {
setVisible8(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.closeIcon}
visible={visible8}
closeIcon
onConfirm={() => setVisible8(false)}
onCancel={() => setVisible8(false)}
>
{translated.content}
</Dialog>
<Cell
title={translated.customClose}
onClick={() => {
setVisible9(true)
}}
/>
<Dialog
className="test-dialog"
title={translated.customClose}
visible={visible9}
closeIcon={<ArrowCornerLeft width="16px" height="16px" />}
closeIconPosition="top-left"
onConfirm={() => setVisible9(false)}
onCancel={() => setVisible9(false)}
style={{
'--nutui-dialog-close-top': '10px',
'--nutui-dialog-close-left': '10px',
'--nutui-dialog-close-color': 'red',
}}
>
{translated.content}
</Dialog>
</div>
</>
)
Expand Down
Loading
Loading