Form prototype
This commit is contained in:
146
src/Form/containers/Drawer/SuperFormDrawer.tsx
Normal file
146
src/Form/containers/Drawer/SuperFormDrawer.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState,
|
||||
type ReactElement,
|
||||
type Ref,
|
||||
} from 'react'
|
||||
import { IconX } from '@tabler/icons-react'
|
||||
import type { FieldValues } from 'react-hook-form'
|
||||
import { ActionIcon, Drawer } from '@mantine/core'
|
||||
import type { SuperFormDrawerProps, SuperFormDrawerRef, SuperFormRef } from '../../types'
|
||||
import SuperForm from '../../components/SuperForm'
|
||||
import { openConfirmModal } from '../../utils/openConfirmModal'
|
||||
|
||||
const SuperFormDrawer = <T extends FieldValues>(
|
||||
{ drawerProps, noCloseOnSubmit, ...formProps }: SuperFormDrawerProps<T>,
|
||||
ref: Ref<SuperFormDrawerRef<T>>
|
||||
) => {
|
||||
// Component Refs
|
||||
const formRef = useRef<SuperFormRef<T>>(null)
|
||||
const drawerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
// Component store State
|
||||
// Tell drawer that form layout mounted to fix refs
|
||||
const [layoutMounted, setLayoutMounted] = useState(false)
|
||||
|
||||
// Component Callback Functions
|
||||
const onSubmit = (data: T, request, formData, form, closeForm: boolean = true) => {
|
||||
formProps?.onSubmit?.(data, request, formData, form, closeForm)
|
||||
|
||||
if (request === 'delete') {
|
||||
drawerProps?.onClose()
|
||||
}
|
||||
|
||||
if (!noCloseOnSubmit) {
|
||||
if (closeForm) {
|
||||
drawerProps?.onClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onCancel = (request) => {
|
||||
if (formRef?.current?.getFormState().isDirty) {
|
||||
openConfirmModal(() => {
|
||||
drawerProps?.onClose()
|
||||
formProps?.onCancel?.(request)
|
||||
})
|
||||
} else {
|
||||
drawerProps?.onClose()
|
||||
formProps?.onCancel?.(request)
|
||||
}
|
||||
}
|
||||
|
||||
const onLayoutMounted = useCallback(() => {
|
||||
setLayoutMounted(true)
|
||||
formProps?.onLayoutMounted?.()
|
||||
}, [formProps?.onLayoutMounted])
|
||||
|
||||
const onLayoutUnMounted = useCallback(() => {
|
||||
setLayoutMounted(false)
|
||||
formProps?.onLayoutUnMounted?.()
|
||||
}, [formProps?.onLayoutUnMounted])
|
||||
|
||||
// Component use Effects
|
||||
useImperativeHandle<SuperFormDrawerRef<T>, SuperFormDrawerRef<T>>(
|
||||
ref,
|
||||
() => ({
|
||||
...formRef.current,
|
||||
drawer: drawerRef.current,
|
||||
} as SuperFormDrawerRef<T>),
|
||||
[layoutMounted]
|
||||
)
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
ref={drawerRef}
|
||||
onClose={onCancel}
|
||||
closeOnClickOutside={false}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape' && drawerProps.closeOnEscape !== false) {
|
||||
e.stopPropagation()
|
||||
onCancel(formProps.request)
|
||||
}
|
||||
}}
|
||||
overlayProps={{ backgroundOpacity: 0.5, blur: 0.5 }}
|
||||
padding={6}
|
||||
position='right'
|
||||
transitionProps={{
|
||||
transition: 'slide-left',
|
||||
duration: 150,
|
||||
timingFunction: 'linear',
|
||||
}}
|
||||
size={500}
|
||||
styles={{
|
||||
content: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'stretch',
|
||||
},
|
||||
body: {
|
||||
minHeight: '100px',
|
||||
flexGrow: 1,
|
||||
},
|
||||
}}
|
||||
keepMounted={false}
|
||||
{...drawerProps}
|
||||
closeOnEscape={false}
|
||||
withCloseButton={false}
|
||||
title={null}
|
||||
>
|
||||
<SuperForm<T>
|
||||
{...formProps}
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
onLayoutMounted={onLayoutMounted}
|
||||
onLayoutUnMounted={onLayoutUnMounted}
|
||||
ref={formRef}
|
||||
layoutProps={{
|
||||
...formProps?.layoutProps,
|
||||
rightSection: (
|
||||
<ActionIcon
|
||||
size='xs'
|
||||
onClick={() => {
|
||||
onCancel(formProps?.request)
|
||||
}}
|
||||
>
|
||||
<IconX size={18} />
|
||||
</ActionIcon>
|
||||
),
|
||||
title:
|
||||
(drawerProps.title as string) ??
|
||||
formProps?.layoutProps?.title ??
|
||||
(formProps?.request as string),
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
|
||||
const FRSuperFormDrawer = forwardRef(SuperFormDrawer) as <T extends FieldValues>(
|
||||
props: SuperFormDrawerProps<T> & { ref?: Ref<SuperFormDrawerRef<T>> }
|
||||
) => ReactElement
|
||||
|
||||
export default FRSuperFormDrawer
|
||||
Reference in New Issue
Block a user