dynamic-modal 1.1.4 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README-ES.md +217 -217
  2. package/README.md +216 -216
  3. package/dist/components/input-upload/input-upload.js +1 -1
  4. package/dist/components/make-button/make-button.js +7 -17
  5. package/dist/components/make-input/make-input.js +7 -17
  6. package/dist/components/make-select/make-select.js +7 -17
  7. package/dist/components/make-textarea/make-textarea.js +7 -17
  8. package/dist/components/make-toggle/make-toggle.js +7 -17
  9. package/dist/components/portal/portal.js +7 -17
  10. package/dist/context/component/component-state.js +7 -17
  11. package/dist/interfaces/modal.d.ts +1 -0
  12. package/dist/modal.js +38 -19
  13. package/eslint.config.mjs +14 -14
  14. package/examples/enable-if.ts +127 -127
  15. package/examples/live-data.ts +61 -61
  16. package/examples/render-if.ts +128 -128
  17. package/examples/simple.ts +74 -74
  18. package/index.ts +5 -5
  19. package/package.json +46 -47
  20. package/src/components/input-upload/input-upload.tsx +67 -67
  21. package/src/components/make-button/make-button.tsx +18 -18
  22. package/src/components/make-description/make-description.tsx +15 -15
  23. package/src/components/make-input/make-input.tsx +53 -53
  24. package/src/components/make-select/make-select.tsx +55 -55
  25. package/src/components/make-textarea/make-textarea.tsx +53 -53
  26. package/src/components/make-toggle/make-toggle.tsx +53 -53
  27. package/src/components/make-upload/make-upload.tsx +40 -40
  28. package/src/components/portal/portal.tsx +37 -37
  29. package/src/context/component/component-state.tsx +17 -17
  30. package/src/hooks/field-render.ts +109 -109
  31. package/src/hooks/modal-handler.ts +38 -38
  32. package/src/interfaces/component-state.ts +33 -33
  33. package/src/interfaces/field.ts +37 -37
  34. package/src/interfaces/input-upload.ts +21 -21
  35. package/src/interfaces/make-button.ts +19 -19
  36. package/src/interfaces/make-description.ts +14 -14
  37. package/src/interfaces/make-field-group.ts +14 -14
  38. package/src/interfaces/make-input.ts +14 -14
  39. package/src/interfaces/make-select.ts +15 -15
  40. package/src/interfaces/make-textarea.ts +11 -11
  41. package/src/interfaces/make-toggle.ts +9 -9
  42. package/src/interfaces/make-upload.ts +14 -14
  43. package/src/interfaces/modal.ts +47 -46
  44. package/src/interfaces/option.ts +3 -3
  45. package/src/interfaces/portal.ts +8 -8
  46. package/src/modal.tsx +196 -164
  47. package/src/tools/general.ts +8 -8
  48. package/tsconfig.json +13 -13
