@saas-ui/modals 2.4.2 → 3.0.0-alpha.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +11 -5
- package/dist/index.cjs +206 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +182 -0
- package/dist/index.d.ts +110 -185
- package/dist/index.js +86 -531
- package/dist/index.js.map +1 -1
- package/package.json +15 -33
- package/src/alert-dialog.tsx +156 -0
- package/src/default-modals.ts +3 -7
- package/src/drawer.tsx +46 -60
- package/src/form.tsx +15 -22
- package/src/index.ts +22 -38
- package/src/modal.tsx +43 -52
- package/src/types.ts +46 -33
- package/dist/chunk-FRC2HTO7.mjs +0 -154
- package/dist/chunk-FRC2HTO7.mjs.map +0 -1
- package/dist/form-BtCUKHAs.d.mts +0 -82
- package/dist/form-BtCUKHAs.d.ts +0 -82
- package/dist/index.d.mts +0 -257
- package/dist/index.mjs +0 -469
- package/dist/index.mjs.map +0 -1
- package/dist/yup/index.d.mts +0 -15
- package/dist/yup/index.d.ts +0 -15
- package/dist/yup/index.js +0 -165
- package/dist/yup/index.js.map +0 -1
- package/dist/yup/index.mjs +0 -20
- package/dist/yup/index.mjs.map +0 -1
- package/dist/zod/index.d.mts +0 -15
- package/dist/zod/index.d.ts +0 -15
- package/dist/zod/index.js +0 -165
- package/dist/zod/index.js.map +0 -1
- package/dist/zod/index.mjs +0 -20
- package/dist/zod/index.mjs.map +0 -1
- package/src/create-modals.tsx +0 -30
- package/src/dialog.tsx +0 -151
- package/src/menu.tsx +0 -107
- package/src/provider.tsx +0 -357
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/dialog.tsx","../src/drawer.tsx","../src/modal.tsx","../src/menu.tsx","../src/form.tsx","../src/provider.tsx","../src/default-modals.ts","../src/create-modals.tsx"],"sourcesContent":["// Exporting from './dialog'\nexport { ConfirmDialog } from './dialog'\nexport type { ConfirmDialogProps } from './dialog'\n\n// Exporting from './drawer'\nexport { BaseDrawer, Drawer } from './drawer'\nexport type { BaseDrawerProps, DrawerProps } from './drawer'\n\n// Exporting from './modal'\nexport { BaseModal, Modal } from './modal'\nexport type { BaseModalProps } from './modal'\n\n// Exporting from './menu'\nexport { MenuDialog, MenuDialogList } from './menu'\nexport type { MenuDialogListProps, MenuDialogProps } from './menu'\n\n// Exporting from './form'\nexport { FormDialog, createFormDialog } from './form'\nexport type {\n DefaultFormType,\n FormDialogFieldOverrides,\n FormDialogProps,\n} from './form'\n\n// Exporting from './provider'\nexport {\n ModalsContext,\n ModalsProvider,\n useModals,\n useModalsContext,\n} from './provider'\nexport type {\n ConfirmDialogOptions,\n DrawerOptions,\n FormDialogOptions,\n MenuDialogOptions,\n ModalConfig,\n ModalId,\n ModalScopes,\n ModalsContextValue,\n ModalsProviderProps,\n OpenOptions,\n} from './provider'\n\n// Exporting from './create-modals'\nexport { createModals } from './create-modals'\nexport type { CreateModalsOptions } from './create-modals'\n","import * as React from 'react'\n\nimport {\n AlertDialog,\n AlertDialogBody,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogContent,\n AlertDialogOverlay,\n AlertDialogProps,\n ButtonGroup,\n ButtonGroupProps,\n Button,\n ButtonProps,\n} from '@chakra-ui/react'\n\nexport interface ConfirmDialogProps\n extends Omit<AlertDialogProps, 'leastDestructiveRef'> {\n /**\n * The dialog title\n */\n title?: React.ReactNode\n /**\n * The cancel button label\n */\n cancelLabel?: React.ReactNode\n /**\n * The confirm button label\n */\n confirmLabel?: React.ReactNode\n /**\n * The cancel button props\n */\n cancelProps?: ButtonProps\n /**\n * The confirm button props\n */\n confirmProps?: ButtonProps\n /**\n * The button group props\n */\n buttonGroupProps?: ButtonGroupProps\n /**\n * Close the dialog on cancel\n * @default true\n */\n closeOnCancel?: boolean\n /**\n * Close the dialog on confirm\n * @default true\n */\n closeOnConfirm?: boolean\n /**\n * Defines which button gets initial focus\n * https://www.w3.org/TR/wai-aria-practices/#alertdialog\n */\n leastDestructiveFocus?: 'cancel' | 'confirm'\n /**\n * Function that's called when cancel is clicked\n */\n onCancel?: () => void\n /**\n * Function that's called when confirm is clicked.\n */\n onConfirm?: () => Promise<void> | void\n}\n\nexport const ConfirmDialog: React.FC<ConfirmDialogProps> = (props) => {\n const {\n title,\n cancelLabel = 'Cancel',\n confirmLabel = 'Confirm',\n cancelProps,\n confirmProps,\n buttonGroupProps,\n isOpen,\n closeOnCancel = true,\n closeOnConfirm = true,\n leastDestructiveFocus = 'cancel',\n onClose,\n onCancel,\n onConfirm,\n children,\n ...rest\n } = props\n\n const cancelRef = React.useRef(null)\n const confirmRef = React.useRef(null)\n const [isLoading, setIsLoading] = React.useState(false)\n\n const handleConfirm = async () => {\n try {\n const result = onConfirm?.()\n if (typeof result?.then === 'function') {\n setIsLoading(true)\n await result\n }\n\n closeOnConfirm && onClose()\n /* eslint-disable no-useless-catch */\n } catch (e: any) {\n throw e\n } finally {\n setIsLoading(false)\n }\n /* eslint-enable */\n }\n\n return (\n <AlertDialog\n isOpen={isOpen}\n onClose={onClose}\n {...rest}\n leastDestructiveRef={\n leastDestructiveFocus === 'cancel' ? cancelRef : confirmRef\n }\n >\n <AlertDialogOverlay>\n <AlertDialogContent>\n <AlertDialogHeader>{title}</AlertDialogHeader>\n\n <AlertDialogBody>{children}</AlertDialogBody>\n\n <AlertDialogFooter>\n <ButtonGroup {...buttonGroupProps}>\n <Button\n ref={cancelRef}\n {...cancelProps}\n onClick={() => {\n onCancel?.()\n\n closeOnCancel && onClose()\n }}\n >\n {cancelProps?.children || cancelLabel}\n </Button>\n <Button\n ref={confirmRef}\n isLoading={isLoading}\n {...confirmProps}\n onClick={handleConfirm}\n >\n {confirmProps?.children || confirmLabel}\n </Button>\n </ButtonGroup>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialogOverlay>\n </AlertDialog>\n )\n}\n","import * as React from 'react'\n\nimport {\n Drawer as ChakraDrawer,\n DrawerOverlay,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerBody,\n DrawerCloseButton,\n DrawerProps as ChakraDrawerProps,\n ModalHeaderProps,\n ModalContentProps,\n ModalFooterProps,\n} from '@chakra-ui/react'\nimport { runIfFn, MaybeRenderProp } from '@chakra-ui/utils'\n\nexport interface BaseDrawerProps extends Omit<ChakraDrawerProps, 'children'> {\n /**\n * The drawer title\n */\n title: React.ReactNode\n /**\n * The modal children\n */\n children: MaybeRenderProp<{\n isOpen: boolean\n onClose: () => void\n }>\n /**\n * The modal footer\n */\n footer?: React.ReactNode\n /**\n * Hide the close button\n */\n hideCloseButton?: boolean\n /**\n * Hide the overflow\n */\n hideOverlay?: boolean\n /**\n * Props for the modal header\n */\n headerProps?: ModalHeaderProps\n /**\n * Props for the modal content\n */\n contentProps?: ModalContentProps\n /**\n * Props for the modal footer\n */\n footerProps?: ModalFooterProps\n}\n\nexport const BaseDrawer: React.FC<BaseDrawerProps> = (props) => {\n const {\n title,\n children,\n footer,\n isOpen,\n onClose,\n hideCloseButton,\n hideOverlay,\n headerProps,\n contentProps,\n footerProps,\n ...rest\n } = props\n return (\n <ChakraDrawer isOpen={isOpen} onClose={onClose} {...rest}>\n {!hideOverlay && <DrawerOverlay />}\n <DrawerContent {...contentProps}>\n {title && <DrawerHeader {...headerProps}>{title}</DrawerHeader>}\n {!hideCloseButton && <DrawerCloseButton />}\n {runIfFn(children, {\n isOpen,\n onClose,\n })}\n {footer && <DrawerFooter {...footerProps}>{footer}</DrawerFooter>}\n </DrawerContent>\n </ChakraDrawer>\n )\n}\n\nexport interface DrawerProps extends BaseDrawerProps {\n /**\n * Drawer footer content, wrapped with `DrawerFooter`\n */\n footer?: React.ReactNode\n}\n\nexport const Drawer: React.FC<DrawerProps> = (props) => {\n const { children, isOpen, onClose, ...rest } = props\n return (\n <BaseDrawer isOpen={isOpen} onClose={onClose} {...rest}>\n <DrawerBody>\n {runIfFn(children, {\n isOpen,\n onClose,\n })}\n </DrawerBody>\n </BaseDrawer>\n )\n}\n","import * as React from 'react'\n\nimport {\n Modal as ChakraModal,\n ModalOverlay,\n ModalContent,\n ModalHeader,\n ModalFooter,\n ModalBody,\n ModalCloseButton,\n ModalProps as ChakraModalProps,\n ModalContentProps,\n ModalHeaderProps,\n ModalFooterProps,\n} from '@chakra-ui/react'\n\nimport { runIfFn, MaybeRenderProp } from '@chakra-ui/utils'\n\nexport interface BaseModalProps extends Omit<ChakraModalProps, 'children'> {\n /**\n * The modal title\n */\n title?: React.ReactNode\n /**\n * The modal children\n */\n children: MaybeRenderProp<{\n isOpen: boolean\n onClose: () => void\n }>\n /**\n * The modal footer\n */\n footer?: React.ReactNode\n /**\n * Hide the close button\n */\n hideCloseButton?: boolean\n /**\n * Hide the overlay\n */\n hideOverlay?: boolean\n /**\n * Props for the modal header\n */\n headerProps?: ModalHeaderProps\n /**\n * Props for the modal content\n */\n contentProps?: ModalContentProps\n /**\n * Props for the modal footer\n */\n footerProps?: ModalFooterProps\n}\n\nexport const BaseModal: React.FC<BaseModalProps> = (props) => {\n const {\n title,\n footer,\n children,\n isOpen,\n onClose,\n hideCloseButton,\n hideOverlay,\n headerProps,\n contentProps,\n footerProps,\n ...rest\n } = props\n return (\n <ChakraModal isOpen={isOpen} onClose={onClose} {...rest}>\n {!hideOverlay && <ModalOverlay />}\n <ModalContent {...contentProps}>\n {title && <ModalHeader {...headerProps}>{title}</ModalHeader>}\n {!hideCloseButton && <ModalCloseButton />}\n {runIfFn(children, {\n isOpen,\n onClose,\n })}\n {footer && <ModalFooter {...footerProps}>{footer}</ModalFooter>}\n </ModalContent>\n </ChakraModal>\n )\n}\n\nexport const Modal: React.FC<BaseModalProps> = (props) => {\n const { children, isOpen, onClose, ...rest } = props\n return (\n <BaseModal {...rest} isOpen={isOpen} onClose={onClose}>\n <ModalBody>\n {runIfFn(children, {\n isOpen,\n onClose,\n })}\n </ModalBody>\n </BaseModal>\n )\n}\n","import * as React from 'react'\n\nimport {\n ModalFooter,\n chakra,\n forwardRef,\n useMenuContext,\n useMenuList,\n createStylesContext,\n useMultiStyleConfig,\n Menu,\n MenuListProps,\n useBreakpointValue,\n} from '@chakra-ui/react'\n\nimport { BaseModal, BaseModalProps } from './modal'\n\nconst [StylesProvider] = createStylesContext('SuiMenuDialog')\n\nexport interface MenuDialogProps extends BaseModalProps {\n /**\n * The modal footer, wrapped with `ModalFooter`\n */\n footer?: React.ReactNode\n}\n\nexport const MenuDialog: React.FC<MenuDialogProps> = (props) => {\n const { onClose, onCloseComplete, ...rest } = props\n\n return (\n <Menu\n variant=\"dialog\"\n onClose={() => {\n onClose?.()\n // Not supported in Menu, so we call it here instead\n // @todo Refactor this in v2?\n onCloseComplete?.()\n }}\n {...rest}\n />\n )\n}\n\nexport interface MenuDialogListProps\n extends Omit<\n BaseModalProps,\n 'isOpen' | 'onClose' | 'children' | 'scrollBehavior'\n >,\n Omit<MenuListProps, 'title'> {}\n\nexport const MenuDialogList = forwardRef<MenuDialogListProps, 'div'>(\n (props, forwardedRef) => {\n const {\n rootProps,\n title,\n footer,\n initialFocusRef,\n hideCloseButton,\n motionPreset = 'slideInBottom',\n isCentered: isCenteredProp,\n ...rest\n } = props\n\n const { isOpen, onClose, menuRef } = useMenuContext()\n\n const { ref, ...ownProps } = useMenuList(rest, forwardedRef)\n\n const styles = useMultiStyleConfig('Menu', props)\n\n const isCentered = useBreakpointValue({ base: true, md: false })\n\n return (\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n initialFocusRef={initialFocusRef || menuRef}\n title={title}\n hideCloseButton={hideCloseButton}\n motionPreset={motionPreset}\n isCentered={isCenteredProp ?? isCentered}\n contentProps={{ mx: 4 }}\n >\n {/* We forward the styles again, otherwise the modal styles will be picked up */}\n <StylesProvider value={styles}>\n <chakra.div\n {...ownProps}\n ref={ref as React.Ref<HTMLDivElement>}\n __css={{\n outline: 0,\n maxHeight: '80vh', // can override this in theme\n overflowY: 'auto', // can override this in theme\n ...styles.list,\n boxShadow: 'none',\n border: 0,\n _dark: {\n /* @ts-expect-error */\n ...(styles.list._dark || {}),\n boxShadow: 'none',\n },\n }}\n />\n </StylesProvider>\n {footer && <ModalFooter>{footer}</ModalFooter>}\n </BaseModal>\n )\n }\n)\n","import * as React from 'react'\n\nimport {\n ModalBody,\n ModalFooter,\n Button,\n forwardRef,\n ButtonProps,\n} from '@chakra-ui/react'\nimport { runIfFn } from '@saas-ui/react-utils'\n\nimport {\n Form,\n AutoFields,\n SubmitButton,\n FormProps,\n FieldValues,\n FieldResolver,\n FieldProps,\n FormType,\n DefaultFieldOverrides,\n} from '@saas-ui/forms'\n\nimport { BaseModal, BaseModalProps } from './modal'\n\nexport type FormDialogFieldOverrides = DefaultFieldOverrides & {\n cancel?: ButtonProps\n}\n\nexport interface FormDialogProps<\n TSchema = any,\n TFieldValues extends FieldValues = FieldValues,\n TContext extends object = object,\n TExtraFieldProps extends object = object,\n TFieldTypes = FieldProps<TFieldValues>,\n> extends Omit<BaseModalProps, 'children'>,\n Pick<\n FormProps<TSchema, TFieldValues, TContext, TExtraFieldProps, TFieldTypes>,\n | 'schema'\n | 'defaultValues'\n | 'values'\n | 'context'\n | 'onChange'\n | 'onSubmit'\n | 'onError'\n | 'resolver'\n | 'mode'\n | 'reValidateMode'\n | 'shouldFocusError'\n | 'shouldUnregister'\n | 'shouldUseNativeValidation'\n | 'criteriaMode'\n | 'delayError'\n | 'resetOptions'\n | 'formRef'\n | 'children'\n > {\n /**\n * The modal footer, will be wrapped with `ModalFooter`.\n * Defaults to a cancel and submit button.\n */\n footer?: React.ReactNode\n /**\n * A schema field resolver used to auto generate form fields.\n */\n fieldResolver?: FieldResolver\n /**\n * Field overrides\n */\n fields?: FormDialogFieldOverrides\n}\n\nconst useFormProps = (props: FormDialogProps) => {\n const {\n schema,\n resolver,\n fieldResolver,\n defaultValues,\n values,\n context,\n onChange,\n onSubmit,\n onError,\n mode,\n reValidateMode,\n shouldFocusError = true,\n shouldUnregister,\n shouldUseNativeValidation,\n criteriaMode,\n delayError = 100,\n fields,\n formRef,\n ...modalProps\n } = props\n\n const formProps = {\n schema,\n resolver,\n defaultValues,\n values,\n context,\n onChange,\n onSubmit,\n onError,\n mode,\n reValidateMode,\n shouldFocusError,\n shouldUnregister,\n shouldUseNativeValidation,\n criteriaMode,\n delayError,\n fields,\n formRef,\n }\n\n return { modalProps, formProps, fields }\n}\n\n/**\n * @todo make this dynamic to support other schema types\n */\ntype MergeDialogProps<T> =\n T extends FormType<\n infer FieldDefs,\n infer ExtraProps,\n infer ExtraFieldProps,\n infer ExtraOverrides\n >\n ? FormType<\n FieldDefs,\n ExtraProps & Omit<BaseModalProps, 'children'>,\n ExtraFieldProps,\n ExtraOverrides & FormDialogFieldOverrides\n >\n : never\n\ntype IsSchemaType<T, Schema, FieldDefs> =\n T extends DefaultFormType<FieldDefs>\n ? T extends (\n props: FormProps<infer TSchema, infer TFieldValues, infer TContext>\n ) => any\n ? Schema extends TSchema\n ? true\n : false\n : false\n : false\n\nexport type DefaultFormType<\n FieldDefs = any,\n ExtraProps = object,\n ExtraFieldProps extends object = object,\n ExtraOverrides = FormDialogFieldOverrides,\n> = (<\n TSchema = unknown,\n TFieldValues extends Record<string, any> = any,\n TContext extends object = object,\n>(\n props: any\n) => React.ReactElement) & {\n displayName?: string\n id?: string\n}\n\nexport function createFormDialog<\n FieldDefs = any,\n ExtraProps = object,\n ExtraFieldProps extends object = object,\n ExtraOverrides = FormDialogFieldOverrides,\n TFormType extends DefaultFormType<\n FieldDefs,\n ExtraProps,\n ExtraFieldProps,\n ExtraOverrides\n > = DefaultFormType<FieldDefs, ExtraProps, ExtraFieldProps, ExtraOverrides>,\n>(Form: TFormType) {\n const Dialog = forwardRef<any, 'div'>((props, ref) => {\n const { isOpen, onClose, footer, children, ...rest } = props\n const { modalProps, formProps, fields } = useFormProps(rest)\n return (\n <BaseModal {...modalProps} isOpen={isOpen} onClose={onClose}>\n <Form\n ref={ref}\n {...(formProps as any)}\n flex=\"1\"\n minHeight=\"0px\"\n display=\"flex\"\n flexDirection=\"column\"\n >\n {(form: any) => (\n <>\n <ModalBody height=\"100%\">\n {runIfFn(children, form) || <AutoFields />}\n </ModalBody>\n\n {footer || (\n <ModalFooter>\n <Button\n variant=\"ghost\"\n mr={3}\n onClick={onClose}\n {...fields?.cancel}\n >\n {fields?.cancel?.children ?? 'Cancel'}\n </Button>\n <SubmitButton {...fields?.submit} />\n </ModalFooter>\n )}\n </>\n )}\n </Form>\n </BaseModal>\n )\n }) as MergeDialogProps<TFormType>\n\n Dialog.displayName = `${Form.displayName || Form.name}Dialog`\n Dialog.id = Form.id\n\n return Dialog\n}\n\n/**\n * Can be used to quickly request information from people without leaving the current page.\n *\n * @see Docs https://saas-ui.dev/docs/components/overlay/form-dialog\n */\nexport const FormDialog = createFormDialog(Form)\n","import * as React from 'react'\n\nimport { BaseModalProps } from './modal'\nimport { DrawerProps } from './drawer'\nimport { ConfirmDialogProps } from './dialog'\nimport { MenuDialogProps } from './menu'\nimport { FormDialogProps } from './form'\nimport { defaultModals } from './default-modals'\nimport { FieldValues, FormType } from '@saas-ui/forms'\nimport { FormDialogHandler, FormHandler } from './types'\n\nexport interface ModalsContextValue<\n TModals extends Record<string, React.FC<any>> = Record<string, React.FC<any>>,\n TTypes extends Extract<keyof TModals, string> = Extract<keyof TModals, string>\n> {\n open: <T extends OpenOptions<TTypes>>(\n componentOrOptions: T extends {\n component: infer TComponent extends React.FC<any>\n }\n ? WithModalOptions<React.ComponentPropsWithRef<TComponent>>\n : T extends {\n type: infer TType extends keyof TModals\n }\n ? WithModalOptions<React.ComponentPropsWithRef<TModals[TType]>>\n : T,\n options?: T extends React.FC<any>\n ? WithModalOptions<React.ComponentPropsWithRef<T>>\n : never\n ) => ModalId\n drawer: (options: DrawerOptions) => ModalId\n alert: (options: ConfirmDialogOptions) => ModalId\n confirm: (options: ConfirmDialogOptions) => ModalId\n menu: (options: MenuDialogOptions) => ModalId\n form: FormDialogHandler<TModals['form']>\n close: (id: ModalId) => void\n closeAll: () => void\n}\n\nexport const ModalsContext = React.createContext<ModalsContextValue<\n typeof defaultModals\n> | null>(null)\n\nexport interface ModalsProviderProps<\n TModals extends Record<string, React.FC<any>> = Record<string, React.FC<any>>\n> {\n children: React.ReactNode\n modals?: TModals\n}\n\nexport type ModalId = string | number\n\ntype WithModalOptions<T> = Omit<T, 'isOpen' | 'onClose'> & ModalOptions\n\ninterface ModalOptions\n extends Omit<BaseModalProps, 'isOpen' | 'onClose' | 'children'> {\n onClose?: (args: { force?: boolean }) => Promise<boolean | undefined> | void\n [key: string]: any\n}\n\nexport interface DrawerOptions\n extends ModalOptions,\n Omit<DrawerProps, 'onClose' | 'isOpen' | 'children' | 'title' | 'size'> {}\n\nexport interface ConfirmDialogOptions\n extends ModalOptions,\n Omit<ConfirmDialogProps, 'onClose' | 'isOpen' | 'children'> {}\n\nexport interface MenuDialogOptions\n extends ModalOptions,\n Omit<MenuDialogProps, 'onClose' | 'isOpen' | 'children'> {}\n\nexport interface FormDialogOptions\n extends ModalOptions,\n Omit<FormDialogProps, 'onClose' | 'isOpen' | 'children'> {}\n\nexport interface OpenOptions<TModalTypes extends string> extends ModalOptions {\n type?: TModalTypes\n scope?: ModalScopes\n}\n\nexport type ModalScopes = 'modal' | 'alert'\n\nexport interface ModalConfig<\n TModalOptions extends ModalOptions = ModalOptions,\n TModalTypes extends string = string\n> {\n /**\n * The modal id, autogenerated when not set.\n * Can be used to close modals.\n */\n id?: ModalId | null\n /**\n * The modal props\n */\n props?: TModalOptions | null\n /**\n * The modal scope\n * Modals can only have one level per scope.\n * The default scopes are 'modal' and 'alert', alerts can be openend above modals.\n */\n scope?: ModalScopes | string\n /**\n * The modal type to open.\n * Build in types are 'modal', 'drawer', 'alert', 'confirm'\n *\n * Custom types can be configured using the `modals` prop of `ModalProvider`\n */\n type?: TModalTypes\n /**\n * Render a custom modal component.\n * This will ignore the `type` param.\n */\n component?: React.FC<BaseModalProps>\n /**\n * Whether the modal is open or not.\n * This is used internally to keep track of the modal state.\n */\n isOpen?: boolean\n}\n\nconst initialModalState: ModalConfig = {\n id: null,\n props: null,\n type: 'modal',\n}\n\nexport function ModalsProvider({ children, modals }: ModalsProviderProps) {\n // Note that updating the Set doesn't trigger a re-render,\n // use in conjuction with setActiveModals\n const _instances = React.useMemo(() => new Set<ModalConfig>(), [])\n\n const [activeModals, setActiveModals] = React.useState<\n Record<string, ModalConfig>\n >({\n modal: initialModalState,\n })\n\n const getModalComponent = React.useMemo(() => {\n const _modals: Record<string, React.FC<any>> = {\n ...defaultModals,\n ...modals,\n }\n\n return (type = 'modal') => {\n const component = _modals[type] || _modals.modal\n\n return component\n }\n }, [modals])\n\n const setActiveModal = (modal: ModalConfig, scope?: string) => {\n if (!scope) {\n return setActiveModals({\n modal,\n })\n }\n setActiveModals((prevState) => ({\n ...prevState,\n [scope]: modal,\n }))\n }\n\n const open = <T extends OpenOptions<any>>(\n componentOrOptions: any,\n options?: T extends React.FC<any>\n ? WithModalOptions<React.ComponentPropsWithRef<T>>\n : never\n ): ModalId => {\n let _options: ModalOptions\n if (typeof componentOrOptions === 'function') {\n _options = {\n component: componentOrOptions,\n ...options,\n } as unknown as T\n } else {\n _options = componentOrOptions\n }\n\n const {\n id = _instances.size + 1,\n type = 'modal',\n scope = 'modal',\n component,\n ...props\n } = _options\n\n const modal: ModalConfig<T> = {\n id,\n props: props as T,\n type,\n scope,\n component,\n isOpen: true,\n }\n\n _instances.add(modal)\n setActiveModal(modal, scope)\n\n return id\n }\n\n const drawer = (options: DrawerOptions) => {\n return open<DrawerOptions>({\n ...options,\n type: 'drawer',\n })\n }\n\n const alert = (options: ConfirmDialogOptions) => {\n return open({\n ...options,\n scope: 'alert',\n type: 'alert',\n cancelProps: {\n display: 'none',\n },\n confirmProps: {\n label: 'OK',\n },\n leastDestructiveFocus: 'confirm',\n })\n }\n\n const confirm = (options: ConfirmDialogOptions) => {\n return open<ConfirmDialogOptions>({\n ...options,\n scope: 'alert',\n type: 'confirm',\n })\n }\n\n const menu = (options: MenuDialogOptions) => {\n return open<MenuDialogOptions>({\n ...options,\n type: 'menu',\n })\n }\n\n const form = (options: any) => {\n return open({\n ...options,\n type: 'form',\n })\n }\n\n const close = async (id?: ModalId | null, force?: boolean) => {\n const modals = [...Array.from(_instances)]\n const modal = modals.filter((modal) => modal.id === id)[0]\n\n if (!modal) {\n return\n }\n\n const shouldClose = await modal.props?.onClose?.({ force })\n if (shouldClose === false) {\n return\n }\n\n const scoped = modals.filter(({ scope }) => scope === modal.scope)\n\n if (scoped.length === 1) {\n setActiveModal(\n {\n ...modal,\n isOpen: false,\n },\n modal.scope\n )\n } else if (scoped.length > 1) {\n setActiveModal(scoped[scoped.length - 2], modal.scope)\n } else {\n setActiveModal(\n {\n id: null,\n props: null,\n type: modal.type, // Keep type same as last modal type to make sure the animation isn't interrupted\n },\n modal.scope\n )\n }\n\n // @todo this is not ideal, but not all modals support onCloseComplete\n setTimeout(() => closeComplete(id), 200)\n }\n\n const closeComplete = (id?: ModalId | null) => {\n const modals = [...Array.from(_instances)]\n const modal = modals.filter((modal) => modal.id === id)[0]\n\n _instances.delete(modal)\n\n const scoped = modal && modals.filter(({ scope }) => scope === modal.scope)\n\n if (scoped?.length === 1) {\n setActiveModal(initialModalState, modal.scope)\n }\n }\n\n const closeAll = () => {\n _instances.forEach((modal) => modal.props?.onClose?.({ force: true }))\n _instances.clear()\n\n setActiveModal(initialModalState)\n }\n\n const context = {\n open,\n drawer,\n alert,\n confirm,\n menu,\n form,\n close,\n closeAll,\n }\n\n const content = React.useMemo(\n () =>\n Object.entries(activeModals).map(([scope, config]) => {\n const Component = config.component || getModalComponent(config.type)\n\n const { title, body, children, ...props } = config.props || {}\n\n return (\n <Component\n key={scope}\n title={title}\n children={body || children}\n {...props}\n isOpen={!!config.isOpen}\n onClose={() => close(config.id)}\n onCloseComplete={() => closeComplete(config.id)}\n />\n )\n }),\n [activeModals]\n )\n\n return (\n <ModalsContext.Provider value={context}>\n {content}\n {children}\n </ModalsContext.Provider>\n )\n}\n\nexport const useModalsContext = () => React.useContext(ModalsContext)\n\nexport const useModals = () => {\n const modals = useModalsContext()\n\n if (!modals) {\n throw new Error('useModals must be used within a ModalsProvider')\n }\n\n return modals\n}\n","import { ConfirmDialog } from './dialog'\nimport { MenuDialog } from './menu'\nimport { FormDialog } from './form'\nimport { Drawer } from './drawer'\nimport { Modal } from './modal'\n\nexport const defaultModals = {\n alert: ConfirmDialog,\n confirm: ConfirmDialog,\n drawer: Drawer,\n modal: Modal,\n menu: MenuDialog,\n form: FormDialog,\n}\n","import { defaultModals } from './default-modals'\nimport {\n ModalsContextValue,\n ModalsProvider,\n ModalsProviderProps,\n useModals,\n} from './provider'\n\nexport interface CreateModalsOptions<\n TModalDefs extends Record<string, React.FC<any>>\n> {\n modals: TModalDefs\n}\n\nexport const createModals = <TModalDefs extends Record<string, React.FC<any>>>(\n options: CreateModalsOptions<TModalDefs>\n) => {\n const modals = {\n ...defaultModals,\n ...options.modals,\n }\n const Provider = (props: Omit<ModalsProviderProps, 'modals'>) => {\n return <ModalsProvider children={props.children} modals={modals} />\n }\n\n return {\n ModalsProvider: Provider,\n useModals: useModals as () => ModalsContextValue<typeof modals>,\n }\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","ChakraDrawer","import_react","import_utils","import_jsx_runtime","ChakraModal","import_react","import_jsx_runtime","import_react","import_jsx_runtime","Form","React","import_jsx_runtime","modals","modal","children","import_jsx_runtime"]}
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/alert-dialog.tsx","../src/drawer.tsx","../src/modal.tsx","../src/default-modals.ts"],"sourcesContent":["import { createModals } from '@saas-ui/modals-provider'\n\nimport { defaultModals } from './default-modals.ts'\n\n// Exporting from './dialog'\nexport { AlertDialog } from './alert-dialog.tsx'\nexport type { AlertDialogProps } from './alert-dialog.tsx'\n\n// Exporting from './drawer'\nexport { Drawer } from './drawer'\nexport type { DrawerProps } from './drawer'\n\n// Exporting from './modal'\nexport { Modal } from './modal'\nexport type { ModalProps } from './modal'\n\n// Exporting from './form'\n// export { FormDialog, createFormDialog } from './form'\n// export type {\n// DefaultFormType,\n// FormDialogFieldOverrides,\n// FormDialogProps,\n// } from './form'\n\n// Exporting from './provider'\n\nconst { useModals, ModalsProvider } = createModals({\n modals: defaultModals,\n})\n\nexport { ModalsProvider, useModals }\n","import * as React from 'react'\n\nimport { Button, ButtonProps, type HTMLChakraProps } from '@chakra-ui/react'\nimport { callAll } from '@saas-ui/core/utils'\nimport { Dialog } from '@saas-ui/react/dialog'\n\nexport interface AlertDialogProps\n extends Omit<\n Dialog.RootProps,\n 'leastDestructiveRef' | 'onOpenChange' | 'open'\n > {\n /**\n * Whether the dialog is open\n */\n open: boolean\n /**\n * Callback when the dialog is opened or closed\n */\n onOpenChange: (details: { open: boolean }) => void\n /**\n * The dialog title\n */\n title?: React.ReactNode\n translations?: {\n cancel?: React.ReactNode\n confirm?: React.ReactNode\n close?: React.ReactNode\n }\n slotProps?: {\n cancel?: ButtonProps\n confirm?: ButtonProps\n footer?: HTMLChakraProps<'div'>\n }\n /**\n * Close the dialog on cancel\n * @default true\n */\n closeOnCancel?: boolean\n /**\n * Close the dialog on confirm\n * @default true\n */\n closeOnConfirm?: boolean\n /**\n * Hide the backdrop\n */\n backdrop?: boolean\n /**\n * Hide the close button\n */\n hideCloseButton?: boolean\n /**\n * Defines which button gets initial focus\n * https://www.w3.org/TR/wai-aria-practices/#alertdialog\n */\n leastDestructiveFocus?: 'cancel' | 'confirm'\n /**\n * Function that's called when cancel is clicked\n */\n onCancel?: () => void\n /**\n * Function that's called when confirm is clicked.\n */\n onConfirm?: () => Promise<void> | void\n}\n\nexport const AlertDialog: React.FC<AlertDialogProps> = (props) => {\n const {\n title,\n translations,\n slotProps,\n open,\n closeOnCancel = true,\n closeOnConfirm = true,\n leastDestructiveFocus = 'cancel',\n onOpenChange,\n onCancel,\n onConfirm,\n children,\n ...rest\n } = props\n\n const cancelRef = React.useRef(null)\n const confirmRef = React.useRef(null)\n const [isLoading, setIsLoading] = React.useState(false)\n\n const handleConfirm = async () => {\n try {\n const result = onConfirm?.()\n if (typeof result?.then === 'function') {\n setIsLoading(true)\n await result\n }\n\n closeOnConfirm && onOpenChange({ open: false })\n /* eslint-disable no-useless-catch */\n } catch (e: any) {\n throw e\n } finally {\n setIsLoading(false)\n }\n /* eslint-enable */\n }\n\n const titleId = React.useId()\n const contentId = React.useId()\n\n return (\n <Dialog.Root\n open={open}\n onOpenChange={onOpenChange}\n size=\"sm\"\n aria-labelledby={titleId}\n aria-describedby={contentId}\n {...rest}\n initialFocusEl={() =>\n leastDestructiveFocus === 'cancel'\n ? cancelRef.current\n : confirmRef.current\n }\n >\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title id={titleId}>{title}</Dialog.Title>\n </Dialog.Header>\n\n <Dialog.Body id={contentId}>{children}</Dialog.Body>\n\n <Dialog.Footer {...slotProps?.footer}>\n <Button\n ref={cancelRef}\n variant=\"ghost\"\n colorPalette=\"gray\"\n {...slotProps?.cancel}\n onClick={callAll(slotProps?.cancel?.onClick, () => {\n onCancel?.()\n\n closeOnCancel && onOpenChange({ open: false })\n })}\n >\n {slotProps?.cancel?.children || translations?.cancel || 'Cancel'}\n </Button>\n <Button\n ref={confirmRef}\n variant=\"solid\"\n disabled={isLoading}\n {...slotProps?.confirm}\n onClick={callAll(handleConfirm, slotProps?.confirm?.onClick)}\n >\n {slotProps?.confirm?.children || translations?.confirm || 'OK'}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n )\n}\n","import * as React from 'react'\n\nimport { type HTMLChakraProps } from '@chakra-ui/react'\nimport { MaybeRenderProp, runIfFn } from '@saas-ui/core/utils'\nimport { Drawer as BaseDrawer } from '@saas-ui/react/drawer'\n\nexport interface DrawerProps extends Omit<BaseDrawer.RootProps, 'children'> {\n /**\n * The drawer title\n */\n title: React.ReactNode\n /**\n * Whether the modal is open\n */\n open: boolean\n /**\n * Callback when the drawer is opened or closed\n */\n onOpenChange: (details: { open: boolean }) => void\n /**\n * The drawer children\n */\n children: MaybeRenderProp<{\n open: boolean\n setOpen: (open: boolean) => void\n }>\n /**\n * The modal footer\n */\n footer?: React.ReactNode\n /**\n * Hide the close button\n */\n hideCloseButton?: boolean\n /**\n * Hide the backdrop\n */\n hideBackdrop?: boolean\n /**\n * Props for the modal header\n */\n headerProps?: HTMLChakraProps<'div'>\n /**\n * Props for the modal content\n */\n contentProps?: BaseDrawer.ContentProps\n /**\n * Props for the modal footer\n */\n footerProps?: HTMLChakraProps<'div'>\n /**\n * Props for the modal body\n */\n bodyProps?: HTMLChakraProps<'div'>\n}\n\nexport const Drawer: React.FC<DrawerProps> = (props) => {\n const {\n title,\n children,\n footer,\n open,\n onOpenChange,\n hideCloseButton,\n hideBackdrop,\n headerProps,\n contentProps,\n bodyProps,\n footerProps,\n ...rest\n } = props\n return (\n <BaseDrawer.Root open={open} onOpenChange={onOpenChange} {...rest}>\n {!hideBackdrop && <BaseDrawer.Backdrop />}\n <BaseDrawer.Content {...contentProps}>\n {title && (\n <BaseDrawer.Header {...headerProps}>{title}</BaseDrawer.Header>\n )}\n {!hideCloseButton && <BaseDrawer.CloseTrigger />}\n <BaseDrawer.Body {...bodyProps}>\n <BaseDrawer.Context>\n {({ open, setOpen }) => runIfFn(children, { open, setOpen })}\n </BaseDrawer.Context>\n </BaseDrawer.Body>\n {footer && (\n <BaseDrawer.Footer {...footerProps}>{footer}</BaseDrawer.Footer>\n )}\n </BaseDrawer.Content>\n </BaseDrawer.Root>\n )\n}\n","import * as React from 'react'\n\nimport type { HTMLChakraProps } from '@chakra-ui/react'\nimport { MaybeRenderProp, runIfFn } from '@saas-ui/core/utils'\nimport { Dialog as BaseDialog } from '@saas-ui/react/dialog'\n\nexport interface ModalProps extends Omit<BaseDialog.RootProps, 'children'> {\n /**\n * The modal title\n */\n title?: React.ReactNode\n /**\n * Whether the modal is open\n */\n open: boolean\n /**\n * Callback when the modal is opened or closed\n */\n onOpenChange: (details: { open: boolean }) => void\n /**\n * The modal children\n */\n children: MaybeRenderProp<{\n open: boolean\n setOpen: (open: boolean) => void\n }>\n /**\n * The modal footer\n */\n footer?: React.ReactNode\n /**\n * Hide the close button\n */\n hideCloseButton?: boolean\n /**\n * Hide the overlay\n */\n hideBackdrop?: boolean\n /**\n * Props for the modal header\n */\n headerProps?: HTMLChakraProps<'div'>\n /**\n * Props for the modal content\n */\n contentProps?: HTMLChakraProps<'div'>\n /**\n * Props for the modal body\n */\n bodyProps?: HTMLChakraProps<'div'>\n /**\n * Props for the modal footer\n */\n footerProps?: HTMLChakraProps<'div'>\n}\n\nexport const Modal: React.FC<ModalProps> = (props) => {\n const {\n title,\n footer,\n children,\n open,\n onOpenChange,\n hideCloseButton,\n hideBackdrop,\n headerProps,\n contentProps,\n bodyProps,\n footerProps,\n ...rest\n } = props\n return (\n <BaseDialog.Root open={open} onOpenChange={onOpenChange} {...rest}>\n <BaseDialog.Content {...contentProps}>\n {title && (\n <BaseDialog.Header {...headerProps}>{title}</BaseDialog.Header>\n )}\n {!hideCloseButton && <BaseDialog.CloseTrigger />}\n <BaseDialog.Body>\n <BaseDialog.Context>\n {({ open, setOpen }) => runIfFn(children, { open, setOpen })}\n </BaseDialog.Context>\n </BaseDialog.Body>\n {footer && (\n <BaseDialog.Footer {...footerProps}>{footer}</BaseDialog.Footer>\n )}\n </BaseDialog.Content>\n </BaseDialog.Root>\n )\n}\n","import { AlertDialog } from './alert-dialog'\nimport { Drawer } from './drawer'\nimport { Modal } from './modal'\n\nexport const defaultModals = {\n alert: AlertDialog,\n confirm: AlertDialog,\n drawer: Drawer,\n modal: Modal,\n}\n"],"mappings":";;;AAAA,SAAS,oBAAoB;;;ACA7B,YAAY,WAAW;AAEvB,SAAS,cAAiD;AAC1D,SAAS,eAAe;AACxB,SAAS,cAAc;AAuHb,cAKF,YALE;AAzDH,IAAM,cAA0C,CAAC,UAAU;AAlElE;AAmEE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,wBAAwB;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,YAAkB,aAAO,IAAI;AACnC,QAAM,aAAmB,aAAO,IAAI;AACpC,QAAM,CAAC,WAAW,YAAY,IAAU,eAAS,KAAK;AAEtD,QAAM,gBAAgB,YAAY;AAChC,QAAI;AACF,YAAM,SAAS;AACf,UAAI,QAAO,iCAAQ,UAAS,YAAY;AACtC,qBAAa,IAAI;AACjB,cAAM;AAAA,MACR;AAEA,wBAAkB,aAAa,EAAE,MAAM,MAAM,CAAC;AAAA,IAEhD,SAAS,GAAQ;AACf,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EAEF;AAEA,QAAM,UAAgB,YAAM;AAC5B,QAAM,YAAkB,YAAM;AAE9B,SACE;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA;AAAA,MACA,MAAK;AAAA,MACL,mBAAiB;AAAA,MACjB,oBAAkB;AAAA,MACjB,GAAG;AAAA,MACJ,gBAAgB,MACd,0BAA0B,WACtB,UAAU,UACV,WAAW;AAAA,MAGjB,+BAAC,OAAO,SAAP,EACC;AAAA,4BAAC,OAAO,QAAP,EACC,8BAAC,OAAO,OAAP,EAAa,IAAI,SAAU,iBAAM,GACpC;AAAA,QAEA,oBAAC,OAAO,MAAP,EAAY,IAAI,WAAY,UAAS;AAAA,QAEtC,qBAAC,OAAO,QAAP,EAAe,GAAG,uCAAW,QAC5B;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,SAAQ;AAAA,cACR,cAAa;AAAA,cACZ,GAAG,uCAAW;AAAA,cACf,SAAS,SAAQ,4CAAW,WAAX,mBAAmB,SAAS,MAAM;AACjD;AAEA,iCAAiB,aAAa,EAAE,MAAM,MAAM,CAAC;AAAA,cAC/C,CAAC;AAAA,cAEA,wDAAW,WAAX,mBAAmB,cAAY,6CAAc,WAAU;AAAA;AAAA,UAC1D;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,SAAQ;AAAA,cACR,UAAU;AAAA,cACT,GAAG,uCAAW;AAAA,cACf,SAAS,QAAQ,gBAAe,4CAAW,YAAX,mBAAoB,OAAO;AAAA,cAE1D,wDAAW,YAAX,mBAAoB,cAAY,6CAAc,YAAW;AAAA;AAAA,UAC5D;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;;;ACxJA,SAA0B,eAAe;AACzC,SAAS,UAAU,kBAAkB;AAqEb,gBAAAA,MAClB,QAAAC,aADkB;AAjBjB,IAAM,SAAgC,CAAC,UAAU;AACtD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,SACE,gBAAAA,MAAC,WAAW,MAAX,EAAgB,MAAY,cAA6B,GAAG,MAC1D;AAAA,KAAC,gBAAgB,gBAAAD,KAAC,WAAW,UAAX,EAAoB;AAAA,IACvC,gBAAAC,MAAC,WAAW,SAAX,EAAoB,GAAG,cACrB;AAAA,eACC,gBAAAD,KAAC,WAAW,QAAX,EAAmB,GAAG,aAAc,iBAAM;AAAA,MAE5C,CAAC,mBAAmB,gBAAAA,KAAC,WAAW,cAAX,EAAwB;AAAA,MAC9C,gBAAAA,KAAC,WAAW,MAAX,EAAiB,GAAG,WACnB,0BAAAA,KAAC,WAAW,SAAX,EACE,WAAC,EAAE,MAAAE,OAAM,QAAQ,MAAM,QAAQ,UAAU,EAAE,MAAAA,OAAM,QAAQ,CAAC,GAC7D,GACF;AAAA,MACC,UACC,gBAAAF,KAAC,WAAW,QAAX,EAAmB,GAAG,aAAc,kBAAO;AAAA,OAEhD;AAAA,KACF;AAEJ;;;ACvFA,SAA0B,WAAAG,gBAAe;AACzC,SAAS,UAAU,kBAAkB;AAqE/B,SAEI,OAAAC,MAFJ,QAAAC,aAAA;AAjBC,IAAM,QAA8B,CAAC,UAAU;AACpD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,SACE,gBAAAD,KAAC,WAAW,MAAX,EAAgB,MAAY,cAA6B,GAAG,MAC3D,0BAAAC,MAAC,WAAW,SAAX,EAAoB,GAAG,cACrB;AAAA,aACC,gBAAAD,KAAC,WAAW,QAAX,EAAmB,GAAG,aAAc,iBAAM;AAAA,IAE5C,CAAC,mBAAmB,gBAAAA,KAAC,WAAW,cAAX,EAAwB;AAAA,IAC9C,gBAAAA,KAAC,WAAW,MAAX,EACC,0BAAAA,KAAC,WAAW,SAAX,EACE,WAAC,EAAE,MAAAE,OAAM,QAAQ,MAAMH,SAAQ,UAAU,EAAE,MAAAG,OAAM,QAAQ,CAAC,GAC7D,GACF;AAAA,IACC,UACC,gBAAAF,KAAC,WAAW,QAAX,EAAmB,GAAG,aAAc,kBAAO;AAAA,KAEhD,GACF;AAEJ;;;ACrFO,IAAM,gBAAgB;AAAA,EAC3B,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AACT;;;AJiBA,IAAM,EAAE,WAAW,eAAe,IAAI,aAAa;AAAA,EACjD,QAAQ;AACV,CAAC;","names":["jsx","jsxs","open","runIfFn","jsx","jsxs","open"]}
|
package/package.json
CHANGED
@@ -1,32 +1,15 @@
|
|
1
1
|
{
|
2
2
|
"name": "@saas-ui/modals",
|
3
|
-
"version": "
|
3
|
+
"version": "3.0.0-alpha.0",
|
4
4
|
"description": "A modal manager for Chakra UI",
|
5
5
|
"source": "src/index.ts",
|
6
|
+
"type": "module",
|
6
7
|
"exports": {
|
7
8
|
".": {
|
9
|
+
"sui": "./src/index.ts",
|
8
10
|
"types": "./dist/index.d.ts",
|
9
|
-
"require": "./dist/index.
|
10
|
-
"import": "./dist/index.
|
11
|
-
},
|
12
|
-
"./zod": {
|
13
|
-
"types": "./dist/zod/index.d.ts",
|
14
|
-
"require": "./dist/zod/index.js",
|
15
|
-
"import": "./dist/zod/index.mjs"
|
16
|
-
},
|
17
|
-
"./zod/src": {
|
18
|
-
"default": "./src/zod/index.ts"
|
19
|
-
},
|
20
|
-
"./yup": {
|
21
|
-
"types": "./dist/yup/index.d.ts",
|
22
|
-
"require": "./dist/yup/index.js",
|
23
|
-
"import": "./dist/yup/index.mjs"
|
24
|
-
},
|
25
|
-
"./yup/src": {
|
26
|
-
"default": "./src/yup/index.ts"
|
27
|
-
},
|
28
|
-
"./src": {
|
29
|
-
"default": "./src/index.ts"
|
11
|
+
"require": "./dist/index.cjs",
|
12
|
+
"import": "./dist/index.js"
|
30
13
|
}
|
31
14
|
},
|
32
15
|
"typesVersions": {
|
@@ -41,8 +24,8 @@
|
|
41
24
|
]
|
42
25
|
}
|
43
26
|
},
|
44
|
-
"main": "./dist/index.
|
45
|
-
"module": "./dist/index.
|
27
|
+
"main": "./dist/index.cjs",
|
28
|
+
"module": "./dist/index.js",
|
46
29
|
"types": "./dist/index.d.ts",
|
47
30
|
"scripts": {
|
48
31
|
"clean": "rimraf dist",
|
@@ -59,12 +42,12 @@
|
|
59
42
|
"publishConfig": {
|
60
43
|
"access": "public"
|
61
44
|
},
|
62
|
-
"author": "Eelco Wiersma <eelco@
|
45
|
+
"author": "Eelco Wiersma <eelco@saas-ui.dev>",
|
63
46
|
"license": "MIT",
|
64
47
|
"homepage": "https://saas-ui.dev/",
|
65
48
|
"repository": {
|
66
49
|
"type": "git",
|
67
|
-
"url": "git+https://github.com/saas-js/saas-ui",
|
50
|
+
"url": "git+https://github.com/saas-js/saas-ui.git",
|
68
51
|
"directory": "packages/saas-ui-modals"
|
69
52
|
},
|
70
53
|
"keywords": [
|
@@ -85,16 +68,15 @@
|
|
85
68
|
"url": "https://storybook.saas-ui.dev"
|
86
69
|
},
|
87
70
|
"dependencies": {
|
88
|
-
"@
|
89
|
-
"@saas-ui/forms": "
|
90
|
-
"@saas-ui/hooks": "
|
91
|
-
"@saas-ui/
|
71
|
+
"@saas-ui/core": "3.0.0-alpha.0",
|
72
|
+
"@saas-ui/forms": "3.0.0-alpha.0",
|
73
|
+
"@saas-ui/hooks": "3.0.0-alpha.0",
|
74
|
+
"@saas-ui/modals-provider": "1.0.0-alpha.0"
|
92
75
|
},
|
93
76
|
"peerDependencies": {
|
94
|
-
"@chakra-ui/react": "
|
77
|
+
"@chakra-ui/react": "^3.0.0",
|
95
78
|
"@emotion/react": ">=11.0.0",
|
96
|
-
"@
|
97
|
-
"framer-motion": ">=6.0.0",
|
79
|
+
"@saas-ui/react": "3.0.0-alpha.0",
|
98
80
|
"react": ">=18.0.0",
|
99
81
|
"react-dom": ">=18.0.0"
|
100
82
|
},
|
@@ -0,0 +1,156 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
|
3
|
+
import { Button, ButtonProps, type HTMLChakraProps } from '@chakra-ui/react'
|
4
|
+
import { callAll } from '@saas-ui/core/utils'
|
5
|
+
import { Dialog } from '@saas-ui/react/dialog'
|
6
|
+
|
7
|
+
export interface AlertDialogProps
|
8
|
+
extends Omit<
|
9
|
+
Dialog.RootProps,
|
10
|
+
'leastDestructiveRef' | 'onOpenChange' | 'open'
|
11
|
+
> {
|
12
|
+
/**
|
13
|
+
* Whether the dialog is open
|
14
|
+
*/
|
15
|
+
open: boolean
|
16
|
+
/**
|
17
|
+
* Callback when the dialog is opened or closed
|
18
|
+
*/
|
19
|
+
onOpenChange: (details: { open: boolean }) => void
|
20
|
+
/**
|
21
|
+
* The dialog title
|
22
|
+
*/
|
23
|
+
title?: React.ReactNode
|
24
|
+
translations?: {
|
25
|
+
cancel?: React.ReactNode
|
26
|
+
confirm?: React.ReactNode
|
27
|
+
close?: React.ReactNode
|
28
|
+
}
|
29
|
+
slotProps?: {
|
30
|
+
cancel?: ButtonProps
|
31
|
+
confirm?: ButtonProps
|
32
|
+
footer?: HTMLChakraProps<'div'>
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Close the dialog on cancel
|
36
|
+
* @default true
|
37
|
+
*/
|
38
|
+
closeOnCancel?: boolean
|
39
|
+
/**
|
40
|
+
* Close the dialog on confirm
|
41
|
+
* @default true
|
42
|
+
*/
|
43
|
+
closeOnConfirm?: boolean
|
44
|
+
/**
|
45
|
+
* Hide the backdrop
|
46
|
+
*/
|
47
|
+
backdrop?: boolean
|
48
|
+
/**
|
49
|
+
* Hide the close button
|
50
|
+
*/
|
51
|
+
hideCloseButton?: boolean
|
52
|
+
/**
|
53
|
+
* Defines which button gets initial focus
|
54
|
+
* https://www.w3.org/TR/wai-aria-practices/#alertdialog
|
55
|
+
*/
|
56
|
+
leastDestructiveFocus?: 'cancel' | 'confirm'
|
57
|
+
/**
|
58
|
+
* Function that's called when cancel is clicked
|
59
|
+
*/
|
60
|
+
onCancel?: () => void
|
61
|
+
/**
|
62
|
+
* Function that's called when confirm is clicked.
|
63
|
+
*/
|
64
|
+
onConfirm?: () => Promise<void> | void
|
65
|
+
}
|
66
|
+
|
67
|
+
export const AlertDialog: React.FC<AlertDialogProps> = (props) => {
|
68
|
+
const {
|
69
|
+
title,
|
70
|
+
translations,
|
71
|
+
slotProps,
|
72
|
+
open,
|
73
|
+
closeOnCancel = true,
|
74
|
+
closeOnConfirm = true,
|
75
|
+
leastDestructiveFocus = 'cancel',
|
76
|
+
onOpenChange,
|
77
|
+
onCancel,
|
78
|
+
onConfirm,
|
79
|
+
children,
|
80
|
+
...rest
|
81
|
+
} = props
|
82
|
+
|
83
|
+
const cancelRef = React.useRef(null)
|
84
|
+
const confirmRef = React.useRef(null)
|
85
|
+
const [isLoading, setIsLoading] = React.useState(false)
|
86
|
+
|
87
|
+
const handleConfirm = async () => {
|
88
|
+
try {
|
89
|
+
const result = onConfirm?.()
|
90
|
+
if (typeof result?.then === 'function') {
|
91
|
+
setIsLoading(true)
|
92
|
+
await result
|
93
|
+
}
|
94
|
+
|
95
|
+
closeOnConfirm && onOpenChange({ open: false })
|
96
|
+
/* eslint-disable no-useless-catch */
|
97
|
+
} catch (e: any) {
|
98
|
+
throw e
|
99
|
+
} finally {
|
100
|
+
setIsLoading(false)
|
101
|
+
}
|
102
|
+
/* eslint-enable */
|
103
|
+
}
|
104
|
+
|
105
|
+
const titleId = React.useId()
|
106
|
+
const contentId = React.useId()
|
107
|
+
|
108
|
+
return (
|
109
|
+
<Dialog.Root
|
110
|
+
open={open}
|
111
|
+
onOpenChange={onOpenChange}
|
112
|
+
size="sm"
|
113
|
+
aria-labelledby={titleId}
|
114
|
+
aria-describedby={contentId}
|
115
|
+
{...rest}
|
116
|
+
initialFocusEl={() =>
|
117
|
+
leastDestructiveFocus === 'cancel'
|
118
|
+
? cancelRef.current
|
119
|
+
: confirmRef.current
|
120
|
+
}
|
121
|
+
>
|
122
|
+
<Dialog.Content>
|
123
|
+
<Dialog.Header>
|
124
|
+
<Dialog.Title id={titleId}>{title}</Dialog.Title>
|
125
|
+
</Dialog.Header>
|
126
|
+
|
127
|
+
<Dialog.Body id={contentId}>{children}</Dialog.Body>
|
128
|
+
|
129
|
+
<Dialog.Footer {...slotProps?.footer}>
|
130
|
+
<Button
|
131
|
+
ref={cancelRef}
|
132
|
+
variant="ghost"
|
133
|
+
colorPalette="gray"
|
134
|
+
{...slotProps?.cancel}
|
135
|
+
onClick={callAll(slotProps?.cancel?.onClick, () => {
|
136
|
+
onCancel?.()
|
137
|
+
|
138
|
+
closeOnCancel && onOpenChange({ open: false })
|
139
|
+
})}
|
140
|
+
>
|
141
|
+
{slotProps?.cancel?.children || translations?.cancel || 'Cancel'}
|
142
|
+
</Button>
|
143
|
+
<Button
|
144
|
+
ref={confirmRef}
|
145
|
+
variant="solid"
|
146
|
+
disabled={isLoading}
|
147
|
+
{...slotProps?.confirm}
|
148
|
+
onClick={callAll(handleConfirm, slotProps?.confirm?.onClick)}
|
149
|
+
>
|
150
|
+
{slotProps?.confirm?.children || translations?.confirm || 'OK'}
|
151
|
+
</Button>
|
152
|
+
</Dialog.Footer>
|
153
|
+
</Dialog.Content>
|
154
|
+
</Dialog.Root>
|
155
|
+
)
|
156
|
+
}
|
package/src/default-modals.ts
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
import {
|
2
|
-
import { MenuDialog } from './menu'
|
3
|
-
import { FormDialog } from './form'
|
1
|
+
import { AlertDialog } from './alert-dialog'
|
4
2
|
import { Drawer } from './drawer'
|
5
3
|
import { Modal } from './modal'
|
6
4
|
|
7
5
|
export const defaultModals = {
|
8
|
-
alert:
|
9
|
-
confirm:
|
6
|
+
alert: AlertDialog,
|
7
|
+
confirm: AlertDialog,
|
10
8
|
drawer: Drawer,
|
11
9
|
modal: Modal,
|
12
|
-
menu: MenuDialog,
|
13
|
-
form: FormDialog,
|
14
10
|
}
|
package/src/drawer.tsx
CHANGED
@@ -1,31 +1,28 @@
|
|
1
1
|
import * as React from 'react'
|
2
2
|
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
DrawerContent,
|
7
|
-
DrawerHeader,
|
8
|
-
DrawerFooter,
|
9
|
-
DrawerBody,
|
10
|
-
DrawerCloseButton,
|
11
|
-
DrawerProps as ChakraDrawerProps,
|
12
|
-
ModalHeaderProps,
|
13
|
-
ModalContentProps,
|
14
|
-
ModalFooterProps,
|
15
|
-
} from '@chakra-ui/react'
|
16
|
-
import { runIfFn, MaybeRenderProp } from '@chakra-ui/utils'
|
3
|
+
import { type HTMLChakraProps } from '@chakra-ui/react'
|
4
|
+
import { MaybeRenderProp, runIfFn } from '@saas-ui/core/utils'
|
5
|
+
import { Drawer as BaseDrawer } from '@saas-ui/react/drawer'
|
17
6
|
|
18
|
-
export interface
|
7
|
+
export interface DrawerProps extends Omit<BaseDrawer.RootProps, 'children'> {
|
19
8
|
/**
|
20
9
|
* The drawer title
|
21
10
|
*/
|
22
11
|
title: React.ReactNode
|
23
12
|
/**
|
24
|
-
*
|
13
|
+
* Whether the modal is open
|
14
|
+
*/
|
15
|
+
open: boolean
|
16
|
+
/**
|
17
|
+
* Callback when the drawer is opened or closed
|
18
|
+
*/
|
19
|
+
onOpenChange: (details: { open: boolean }) => void
|
20
|
+
/**
|
21
|
+
* The drawer children
|
25
22
|
*/
|
26
23
|
children: MaybeRenderProp<{
|
27
|
-
|
28
|
-
|
24
|
+
open: boolean
|
25
|
+
setOpen: (open: boolean) => void
|
29
26
|
}>
|
30
27
|
/**
|
31
28
|
* The modal footer
|
@@ -36,70 +33,59 @@ export interface BaseDrawerProps extends Omit<ChakraDrawerProps, 'children'> {
|
|
36
33
|
*/
|
37
34
|
hideCloseButton?: boolean
|
38
35
|
/**
|
39
|
-
* Hide the
|
36
|
+
* Hide the backdrop
|
40
37
|
*/
|
41
|
-
|
38
|
+
hideBackdrop?: boolean
|
42
39
|
/**
|
43
40
|
* Props for the modal header
|
44
41
|
*/
|
45
|
-
headerProps?:
|
42
|
+
headerProps?: HTMLChakraProps<'div'>
|
46
43
|
/**
|
47
44
|
* Props for the modal content
|
48
45
|
*/
|
49
|
-
contentProps?:
|
46
|
+
contentProps?: BaseDrawer.ContentProps
|
50
47
|
/**
|
51
48
|
* Props for the modal footer
|
52
49
|
*/
|
53
|
-
footerProps?:
|
50
|
+
footerProps?: HTMLChakraProps<'div'>
|
51
|
+
/**
|
52
|
+
* Props for the modal body
|
53
|
+
*/
|
54
|
+
bodyProps?: HTMLChakraProps<'div'>
|
54
55
|
}
|
55
56
|
|
56
|
-
export const
|
57
|
+
export const Drawer: React.FC<DrawerProps> = (props) => {
|
57
58
|
const {
|
58
59
|
title,
|
59
60
|
children,
|
60
61
|
footer,
|
61
|
-
|
62
|
-
|
62
|
+
open,
|
63
|
+
onOpenChange,
|
63
64
|
hideCloseButton,
|
64
|
-
|
65
|
+
hideBackdrop,
|
65
66
|
headerProps,
|
66
67
|
contentProps,
|
68
|
+
bodyProps,
|
67
69
|
footerProps,
|
68
70
|
...rest
|
69
71
|
} = props
|
70
72
|
return (
|
71
|
-
<
|
72
|
-
{!
|
73
|
-
<
|
74
|
-
{title &&
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
* Drawer footer content, wrapped with `DrawerFooter`
|
89
|
-
*/
|
90
|
-
footer?: React.ReactNode
|
91
|
-
}
|
92
|
-
|
93
|
-
export const Drawer: React.FC<DrawerProps> = (props) => {
|
94
|
-
const { children, isOpen, onClose, ...rest } = props
|
95
|
-
return (
|
96
|
-
<BaseDrawer isOpen={isOpen} onClose={onClose} {...rest}>
|
97
|
-
<DrawerBody>
|
98
|
-
{runIfFn(children, {
|
99
|
-
isOpen,
|
100
|
-
onClose,
|
101
|
-
})}
|
102
|
-
</DrawerBody>
|
103
|
-
</BaseDrawer>
|
73
|
+
<BaseDrawer.Root open={open} onOpenChange={onOpenChange} {...rest}>
|
74
|
+
{!hideBackdrop && <BaseDrawer.Backdrop />}
|
75
|
+
<BaseDrawer.Content {...contentProps}>
|
76
|
+
{title && (
|
77
|
+
<BaseDrawer.Header {...headerProps}>{title}</BaseDrawer.Header>
|
78
|
+
)}
|
79
|
+
{!hideCloseButton && <BaseDrawer.CloseTrigger />}
|
80
|
+
<BaseDrawer.Body {...bodyProps}>
|
81
|
+
<BaseDrawer.Context>
|
82
|
+
{({ open, setOpen }) => runIfFn(children, { open, setOpen })}
|
83
|
+
</BaseDrawer.Context>
|
84
|
+
</BaseDrawer.Body>
|
85
|
+
{footer && (
|
86
|
+
<BaseDrawer.Footer {...footerProps}>{footer}</BaseDrawer.Footer>
|
87
|
+
)}
|
88
|
+
</BaseDrawer.Content>
|
89
|
+
</BaseDrawer.Root>
|
104
90
|
)
|
105
91
|
}
|
package/src/form.tsx
CHANGED
@@ -1,24 +1,17 @@
|
|
1
1
|
import * as React from 'react'
|
2
2
|
|
3
|
+
import { Button, ButtonProps, Dialog } from '@chakra-ui/react'
|
4
|
+
import { runIfFn } from '@saas-ui/core/utils'
|
3
5
|
import {
|
4
|
-
ModalBody,
|
5
|
-
ModalFooter,
|
6
|
-
Button,
|
7
|
-
forwardRef,
|
8
|
-
ButtonProps,
|
9
|
-
} from '@chakra-ui/react'
|
10
|
-
import { runIfFn } from '@saas-ui/react-utils'
|
11
|
-
|
12
|
-
import {
|
13
|
-
Form,
|
14
6
|
AutoFields,
|
15
|
-
|
16
|
-
FormProps,
|
17
|
-
FieldValues,
|
18
|
-
FieldResolver,
|
7
|
+
DefaultFieldOverrides,
|
19
8
|
FieldProps,
|
9
|
+
FieldResolver,
|
10
|
+
FieldValues,
|
11
|
+
Form,
|
12
|
+
FormProps,
|
20
13
|
FormType,
|
21
|
-
|
14
|
+
SubmitButton,
|
22
15
|
} from '@saas-ui/forms'
|
23
16
|
|
24
17
|
import { BaseModal, BaseModalProps } from './modal'
|
@@ -137,7 +130,7 @@ type MergeDialogProps<T> =
|
|
137
130
|
type IsSchemaType<T, Schema, FieldDefs> =
|
138
131
|
T extends DefaultFormType<FieldDefs>
|
139
132
|
? T extends (
|
140
|
-
props: FormProps<infer TSchema, infer TFieldValues, infer TContext
|
133
|
+
props: FormProps<infer TSchema, infer TFieldValues, infer TContext>,
|
141
134
|
) => any
|
142
135
|
? Schema extends TSchema
|
143
136
|
? true
|
@@ -155,7 +148,7 @@ export type DefaultFormType<
|
|
155
148
|
TFieldValues extends Record<string, any> = any,
|
156
149
|
TContext extends object = object,
|
157
150
|
>(
|
158
|
-
props: any
|
151
|
+
props: any,
|
159
152
|
) => React.ReactElement) & {
|
160
153
|
displayName?: string
|
161
154
|
id?: string
|
@@ -173,7 +166,7 @@ export function createFormDialog<
|
|
173
166
|
ExtraOverrides
|
174
167
|
> = DefaultFormType<FieldDefs, ExtraProps, ExtraFieldProps, ExtraOverrides>,
|
175
168
|
>(Form: TFormType) {
|
176
|
-
const Dialog = forwardRef<
|
169
|
+
const Dialog = React.forwardRef<HTMLDivElement, any>((props, ref) => {
|
177
170
|
const { isOpen, onClose, footer, children, ...rest } = props
|
178
171
|
const { modalProps, formProps, fields } = useFormProps(rest)
|
179
172
|
return (
|
@@ -188,12 +181,12 @@ export function createFormDialog<
|
|
188
181
|
>
|
189
182
|
{(form: any) => (
|
190
183
|
<>
|
191
|
-
<
|
184
|
+
<Dialog.Body height="100%">
|
192
185
|
{runIfFn(children, form) || <AutoFields />}
|
193
|
-
</
|
186
|
+
</Dialog.Body>
|
194
187
|
|
195
188
|
{footer || (
|
196
|
-
<
|
189
|
+
<Dialog.Footer>
|
197
190
|
<Button
|
198
191
|
variant="ghost"
|
199
192
|
mr={3}
|
@@ -203,7 +196,7 @@ export function createFormDialog<
|
|
203
196
|
{fields?.cancel?.children ?? 'Cancel'}
|
204
197
|
</Button>
|
205
198
|
<SubmitButton {...fields?.submit} />
|
206
|
-
</
|
199
|
+
</Dialog.Footer>
|
207
200
|
)}
|
208
201
|
</>
|
209
202
|
)}
|