feishin/src/shared/components/modal/modal.tsx

146 lines
3.9 KiB
TypeScript
Raw Normal View History

import { Modal as MantineModal, ModalProps as MantineModalProps } from '@mantine/core';
2023-01-03 00:12:07 -08:00
import { closeAllModals, ContextModalProps } from '@mantine/modals';
import {
ModalsProvider as MantineModalsProvider,
ModalsProviderProps as MantineModalsProviderProps,
} from '@mantine/modals';
import React, { ReactNode } from 'react';
import styles from './modal.module.css';
import { Button } from '/@/shared/components/button/button';
import { Flex } from '/@/shared/components/flex/flex';
import { Group } from '/@/shared/components/group/group';
import { Icon } from '/@/shared/components/icon/icon';
import { Stack } from '/@/shared/components/stack/stack';
2022-12-19 15:59:14 -08:00
export interface ModalProps extends Omit<MantineModalProps, 'onClose'> {
2023-07-01 19:10:05 -07:00
children?: ReactNode;
handlers: {
close: () => void;
open: () => void;
toggle: () => void;
};
2022-12-19 15:59:14 -08:00
}
export const Modal = ({ children, classNames, handlers, ...rest }: ModalProps) => {
2023-07-01 19:10:05 -07:00
return (
<MantineModal
{...rest}
classNames={{
body: styles.body,
content: styles.content,
header: styles.header,
root: styles.root,
title: styles.title,
...classNames,
}}
2023-07-01 19:10:05 -07:00
onClose={handlers.close}
radius="lg"
transitionProps={{
duration: 300,
exitDuration: 300,
transition: 'fade',
}}
2023-07-01 19:10:05 -07:00
>
{children}
</MantineModal>
);
2022-12-19 15:59:14 -08:00
};
export type ContextModalVars = {
2023-07-01 19:10:05 -07:00
context: ContextModalProps['context'];
id: ContextModalProps['id'];
2022-12-19 15:59:14 -08:00
};
export const BaseContextModal = ({
2023-07-01 19:10:05 -07:00
context,
id,
innerProps,
2022-12-19 15:59:14 -08:00
}: ContextModalProps<{
2023-07-01 19:10:05 -07:00
modalBody: (vars: ContextModalVars) => React.ReactNode;
2022-12-19 15:59:14 -08:00
}>) => <>{innerProps.modalBody({ context, id })}</>;
2023-01-03 00:12:07 -08:00
interface ConfirmModalProps {
2023-07-01 19:10:05 -07:00
children: ReactNode;
disabled?: boolean;
labels?: {
cancel?: string;
confirm?: string;
};
loading?: boolean;
onCancel?: () => void;
onConfirm: () => void;
2023-01-03 00:12:07 -08:00
}
export const ConfirmModal = ({
children,
2023-07-01 19:10:05 -07:00
disabled,
labels,
loading,
2023-07-01 19:10:05 -07:00
onCancel,
onConfirm,
}: ConfirmModalProps) => {
2023-07-01 19:10:05 -07:00
const handleCancel = () => {
if (onCancel) {
onCancel();
} else {
closeAllModals();
}
};
2023-01-03 00:12:07 -08:00
2023-07-01 19:10:05 -07:00
return (
<Stack>
<Flex>{children}</Flex>
<Group justify="flex-end">
2023-07-01 19:10:05 -07:00
<Button
data-focus
onClick={handleCancel}
variant="default"
2023-07-01 19:10:05 -07:00
>
{labels?.cancel ? labels.cancel : 'Cancel'}
</Button>
<Button
disabled={disabled}
loading={loading}
onClick={onConfirm}
variant="filled"
2023-07-01 19:10:05 -07:00
>
{labels?.confirm ? labels.confirm : 'Confirm'}
</Button>
</Group>
</Stack>
);
2023-01-03 00:12:07 -08:00
};
export interface ModalsProviderProps extends MantineModalsProviderProps {}
export const ModalsProvider = ({ children, ...rest }: ModalsProviderProps) => {
return (
<MantineModalsProvider
modalProps={{
centered: true,
classNames: {
body: styles.body,
content: styles.content,
header: styles.header,
root: styles.root,
title: styles.title,
},
closeButtonProps: {
icon: <Icon icon="x" />,
},
radius: 'lg',
transitionProps: {
duration: 300,
exitDuration: 300,
transition: 'fade',
},
}}
{...rest}
>
{children}
</MantineModalsProvider>
);
};