@@ -1,15 +1,15 @@
1
- import { IField, IFieldProps } from './field'
2
- import { IModalLiveDataCondition } from './modal'
3
- import { IOption } from './option'
4
-
5
- export interface IMakeSelect extends IField {
6
- elementType: 'select'
7
- options: Array<IOption>
8
- liveData?: IModalLiveDataCondition
9
- isSearch?: boolean
10
- isMulti?: boolean
11
- }
12
-
13
- export interface IMakeSelectProps extends IFieldProps {
14
- element: Omit<IMakeSelect, 'elementType'>
15
- }
1
+ import { IField, IFieldProps } from './field'
2
+ import { IModalLiveDataCondition } from './modal'
3
+ import { IOption } from './option'
4
+
5
+ export interface IMakeSelect extends IField {
6
+ elementType: 'select'
7
+ options: Array<IOption>
8
+ liveData?: IModalLiveDataCondition
9
+ isSearch?: boolean
10
+ isMulti?: boolean
11
+ }
12
+
13
+ export interface IMakeSelectProps extends IFieldProps {
14
+ element: Omit<IMakeSelect, 'elementType'>
15
+ }
@@ -1,11 +1,11 @@
1
- import { IField, IFieldProps } from './field'
2
-
3
- export interface IMakeTextarea extends IField {
4
- elementType: 'textarea'
5
- cols?: number
6
- rows?: number
7
- }
8
-
9
- export interface IMakeTextareaProps extends IFieldProps {
10
- element: Omit<IMakeTextarea, 'elementType'>
11
- }
1
+ import { IField, IFieldProps } from './field'
2
+
3
+ export interface IMakeTextarea extends IField {
4
+ elementType: 'textarea'
5
+ cols?: number
6
+ rows?: number
7
+ }
8
+
9
+ export interface IMakeTextareaProps extends IFieldProps {
10
+ element: Omit<IMakeTextarea, 'elementType'>
11
+ }
@@ -1,9 +1,9 @@
1
- import { IField, IFieldProps } from './field'
2
-
3
- export interface IMakeToggle extends IField {
4
- elementType: 'toggle'
5
- }
6
-
7
- export interface IMakeToggleProps extends IFieldProps {
8
- element: Omit<IMakeToggle, 'elementType'>
9
- }
1
+ import { IField, IFieldProps } from './field'
2
+
3
+ export interface IMakeToggle extends IField {
4
+ elementType: 'toggle'
5
+ }
6
+
7
+ export interface IMakeToggleProps extends IFieldProps {
8
+ element: Omit<IMakeToggle, 'elementType'>
9
+ }
@@ -1,14 +1,14 @@
1
- import { IField, IFieldProps } from './field'
2
-
3
- export interface IMakeUpload extends Omit<IField, 'defaultValue'> {
4
- elementType: 'upload'
5
- helpText?: string
6
- read: boolean
7
- image?: boolean
8
- accept?:string
9
- readAsArrayBuffer?: boolean
10
- }
11
-
12
- export interface IMakeUploadProps extends IFieldProps {
13
- element: Omit<IMakeUpload, 'elementType'>
14
- }
1
+ import { IField, IFieldProps } from './field'
2
+
3
+ export interface IMakeUpload extends Omit<IField, 'defaultValue'> {
4
+ elementType: 'upload'
5
+ helpText?: string
6
+ read: boolean
7
+ image?: boolean
8
+ accept?:string
9
+ readAsArrayBuffer?: boolean
10
+ }
11
+
12
+ export interface IMakeUploadProps extends IFieldProps {
13
+ element: Omit<IMakeUpload, 'elementType'>
14
+ }
@@ -1,46 +1,47 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { CSSProperties } from 'react'
3
- import { IMakeSelect } from './make-select'
4
- import { IMakeInput } from './make-input'
5
- import { IMakeTextarea } from './make-textarea'
6
- import { IMakeToggle } from './make-toggle'
7
- import { IMakeDescription } from './make-description'
8
- import { IMakeFieldGroup } from './make-field-group'
9
- import { IMakeUpload } from './make-upload'
10
- import { IOption } from './option'
11
- import { IMakeButton } from './make-button'
12
-
13
- export type IModalField = IMakeSelect | IMakeInput | IMakeFieldGroup | IMakeTextarea | IMakeToggle | IMakeDescription | IMakeUpload | IMakeButton
14
-
15
- export type IFormField = IMakeSelect | IMakeInput | IMakeTextarea | IMakeToggle
16
-
17
- export type IModalRenderCondition = Record<string, Array<string | number | boolean> | undefined>
18
-
19
- export type IModalLiveDataCondition = {
20
- action: (data: string, ...args: any[]) => Promise<Array<IOption>>
21
- condition: Array<string>
22
- }
23
-
24
- export interface IModalConfigProps {
25
- reservedData?: Record<string, any>
26
- title: string
27
- fields: Array<IModalField>
28
- out: (data: any) => void
29
- onClose?: () => void
30
- style?: CSSProperties;
31
- overFlowBody?: string | number
32
- minHeightBody?: string | number
33
- actions: {
34
- containerStyle?: CSSProperties
35
- cancel?: Omit<IMakeButton, 'elementType'>
36
- action: Omit<IMakeButton, 'elementType'>
37
- }
38
- }
39
-
40
- export type IModalConfigLoader<T = any, D = any> = (props: T, action: (modalResult: D) => void) => IModalConfigProps
41
-
42
- export interface IModal {
43
- open: boolean;
44
- close: () => void
45
- config: IModalConfigProps
46
- }
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { CSSProperties } from 'react'
3
+ import { IMakeSelect } from './make-select'
4
+ import { IMakeInput } from './make-input'
5
+ import { IMakeTextarea } from './make-textarea'
6
+ import { IMakeToggle } from './make-toggle'
7
+ import { IMakeDescription } from './make-description'
8
+ import { IMakeFieldGroup } from './make-field-group'
9
+ import { IMakeUpload } from './make-upload'
10
+ import { IOption } from './option'
11
+ import { IMakeButton } from './make-button'
12
+
13
+ export type IModalField = IMakeSelect | IMakeInput | IMakeFieldGroup | IMakeTextarea | IMakeToggle | IMakeDescription | IMakeUpload | IMakeButton
14
+
15
+ export type IFormField = IMakeSelect | IMakeInput | IMakeTextarea | IMakeToggle
16
+
17
+ export type IModalRenderCondition = Record<string, Array<string | number | boolean> | undefined>
18
+
19
+ export type IModalLiveDataCondition = {
20
+ action: (data: string, ...args: any[]) => Promise<Array<IOption>>
21
+ condition: Array<string>
22
+ }
23
+
24
+ export interface IModalConfigProps {
25
+ reservedData?: Record<string, any>
26
+ title: string
27
+ fields: Array<IModalField>
28
+ out: (data: any) => void
29
+ onClose?: () => void
30
+ style?: CSSProperties
31
+ overFlowBody?: string | number
32
+ minHeightBody?: string | number
33
+ useSubmit?: boolean
34
+ actions: {
35
+ containerStyle?: CSSProperties
36
+ cancel?: Omit<IMakeButton, 'elementType'>
37
+ action: Omit<IMakeButton, 'elementType'>
38
+ }
39
+ }
40
+
41
+ export type IModalConfigLoader<T = any, D = any> = (props: T, action: (modalResult: D) => void) => IModalConfigProps
42
+
43
+ export interface IModal {
44
+ open: boolean
45
+ close: () => void
46
+ config: IModalConfigProps
47
+ }
@@ -1,4 +1,4 @@
1
- export interface IOption {
2
- id: string
3
- name: string
1
+ export interface IOption {
2
+ id: string
3
+ name: string
4
4
  }
@@ -1,8 +1,8 @@
1
- import { ReactNode } from 'react'
2
-
3
- export interface IPortal {
4
- children: ReactNode
5
- closeTime: number
6
- portalOpen: boolean
7
- portalTag?: string
8
- }
1
+ import { ReactNode } from 'react'
2
+
3
+ export interface IPortal {
4
+ children: ReactNode
5
+ closeTime: number
6
+ portalOpen: boolean
7
+ portalTag?: string
8
+ }
package/src/modal.tsx CHANGED
@@ -1,164 +1,196 @@
1
- 'use client'
2
-
3
- import React, { useContext, useEffect, useState } from 'react'
4
- import { useForm } from 'react-hook-form'
5
- import { Portal } from './components/portal/portal'
6
- import MakeToggle from './components/make-toggle/make-toggle'
7
- import MakeInput from './components/make-input/make-input'
8
- import MakeSelect from './components/make-select/make-select'
9
- import MakeTextarea from './components/make-textarea/make-textarea'
10
- import { IModal, IModalField, IModalConfigProps, IFormField } from './interfaces/modal'
11
- import MakeDescription from './components/make-description/make-description'
12
- import { IFieldProps } from './interfaces/field'
13
- import MakeUpload from './components/make-upload/make-upload'
14
- import MakeButton from './components/make-button/make-button'
15
- import { IMakeInput } from './interfaces/make-input'
16
- import { IMakeSelect } from './interfaces/make-select'
17
- import { IMakeTextarea } from './interfaces/make-textarea'
18
- import { IMakeToggle } from './interfaces/make-toggle'
19
- import { IMakeDescription } from './interfaces/make-description'
20
- import { IMakeUpload } from './interfaces/make-upload'
21
- import { IMakeButton } from './interfaces/make-button'
22
- import { ComponentStateContext } from './context/component/component-state'
23
-
24
- export const Modal = ({ open, close, config }: IModal) => {
25
- const { ModalButtonAction, ModalButtonCancel } = useContext(ComponentStateContext)
26
- const [modalReady, setModalReady] = useState<IModalConfigProps | undefined>(undefined)
27
- const [defaultLoaded, setDefaultLoaded] = useState<boolean>(false)
28
-
29
- const {
30
- control,
31
- handleSubmit,
32
- getValues,
33
- unregister,
34
- setValue,
35
- watch
36
- } = useForm()
37
-
38
- const formValueHandler = (element: IFormField) => {
39
- if (['group', 'upload', 'text'].includes(element.elementType)) return
40
- if(!element.defaultValue && element.renderIf) {
41
- unregister(element.name)
42
- return
43
- }
44
-
45
- const defaultValue = element.defaultValue ?? ''
46
- const parsedValue: boolean | string | Array<string> | undefined = defaultValue === 'true' ? true : defaultValue === 'false' ? false : defaultValue
47
- setValue(element.name, parsedValue ?? '')
48
- }
49
-
50
- const autoLoadGroup = (groupFields: Array<IModalField>) => {
51
- groupFields.forEach(element => {
52
- formValueHandler(element as IFormField)
53
- })
54
- }
55
-
56
- const autoLoadField = (modalFields: Array<IModalField>) => {
57
- if (defaultLoaded) return
58
-
59
- modalFields.forEach(element => {
60
- if (element.elementType === 'group') {
61
- autoLoadGroup(element.groups)
62
- return
63
- }
64
- formValueHandler(element as IFormField)
65
- })
66
-
67
- setDefaultLoaded(true)
68
- }
69
-
70
- const getRender = ({ elementType, ...element }: IModalField, index: number, isEndOfRender: boolean = false) => {
71
- if (isEndOfRender && modalReady) setTimeout(() => autoLoadField(modalReady.fields), 200)
72
-
73
- const props: IFieldProps = {
74
- control,
75
- watch,
76
- setValue,
77
- unregister
78
- }
79
-
80
- return elementType === 'input'
81
- ? <MakeInput {...props} key={`modal-input-${index}`} element={element as IMakeInput} />
82
- : elementType === 'select'
83
- ? <MakeSelect {...props} key={`modal-select-${index}`} element={element as IMakeSelect} />
84
- : elementType === 'textarea'
85
- ? <MakeTextarea {...props} key={`modal-textarea-${index}`} element={element as IMakeTextarea} />
86
- : elementType === 'toggle'
87
- ? <MakeToggle {...props} key={`modal-toggle-${index}`} element={element as IMakeToggle} />
88
- : elementType === 'text'
89
- ? <MakeDescription {...props} key={`modal-text-${index}`} element={element as IMakeDescription} />
90
- : elementType === 'upload'
91
- ? <MakeUpload {...props} key={`modal-upload-${index}`} element={element as IMakeUpload} />
92
- : elementType === 'button'
93
- ? <MakeButton {...props} key={`modal-button-${index}`} element={element as IMakeButton} />
94
- : null
95
- }
96
-
97
- const closeHandler = (): void => {
98
- if (modalReady?.onClose) modalReady.onClose()
99
-
100
- setTimeout(() => {
101
- const form = getValues()
102
- unregister(Object.keys(form))
103
- setModalReady(undefined)
104
- setDefaultLoaded(false)
105
- close()
106
- }, 200)
107
- }
108
-
109
- const actionHandler = (data: Record<string, string | number | object>): void => {
110
- modalReady?.out({ ...(modalReady?.reservedData ?? {}), ...data })
111
- closeHandler()
112
- }
113
-
114
- useEffect(() => {
115
- if (open && !modalReady) setModalReady(config)
116
- }, [config, modalReady, open])
117
-
118
- return (
119
- modalReady
120
- ? <Portal closeTime={200} portalOpen={open} portalTag={'#modal-portal'}>
121
- <div className='rounded bg-white relative w-auto h-auto min-h-[200px] min-w-[500px]' style={modalReady.style} >
122
- <form className='flex flex-col p-4 gap-4' autoComplete='off' onSubmit={handleSubmit(actionHandler)}>
123
- <h2 className='text-bold text-center border-b pb-4 font-semibold'>{modalReady.title}</h2>
124
- <div
125
- className='flex flex-col gap-4 py-4'
126
- style={{
127
- overflowY: modalReady.overFlowBody ? 'auto' : undefined,
128
- height: modalReady.overFlowBody,
129
- minHeight: modalReady.minHeightBody
130
- }}
131
- >
132
- {
133
- modalReady.fields.map((element, index) => {
134
- const isEndOfRender: boolean = index + 1 === modalReady.fields.length
135
-
136
- if (element.elementType === 'group') {
137
- return (
138
- <div key={`modal-group-${index}`} className='flex flex-col w-full gap-2'>
139
- { element.title && <h3 className='font-bold border-b-2 pb-2 mb-2'>{element.title}</h3> }
140
- <div key={`modal-group-${index}`} className='flex gap-4 w-full' style={element.style}>
141
- {
142
- element.groups
143
- .filter(sub => ['input', 'select', 'toggle', 'multiselect', 'upload', 'button', 'autocomplete'].includes(sub.elementType))
144
- .map((sub, subIndex) => getRender(sub, index + subIndex, isEndOfRender))
145
- }
146
- </div>
147
- </div>
148
- )
149
- } else { return getRender(element, index, isEndOfRender) }
150
- })
151
- }
152
- </div>
153
- <div className='flex gap-4 items-center justify-center border-t' style={modalReady?.actions.containerStyle}>
154
- {modalReady.actions.cancel && <ModalButtonCancel {...modalReady.actions.cancel} onClick={closeHandler} />}
155
- <ModalButtonAction {...modalReady.actions.action} type='submit' />
156
- </div>
157
- </form>
158
- </div>
159
- </Portal>
160
- : null
161
- )
162
- }
163
-
164
- export default Modal
1
+ 'use client'
2
+
3
+ import React, { useContext, useEffect, useState } from 'react'
4
+ import { useForm } from 'react-hook-form'
5
+ import { Portal } from './components/portal/portal'
6
+ import MakeToggle from './components/make-toggle/make-toggle'
7
+ import MakeInput from './components/make-input/make-input'
8
+ import MakeSelect from './components/make-select/make-select'
9
+ import MakeTextarea from './components/make-textarea/make-textarea'
10
+ import { IModal, IModalField, IModalConfigProps, IFormField } from './interfaces/modal'
11
+ import MakeDescription from './components/make-description/make-description'
12
+ import { IFieldProps } from './interfaces/field'
13
+ import MakeUpload from './components/make-upload/make-upload'
14
+ import MakeButton from './components/make-button/make-button'
15
+ import { IMakeInput } from './interfaces/make-input'
16
+ import { IMakeSelect } from './interfaces/make-select'
17
+ import { IMakeTextarea } from './interfaces/make-textarea'
18
+ import { IMakeToggle } from './interfaces/make-toggle'
19
+ import { IMakeDescription } from './interfaces/make-description'
20
+ import { IMakeUpload } from './interfaces/make-upload'
21
+ import { IMakeButton } from './interfaces/make-button'
22
+ import { ComponentStateContext } from './context/component/component-state'
23
+
24
+ export const Modal = ({ open, close, config }: IModal) => {
25
+ const { ModalButtonAction, ModalButtonCancel } = useContext(ComponentStateContext)
26
+ const [modalReady, setModalReady] = useState<IModalConfigProps | undefined>(undefined)
27
+ const [defaultLoaded, setDefaultLoaded] = useState<boolean>(false)
28
+
29
+ const {
30
+ control,
31
+ handleSubmit,
32
+ getValues,
33
+ unregister,
34
+ setValue,
35
+ watch,
36
+ trigger,
37
+ getFieldState
38
+ } = useForm()
39
+
40
+ const formValueHandler = (element: IFormField) => {
41
+ if (['group', 'upload', 'text'].includes(element.elementType)) return
42
+ if(!element.defaultValue && element.renderIf) {
43
+ unregister(element.name)
44
+ return
45
+ }
46
+
47
+ const defaultValue = element.defaultValue ?? ''
48
+ const parsedValue: boolean | string | Array<string> | undefined = defaultValue === 'true' ? true : defaultValue === 'false' ? false : defaultValue
49
+ setValue(element.name, parsedValue ?? '')
50
+ }
51
+
52
+ const autoLoadGroup = (groupFields: Array<IModalField>) => {
53
+ groupFields.forEach(element => {
54
+ formValueHandler(element as IFormField)
55
+ })
56
+ }
57
+
58
+ const autoLoadField = (modalFields: Array<IModalField>) => {
59
+ if (defaultLoaded) return
60
+
61
+ modalFields.forEach(element => {
62
+ if (element.elementType === 'group') {
63
+ autoLoadGroup(element.groups)
64
+ return
65
+ }
66
+ formValueHandler(element as IFormField)
67
+ })
68
+
69
+ setDefaultLoaded(true)
70
+ }
71
+
72
+
73
+ const getUseSubmit = (modalConfig: IModalConfigProps): boolean => {
74
+ const useSubmit = modalConfig.useSubmit === undefined ? true : modalConfig.useSubmit === false ? false : true
75
+
76
+ return useSubmit
77
+ }
78
+
79
+ const getRender = ({ elementType, ...element }: IModalField, index: number, isEndOfRender: boolean = false) => {
80
+ if (isEndOfRender && modalReady) setTimeout(() => autoLoadField(modalReady.fields), 200)
81
+
82
+ const props: IFieldProps = {
83
+ control,
84
+ watch,
85
+ setValue,
86
+ unregister
87
+ }
88
+
89
+ return elementType === 'input'
90
+ ? <MakeInput {...props} key={`modal-input-${index}`} element={element as IMakeInput} />
91
+ : elementType === 'select'
92
+ ? <MakeSelect {...props} key={`modal-select-${index}`} element={element as IMakeSelect} />
93
+ : elementType === 'textarea'
94
+ ? <MakeTextarea {...props} key={`modal-textarea-${index}`} element={element as IMakeTextarea} />
95
+ : elementType === 'toggle'
96
+ ? <MakeToggle {...props} key={`modal-toggle-${index}`} element={element as IMakeToggle} />
97
+ : elementType === 'text'
98
+ ? <MakeDescription {...props} key={`modal-text-${index}`} element={element as IMakeDescription} />
99
+ : elementType === 'upload'
100
+ ? <MakeUpload {...props} key={`modal-upload-${index}`} element={element as IMakeUpload} />
101
+ : elementType === 'button'
102
+ ? <MakeButton {...props} key={`modal-button-${index}`} element={element as IMakeButton} />
103
+ : null
104
+ }
105
+
106
+
107
+ const closeHandler = (): void => {
108
+ if (modalReady?.onClose) modalReady.onClose()
109
+
110
+ setTimeout(() => {
111
+ const form = getValues()
112
+ unregister(Object.keys(form))
113
+ setModalReady(undefined)
114
+ setDefaultLoaded(false)
115
+ close()
116
+ }, 200)
117
+ }
118
+
119
+ const manualSubmit = async (): Promise<void> => {
120
+ const form = getValues()
121
+ const fields = Object.keys(form)
122
+ await trigger(fields)
123
+
124
+ const validations: Array<boolean> = fields.map(field => {
125
+ const { invalid } = getFieldState(field)
126
+
127
+ return invalid
128
+ })
129
+
130
+ const result = validations.some(isInvalid => isInvalid) ? undefined : form
131
+
132
+ if(!result) return
133
+
134
+ actionHandler({ ...(modalReady?.reservedData ?? {}), ...form })
135
+ }
136
+
137
+ const actionHandler = (data: Record<string, string | number | object>): void => {
138
+ modalReady?.out({ ...(modalReady?.reservedData ?? {}), ...data })
139
+ closeHandler()
140
+ }
141
+
142
+ useEffect(() => {
143
+ if (open && !modalReady) setModalReady(config)
144
+ }, [config, modalReady, open])
145
+
146
+ return (
147
+ modalReady
148
+ ? <Portal closeTime={200} portalOpen={open} portalTag={'#modal-portal'}>
149
+ <div className='rounded bg-white relative w-auto h-auto min-h-[200px] min-w-[500px]' style={modalReady.style} >
150
+ <form className='flex flex-col p-4 gap-4' autoComplete='off' onSubmit={handleSubmit(actionHandler)}>
151
+ <h2 className='text-bold text-center border-b pb-4 font-semibold'>{modalReady.title}</h2>
152
+ <div
153
+ className='flex flex-col gap-4 py-4'
154
+ style={{
155
+ overflowY: modalReady.overFlowBody ? 'auto' : undefined,
156
+ height: modalReady.overFlowBody,
157
+ minHeight: modalReady.minHeightBody
158
+ }}
159
+ >
160
+ {
161
+ modalReady.fields.map((element, index) => {
162
+ const isEndOfRender: boolean = index + 1 === modalReady.fields.length
163
+
164
+ if (element.elementType === 'group') {
165
+ return (
166
+ <div key={`modal-group-${index}`} className='flex flex-col w-full gap-2'>
167
+ { element.title && <h3 className='font-bold border-b-2 pb-2 mb-2'>{element.title}</h3> }
168
+ <div key={`modal-group-${index}`} className='flex gap-4 w-full' style={element.style}>
169
+ {
170
+ element.groups
171
+ .filter(sub => ['input', 'select', 'toggle', 'multiselect', 'upload', 'button', 'autocomplete'].includes(sub.elementType))
172
+ .map((sub, subIndex) => getRender(sub, index + subIndex, isEndOfRender))
173
+ }
174
+ </div>
175
+ </div>
176
+ )
177
+ } else { return getRender(element, index, isEndOfRender) }
178
+ })
179
+ }
180
+ </div>
181
+ <div className='flex gap-4 items-center justify-center border-t' style={modalReady?.actions.containerStyle}>
182
+ {modalReady.actions.cancel && <ModalButtonCancel {...modalReady.actions.cancel} onClick={closeHandler} />}
183
+ {
184
+ getUseSubmit(modalReady) ?
185
+ <ModalButtonAction {...modalReady.actions.action} type='submit' />:
186
+ <ModalButtonAction {...modalReady.actions.action} onClick={manualSubmit} type='button' />
187
+ }
188
+ </div>
189
+ </form>
190
+ </div>
191
+ </Portal>
192
+ : null
193
+ )
194
+ }
195
+
196
+ export default Modal
@@ -1,8 +1,8 @@
1
- 'use client'
2
-
3
- export const generateId = (): string => {
4
- return Math.random()
5
- .toString(36)
6
- .split('.')[1]
7
- .substring(0, 6)
8
- }
1
+ 'use client'
2
+
3
+ export const generateId = (): string => {
4
+ return Math.random()
5
+ .toString(36)
6
+ .split('.')[1]
7
+ .substring(0, 6)
8
+ }
package/tsconfig.json CHANGED
@@ -1,13 +1,13 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2016",
4
- "module": "commonjs",
5
- "declaration": true,
6
- "outDir": "./dist",
7
- "strict": true,
8
- "jsx": "react",
9
- "esModuleInterop": true,
10
- "skipLibCheck": true
11
- },
12
- "include": ["src/**/*"]
13
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2016",
4
+ "module": "commonjs",
5
+ "declaration": true,
6
+ "outDir": "./dist",
7
+ "strict": true,
8
+ "jsx": "react",
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": ["src/**/*"]
13
+ }