Skip to content

Commit

Permalink
feat: add closeOnBack to Popup, CenterPopup and other components bu…
Browse files Browse the repository at this point in the history
…ilt on them
  • Loading branch information
guoyunhe committed Nov 17, 2023
1 parent 671ea15 commit 1cd3e80
Show file tree
Hide file tree
Showing 22 changed files with 64 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/components/action-sheet/action-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type ActionSheetProps = {
onClose?: () => void
onMaskClick?: () => void
closeOnAction?: boolean
closeOnBack?: boolean
closeOnMaskClick?: boolean
safeArea?: boolean
popupClassName?: string
Expand All @@ -45,6 +46,7 @@ const defaultProps = {
actions: [],
cancelText: '',
closeOnAction: false,
closeOnBack: false,
closeOnMaskClick: true,
safeArea: true,
destroyOnClose: false,
Expand All @@ -64,6 +66,7 @@ export const ActionSheet: FC<ActionSheetProps> = p => {
props.onClose?.()
}
}}
closeOnBack={props.closeOnBack}
afterClose={props.afterClose}
className={classNames(`${classPrefix}-popup`, props.popupClassName)}
style={props.popupStyle}
Expand Down
1 change: 1 addition & 0 deletions src/components/action-sheet/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Triggered by user operation, it provides a set of two or more options related to
| afterClose | Triggered when completely closed | `() => void` | - |
| cancelText | The text of the cancel button , if it is null, the cancel button would not be displayed | `ReactNode` | - |
| closeOnAction | Whether to close after clicking the option | `boolean` | `false` |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `true` |
| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` |
| forceRender | Render content forcely | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/action-sheet/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
| afterClose | 完全关闭后触发 | `() => void` | - |
| cancelText | 取消按钮文字,如果设置为空则不显示取消按钮 | `ReactNode` | - |
| closeOnAction | 点击选项后是否关闭 | `boolean` | `false` |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `true` |
| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
| forceRender | 强制渲染内容 | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/calendar-picker/calendar-picker.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ When the user needs to enter a date, he can select it in the pop-up date panel.
| popupStyle | The custom style of the popup | `React.CSSProperties` | - |
| popupBodyStyle | The custom style of the popup body | `React.CSSProperties` | - |
| forceRender | Render content forcely,When ref is passed,always be true | `boolean` | `false` |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `true` |
| onClose | Triggered when closed | `() => void` | - |
| onMaskClick | Triggered when the mask is clicked | `() => void` | - |
Expand Down
3 changes: 3 additions & 0 deletions src/components/calendar-picker/calendar-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type CalendarPickerProps = CalendarPickerViewProps & {
popupStyle?: React.CSSProperties
popupBodyStyle?: React.CSSProperties
forceRender?: true
closeOnBack?: boolean
closeOnMaskClick?: boolean
onClose?: () => void
onMaskClick?: () => void
Expand Down Expand Up @@ -64,6 +65,7 @@ export const CalendarPicker = forwardRef<
popupStyle,
popupBodyStyle,
forceRender,
closeOnBack,
closeOnMaskClick,
onClose,
onConfirm,
Expand Down Expand Up @@ -117,6 +119,7 @@ export const CalendarPicker = forwardRef<
onClose?.()
}
}}
closeOnBack={closeOnBack}
>
<CalendarPickerView ref={calendarRef} {...calendarViewProps} />
{footer}
Expand Down
1 change: 1 addition & 0 deletions src/components/calendar-picker/calendar-picker.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
| popupStyle | 弹层容器的自定义样式 | `React.CSSProperties` | - |
| popupBodyStyle | 容器内部自定义样式 | `React.CSSProperties` | - |
| forceRender | 强制渲染内容,当传递 ref 时,会强制设为 true | `boolean` | `false` |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `true` |
| onClose | 关闭时触发 | `() => void` | - |
| onMaskClick | 点击背景蒙层时触发 | `() => void` | - |
Expand Down
17 changes: 16 additions & 1 deletion src/components/center-popup/center-popup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import type { FC, PropsWithChildren } from 'react'
import { renderToContainer } from '../../utils/render-to-container'
import Mask from '../mask'
Expand Down Expand Up @@ -144,6 +144,21 @@ export const CenterPopup: FC<CenterPopupProps> = p => {
)
)

useEffect(() => {
if (maskVisible && props.closeOnBack) {
const handlePopState = (e: PopStateEvent) => {

Check warning on line 149 in src/components/center-popup/center-popup.tsx

View workflow job for this annotation

GitHub Actions / check

'e' is defined but never used

Check warning on line 149 in src/components/center-popup/center-popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/center-popup/center-popup.tsx#L149

Added line #L149 was not covered by tests
// prevent history back
history.go(1)

Check warning on line 151 in src/components/center-popup/center-popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/center-popup/center-popup.tsx#L151

Added line #L151 was not covered by tests
// close popup instead
props.onClose?.()
}
window.addEventListener('popstate', handlePopState)
return () => {
window.removeEventListener('popstate', handlePopState)

Check warning on line 157 in src/components/center-popup/center-popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/center-popup/center-popup.tsx#L155-L157

Added lines #L155 - L157 were not covered by tests
}
}
}, [maskVisible])

return (
<ShouldRender
active={active}
Expand Down
2 changes: 2 additions & 0 deletions src/components/date-picker/date-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type DatePickerProps = Pick<
| 'onCancel'
| 'onClose'
| 'closeOnMaskClick'
| 'closeOnBack'
| 'visible'
| 'confirmText'
| 'cancelText'
Expand Down Expand Up @@ -135,6 +136,7 @@ export const DatePicker = forwardRef<DatePickerRef, DatePickerProps>(
value={pickerValue}
onCancel={props.onCancel}
onClose={props.onClose}
closeOnBack={props.closeOnBack}
closeOnMaskClick={props.closeOnMaskClick}
visible={props.visible}
confirmText={props.confirmText}
Expand Down
3 changes: 3 additions & 0 deletions src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ export type DialogProps = Pick<
onAction?: (action: Action, index: number) => void | Promise<void>
onClose?: () => void
closeOnAction?: boolean
closeOnBack?: boolean
closeOnMaskClick?: boolean
} & NativeProps

const defaultProps = {
actions: [] as Action[],
closeOnAction: false,
closeOnBack: false,
closeOnMaskClick: false,
getContainer: null,
}
Expand Down Expand Up @@ -109,6 +111,7 @@ export const Dialog: FC<DialogProps> = p => {
}
: undefined
}
closeOnBack={props.closeOnBack}
visible={props.visible}
getContainer={props.getContainer}
bodyStyle={props.bodyStyle}
Expand Down
1 change: 1 addition & 0 deletions src/components/dialog/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ When users need to process transactions, but do not want to jump to pages to int
| bodyClassName | `Dialog` content class name | `string` | - |
| bodyStyle | `Dialog` content style | `React.CSSProperties` | - |
| closeOnAction | Whether to close after clicking the operation button | `boolean` | `false` |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to support clicking the mask to close the dialog box | `boolean` | `false` |
| content | The content of the Dialog | `React.ReactNode` | - |
| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/dialog/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
| bodyClassName | `Dialog` 内容类名 | `string` | - |
| bodyStyle | `Dialog` 内容样式 | `React.CSSProperties` | - |
| closeOnAction | 点击操作按钮后后是否关闭 | `boolean` | `false` |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 是否支持点击遮罩关闭对话框 | `boolean` | `false` |
| content | 对话框内容 | `React.ReactNode` | - |
| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/modal/demos/demo1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export default () => {
Modal.show({
content: '点击遮罩关闭',
closeOnMaskClick: true,
closeOnBack: true,
})
}}
>
Expand Down
1 change: 1 addition & 0 deletions src/components/modal/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ When users need to process transactions, but do not want to jump to pages to int
| bodyClassName | `Modal` content class name | `string` | - |
| bodyStyle | `Modal` content style | `React.CSSProperties` | - |
| closeOnAction | Whether to close after clicking the operation button | `boolean` | `false` |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to support clicking the mask to close the modal box | `boolean` | `false` |
| content | The content of the Modal | `React.ReactNode` | - |
| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/modal/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
| bodyClassName | `Modal` 内容类名 | `string` | - |
| bodyStyle | `Modal` 内容样式 | `React.CSSProperties` | - |
| closeOnAction | 点击操作按钮后后是否关闭 | `boolean` | `false` |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 是否支持点击遮罩关闭弹窗 | `boolean` | `false` |
| content | 弹窗内容 | `React.ReactNode` | - |
| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
Expand Down
3 changes: 3 additions & 0 deletions src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ export type ModalProps = Pick<
onAction?: (action: Action, index: number) => void | Promise<void>
onClose?: () => void
closeOnAction?: boolean
closeOnBack?: boolean
closeOnMaskClick?: boolean
showCloseButton?: boolean
} & NativeProps

const defaultProps = {
actions: [] as Action[],
closeOnAction: false,
closeOnBack: false,
closeOnMaskClick: false,
getContainer: null,
}
Expand Down Expand Up @@ -99,6 +101,7 @@ export const Modal: FC<ModalProps> = p => {
afterClose={props.afterClose}
afterShow={props.afterShow}
showCloseButton={props.showCloseButton}
closeOnBack={props.closeOnBack}
closeOnMaskClick={props.closeOnMaskClick}
onClose={props.onClose}
visible={props.visible}
Expand Down
1 change: 1 addition & 0 deletions src/components/picker/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type PickerValueExtend = {
| --- | --- | --- | --- |
| cancelText | Text of the cancel button | `ReactNode` | `'取消'` |
| children | Render function of the selected options | `(items: PickerColumnItem[], actions: PickerActions) => ReactNode` | - |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `true` |
| columns | Options to configure each column | `PickerColumn[] \| ((value: PickerValue[]) => PickerColumn[])` | - |
| confirmText | Text of the ok button | `ReactNode` | `'确定'` |
Expand Down
1 change: 1 addition & 0 deletions src/components/picker/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type PickerValueExtend = {
| --- | --- | --- | --- |
| cancelText | 取消按钮的文字 | `ReactNode` | `'取消'` |
| children | 所选项的渲染函数 | `(items: PickerColumnItem[], actions: PickerActions) => ReactNode` | - |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `true` |
| columns | 配置每一列的选项 | `PickerColumn[] \| ((value: PickerValue[]) => PickerColumn[])` | - |
| confirmText | 确定按钮的文字 | `ReactNode` | `'确定'` |
Expand Down
3 changes: 3 additions & 0 deletions src/components/picker/picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type PickerProps = {
onConfirm?: (value: PickerValue[], extend: PickerValueExtend) => void
onCancel?: () => void
onClose?: () => void
closeOnBack?: boolean
closeOnMaskClick?: boolean
visible?: boolean
title?: ReactNode
Expand Down Expand Up @@ -78,6 +79,7 @@ export type PickerProps = {

const defaultProps = {
defaultValue: [],
closeOnBack: false,
closeOnMaskClick: true,
renderLabel: defaultRenderLabel,
destroyOnClose: false,
Expand Down Expand Up @@ -205,6 +207,7 @@ export const Picker = memo(
props.onCancel?.()
setVisible(false)
}}
closeOnBack={props.closeOnBack}
getContainer={props.getContainer}
destroyOnClose={props.destroyOnClose}
afterShow={props.afterShow}
Expand Down
1 change: 1 addition & 0 deletions src/components/popup/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ It is suitable for displaying pop-up windows, information prompts, selection inp
| bodyClassName | Content section class name | `string` | - |
| bodyStyle | Content section style | `React.CSSProperties` | - |
| className | Container class name | `string` | - |
| closeOnBack | Whether to close after clicking browser back button or use back swipe guesture | `boolean` | `false` |
| closeOnMaskClick | Whether to close after clicking the mask layer | `boolean` | `false` |
| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` |
| forceRender | Render content forcely | `boolean` | `false` |
Expand Down
1 change: 1 addition & 0 deletions src/components/popup/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
| bodyClassName | 内容区域类名 | `string` | - |
| bodyStyle | 内容区域样式 | `React.CSSProperties` | - |
| className | 容器类名 | `string` | - |
| closeOnBack | 点击后退按钮或滑动后退手势是否关闭 | `boolean` | `false` |
| closeOnMaskClick | 点击背景蒙层后是否关闭 | `boolean` | `false` |
| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
| forceRender | 强制渲染内容 | `boolean` | `false` |
Expand Down
2 changes: 2 additions & 0 deletions src/components/popup/popup-base-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type PopupBaseProps = {
afterShow?: () => void
bodyClassName?: string
bodyStyle?: CSSProperties
closeOnBack?: boolean
closeOnMaskClick?: boolean
destroyOnClose?: boolean
disableBodyScroll?: boolean
Expand All @@ -26,6 +27,7 @@ export type PopupBaseProps = {
}

export const defaultPopupBaseProps = {
closeOnBack: false,
closeOnMaskClick: false,
destroyOnClose: false,
disableBodyScroll: true,
Expand Down
17 changes: 16 additions & 1 deletion src/components/popup/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from 'classnames'
import React, { useState, useRef } from 'react'
import React, { useState, useRef, useEffect } from 'react'
import type { FC, PropsWithChildren } from 'react'
import { useIsomorphicLayoutEffect, useUnmountedRef } from 'ahooks'
import { NativeProps, withNativeProps } from '../../utils/native-props'
Expand Down Expand Up @@ -165,6 +165,21 @@ export const Popup: FC<PopupProps> = p => {
)
)

useEffect(() => {
if (maskVisible && props.closeOnBack) {
const handlePopState = () => {

Check warning on line 170 in src/components/popup/popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/popup/popup.tsx#L170

Added line #L170 was not covered by tests
// prevent history back
history.go(1)

Check warning on line 172 in src/components/popup/popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/popup/popup.tsx#L172

Added line #L172 was not covered by tests
// close popup instead
props.onClose?.()
}
window.addEventListener('popstate', handlePopState)
return () => {
window.removeEventListener('popstate', handlePopState)

Check warning on line 178 in src/components/popup/popup.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/popup/popup.tsx#L176-L178

Added lines #L176 - L178 were not covered by tests
}
}
}, [maskVisible])

return (
<ShouldRender
active={active}
Expand Down

0 comments on commit 1cd3e80

Please sign in to comment.