Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/packages/popup/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,7 @@ import { Popup } from '@nutui/nutui-react-taro'
| \--nutui-popup-title-height | 标题栏的高度 | `50px` |
| \--nutui-popup-title-border-bottom | 标题栏底部边框 | `0` |
| \--nutui-popup-animation-duration | 弹框动画的延时 | `0.3s` |

## FAQ

在 iOS 下,有时候 `lockScroll` 可能不生效,此刻在打开 `popup` 时,可将宿主页面的样式增加 `overflow: hidden;`,关闭弹层时,再重置样式。
74 changes: 22 additions & 52 deletions src/packages/popup/popup.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { createPortal } from 'react-dom'
import { CSSTransition } from 'react-transition-group'
import classNames from 'classnames'
import { Close } from '@nutui/icons-react-taro'
import { EnterHandler, ExitHandler } from 'react-transition-group/Transition'
import { View, ITouchEvent } from '@tarojs/components'
import {
OverlayProps,
Expand Down Expand Up @@ -108,34 +107,21 @@ export const Popup: FunctionComponent<
const [transitionName, setTransitionName] = useState('')
const refObject = useLockScrollTaro(innerVisible && lockScroll)
const classPrefix = 'nut-popup'
const baseStyle = {
zIndex: index,
}

const overlayStyles = {
...overlayStyle,
'--nutui-overlay-zIndex': index,
}

const popStyles = {
...style,
...baseStyle,
}

const popStyles = { ...style, zIndex: index }
const popClassName = classNames(
classPrefix,
{
[`${classPrefix}`]: true,
[`${classPrefix}-round`]: round || position === 'bottom',
[`${classPrefix}-${position}`]: true,
},
className
)

const closeClasses = classNames({
[`${classPrefix}-title-right`]: true,
[`${classPrefix}-title-right-${closeIconPosition}`]: true,
})

const open = () => {
if (!innerVisible) {
setInnerVisible(true)
Expand All @@ -159,40 +145,26 @@ export const Popup: FunctionComponent<
}
}

const onHandleClickOverlay = (e: ITouchEvent) => {
const handleOverlayClick = (e: ITouchEvent) => {
e.stopPropagation()
if (closeOnOverlayClick) {
const closed = onOverlayClick && onOverlayClick(e)
closed && close()
if (closeOnOverlayClick && onOverlayClick(e)) {
close()
}
}

const onHandleClick = (e: ITouchEvent) => {
onClick && onClick(e)
}

const onHandleClickCloseIcon = (e: ITouchEvent) => {
const closed = onCloseIconClick && onCloseIconClick(e)
closed && close()
}

const onHandleOpened: EnterHandler<HTMLElement | undefined> | undefined = (
e: HTMLElement
) => {
afterShow && afterShow()
}

const onHandleClosed: ExitHandler<HTMLElement | undefined> | undefined = (
e: HTMLElement
) => {
afterClose && afterClose()
const handleCloseIconClick = (e: ITouchEvent) => {
onCloseIconClick(e) && close()
}

const renderCloseIcon = () => {
const closeClasses = classNames(
`${classPrefix}-title-right`,
`${classPrefix}-title-right-${closeIconPosition}`
)
return (
<>
{closeable && (
<View className={closeClasses} onClick={onHandleClickCloseIcon}>
<View className={closeClasses} onClick={handleCloseIconClick}>
{React.isValidElement(closeIcon) ? closeIcon : <Close />}
</View>
)}
Expand Down Expand Up @@ -244,18 +216,18 @@ export const Popup: FunctionComponent<
unmountOnExit={destroyOnClose}
timeout={duration}
in={innerVisible}
onEntered={onHandleOpened}
onExited={onHandleClosed}
onEntered={afterShow}
onExited={afterClose}
>
<View
ref={refObject}
style={popStyles}
className={popClassName}
onClick={onHandleClick}
onClick={onClick}
catchMove={lockScroll}
>
{renderTitle()}
{showChildren ? children : ''}
{showChildren ? children : null}
</View>
</CSSTransition>
)
Expand All @@ -264,17 +236,17 @@ export const Popup: FunctionComponent<
const renderNode = () => {
return (
<>
{overlay ? (
{overlay && (
<Overlay
style={overlayStyles}
className={overlayClassName}
visible={innerVisible}
closeOnOverlayClick={closeOnOverlayClick}
lockScroll={lockScroll}
duration={duration}
onClick={onHandleClickOverlay}
onClick={handleOverlayClick}
/>
) : null}
)}
{renderPop()}
</>
)
Expand All @@ -288,11 +260,9 @@ export const Popup: FunctionComponent<
setTransitionName(transition || `${classPrefix}-slide-${position}`)
}, [position, transition])

const resolveContainer = (getContainer: Teleport | undefined) => {
const container =
typeof getContainer === 'function' ? getContainer() : getContainer
return container || document.body
}
const resolveContainer = (getContainer: Teleport | undefined) =>
(typeof getContainer === 'function' ? getContainer() : getContainer) ||
document.body

const renderToContainer = (getContainer: Teleport, node: ReactElement) => {
if (getContainer) {
Expand Down
83 changes: 24 additions & 59 deletions src/packages/popup/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, {
FunctionComponent,
MouseEvent,
MouseEventHandler,
ReactElement,
ReactNode,
ReactPortal,
Expand All @@ -12,7 +11,6 @@ import { createPortal } from 'react-dom'
import { CSSTransition } from 'react-transition-group'
import classNames from 'classnames'
import { Close } from '@nutui/icons-react'
import { EnterHandler, ExitHandler } from 'react-transition-group/Transition'
import { defaultOverlayProps, OverlayProps } from '@/packages/overlay/overlay'
import Overlay from '@/packages/overlay'
import { ComponentDefaults } from '@/utils/typings'
Expand Down Expand Up @@ -98,45 +96,30 @@ export const Popup: FunctionComponent<
afterClose,
onClick,
} = { ...defaultProps, ...props }
const nodeRef = React.useRef(null)
const nodeRef = React.useRef<HTMLDivElement | null>(null)
let innerIndex = zIndex || _zIndex
const [index, setIndex] = useState(innerIndex)
const [innerVisible, setInnerVisible] = useState(visible)
const [showChildren, setShowChildren] = useState(true)
const [transitionName, setTransitionName] = useState('')

const shouldLockScroll = !innerVisible ? false : lockScroll
useLockScroll(nodeRef, shouldLockScroll)
useLockScroll(nodeRef, innerVisible && lockScroll)

const classPrefix = 'nut-popup'
const baseStyle = {
zIndex: index,
}

const overlayStyles = {
...overlayStyle,
'--nutui-overlay-zIndex': index,
}

const popStyles = {
...style,
...baseStyle,
}

const popStyles = { ...style, zIndex: index }
const popClassName = classNames(
classPrefix,
{
[`${classPrefix}`]: true,
[`${classPrefix}-round`]: round || position === 'bottom',
[`${classPrefix}-${position}`]: true,
},
className
)

const closeClasses = classNames({
[`${classPrefix}-title-right`]: true,
[`${classPrefix}-title-right-${closeIconPosition}`]: true,
})

const open = () => {
if (!innerVisible) {
setInnerVisible(true)
Expand All @@ -160,42 +143,26 @@ export const Popup: FunctionComponent<
}
}

const onHandleClickOverlay = (e: MouseEvent) => {
const handleOverlayClick = (e: MouseEvent) => {
e.stopPropagation()
if (closeOnOverlayClick) {
const closed = onOverlayClick && onOverlayClick(e)
closed && close()
if (closeOnOverlayClick && onOverlayClick(e)) {
close()
}
}

const onHandleClick: MouseEventHandler<HTMLDivElement> = (e: MouseEvent) => {
onClick && onClick(e)
}

const onHandleClickCloseIcon: MouseEventHandler<HTMLDivElement> = (
e: MouseEvent
) => {
const closed = onCloseIconClick && onCloseIconClick(e)
closed && close()
}

const onHandleOpened: EnterHandler<HTMLElement | undefined> | undefined = (
e: HTMLElement
) => {
afterShow && afterShow()
}

const onHandleClosed: ExitHandler<HTMLElement | undefined> | undefined = (
e: HTMLElement
) => {
afterClose && afterClose()
const handleCloseIconClick = (e: MouseEvent) => {
onCloseIconClick(e) && close()
}

const renderCloseIcon = () => {
const closeClasses = classNames(
`${classPrefix}-title-right`,
`${classPrefix}-title-right-${closeIconPosition}`
)
return (
<>
{closeable && (
<div className={closeClasses} onClick={onHandleClickCloseIcon}>
<div className={closeClasses} onClick={handleCloseIconClick}>
{React.isValidElement(closeIcon) ? closeIcon : <Close />}
</div>
)}
Expand Down Expand Up @@ -245,17 +212,17 @@ export const Popup: FunctionComponent<
unmountOnExit={destroyOnClose}
timeout={duration}
in={innerVisible}
onEntered={onHandleOpened}
onExited={onHandleClosed}
onEntered={afterShow}
onExited={afterClose}
>
<div
ref={nodeRef}
style={popStyles}
className={popClassName}
onClick={onHandleClick}
onClick={onClick}
>
{renderTitle()}
{showChildren ? children : ''}
{showChildren ? children : null}
</div>
</CSSTransition>
)
Expand All @@ -264,17 +231,17 @@ export const Popup: FunctionComponent<
const renderNode = () => {
return (
<>
{overlay ? (
{overlay && (
<Overlay
style={overlayStyles}
className={overlayClassName}
visible={innerVisible}
closeOnOverlayClick={closeOnOverlayClick}
lockScroll={lockScroll}
duration={duration}
onClick={onHandleClickOverlay}
onClick={handleOverlayClick}
/>
) : null}
)}
{renderPop()}
</>
)
Expand All @@ -288,11 +255,9 @@ export const Popup: FunctionComponent<
setTransitionName(transition || `${classPrefix}-slide-${position}`)
}, [position, transition])

const resolveContainer = (getContainer: Teleport | undefined) => {
const container =
typeof getContainer === 'function' ? getContainer() : getContainer
return container || document.body
}
const resolveContainer = (getContainer: Teleport | undefined) =>
(typeof getContainer === 'function' ? getContainer() : getContainer) ||
document.body

const renderToContainer = (getContainer: Teleport, node: ReactElement) => {
if (getContainer) {
Expand Down