mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-09 21:25:45 +08:00
118 lines
3.2 KiB
TypeScript
118 lines
3.2 KiB
TypeScript
import { CloseIcon } from '@blocksuite/icons';
|
|
import type {
|
|
DialogContentProps,
|
|
DialogOverlayProps,
|
|
DialogPortalProps,
|
|
DialogProps,
|
|
} from '@radix-ui/react-dialog';
|
|
import * as Dialog from '@radix-ui/react-dialog';
|
|
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
|
import clsx from 'clsx';
|
|
import type { CSSProperties } from 'react';
|
|
import { forwardRef } from 'react';
|
|
|
|
import type { IconButtonProps } from '../button';
|
|
import { IconButton } from '../button';
|
|
import * as styles from './styles.css';
|
|
|
|
export interface ModalProps extends DialogProps {
|
|
width?: CSSProperties['width'];
|
|
height?: CSSProperties['height'];
|
|
minHeight?: CSSProperties['minHeight'];
|
|
title?: React.ReactNode;
|
|
description?: React.ReactNode;
|
|
withoutCloseButton?: boolean;
|
|
|
|
portalOptions?: DialogPortalProps;
|
|
contentOptions?: DialogContentProps;
|
|
overlayOptions?: DialogOverlayProps;
|
|
closeButtonOptions?: IconButtonProps;
|
|
}
|
|
|
|
const getVar = (style: number | string = '', defaultValue = '') => {
|
|
return style
|
|
? typeof style === 'number'
|
|
? `${style}px`
|
|
: style
|
|
: defaultValue;
|
|
};
|
|
|
|
export const Modal = forwardRef<HTMLDivElement, ModalProps>(
|
|
(
|
|
{
|
|
width,
|
|
height,
|
|
minHeight = 194,
|
|
title,
|
|
description,
|
|
withoutCloseButton = false,
|
|
|
|
portalOptions,
|
|
contentOptions: {
|
|
style: contentStyle,
|
|
className: contentClassName,
|
|
...otherContentOptions
|
|
} = {},
|
|
overlayOptions: {
|
|
className: overlayClassName,
|
|
...otherOverlayOptions
|
|
} = {},
|
|
closeButtonOptions = {},
|
|
children,
|
|
...props
|
|
},
|
|
ref
|
|
) => (
|
|
<Dialog.Root {...props}>
|
|
<Dialog.Portal {...portalOptions}>
|
|
<Dialog.Overlay
|
|
className={clsx(styles.modalOverlay, overlayClassName)}
|
|
{...otherOverlayOptions}
|
|
/>
|
|
<div className={styles.modalContentWrapper}>
|
|
<Dialog.Content
|
|
className={clsx(styles.modalContent, contentClassName)}
|
|
style={{
|
|
...assignInlineVars({
|
|
[styles.widthVar]: getVar(width, '50vw'),
|
|
[styles.heightVar]: getVar(height, 'unset'),
|
|
[styles.minHeightVar]: getVar(minHeight, '26px'),
|
|
}),
|
|
...contentStyle,
|
|
}}
|
|
{...otherContentOptions}
|
|
ref={ref}
|
|
>
|
|
{withoutCloseButton ? null : (
|
|
<Dialog.Close asChild>
|
|
<IconButton
|
|
className={styles.closeButton}
|
|
aria-label="Close"
|
|
type="plain"
|
|
{...closeButtonOptions}
|
|
>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Dialog.Close>
|
|
)}
|
|
{title ? (
|
|
<Dialog.Title className={styles.modalHeader}>
|
|
{title}
|
|
</Dialog.Title>
|
|
) : null}
|
|
{description ? (
|
|
<Dialog.Description className={styles.modalDescription}>
|
|
{description}
|
|
</Dialog.Description>
|
|
) : null}
|
|
|
|
{children}
|
|
</Dialog.Content>
|
|
</div>
|
|
</Dialog.Portal>
|
|
</Dialog.Root>
|
|
)
|
|
);
|
|
|
|
Modal.displayName = 'Modal';
|