dynamic-modal 1.0.11 → 1.0.13

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 (58) hide show
  1. package/.idea/dynamic-modal.iml +12 -0
  2. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  3. package/.idea/modules.xml +8 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/README-ES.md +119 -119
  6. package/README.md +119 -119
  7. package/dist/components/input-upload/input-upload.js +18 -8
  8. package/dist/components/make-autocomplete/make-autocomplete.js +24 -17
  9. package/dist/components/make-input/make-input.js +24 -17
  10. package/dist/components/make-multi-select/make-multi-select.js +24 -17
  11. package/dist/components/make-select/make-select.js +24 -17
  12. package/dist/components/make-textarea/make-textarea.js +23 -16
  13. package/dist/components/make-toggle/make-toggle.js +36 -14
  14. package/dist/components/make-upload/make-upload.js +20 -8
  15. package/dist/components/portal/portal.js +17 -7
  16. package/dist/interfaces/field.d.ts +7 -4
  17. package/dist/interfaces/input-upload.d.ts +1 -15
  18. package/dist/modal.js +17 -7
  19. package/eslint.config.mjs +13 -13
  20. package/examples/enable-if.ts +129 -129
  21. package/examples/live-data.ts +63 -63
  22. package/examples/render-if.ts +130 -130
  23. package/examples/simple.ts +76 -76
  24. package/index.ts +2 -2
  25. package/package.json +48 -48
  26. package/src/components/input-upload/input-upload.tsx +72 -72
  27. package/src/components/make-autocomplete/make-autocomplete.tsx +54 -53
  28. package/src/components/make-button/make-button.tsx +17 -17
  29. package/src/components/make-input/make-input.tsx +47 -46
  30. package/src/components/make-multi-select/make-multi-select.tsx +56 -55
  31. package/src/components/make-select/make-select.tsx +54 -53
  32. package/src/components/make-text/make-text.tsx +16 -16
  33. package/src/components/make-textarea/make-textarea.tsx +48 -47
  34. package/src/components/make-title/make-title.tsx +12 -12
  35. package/src/components/make-toggle/make-toggle.tsx +44 -44
  36. package/src/components/make-upload/make-upload.tsx +34 -41
  37. package/src/components/portal/portal.tsx +36 -36
  38. package/src/hooks/field-render.ts +108 -108
  39. package/src/hooks/modal-handler.ts +37 -37
  40. package/src/interfaces/field.ts +35 -31
  41. package/src/interfaces/input-upload.ts +21 -37
  42. package/src/interfaces/make-autocomplete.ts +13 -13
  43. package/src/interfaces/make-button.ts +20 -20
  44. package/src/interfaces/make-field-group.ts +13 -13
  45. package/src/interfaces/make-field.ts +14 -14
  46. package/src/interfaces/make-multi-select.ts +14 -14
  47. package/src/interfaces/make-select.ts +12 -12
  48. package/src/interfaces/make-text.ts +12 -12
  49. package/src/interfaces/make-textarea.ts +11 -11
  50. package/src/interfaces/make-title.ts +3 -3
  51. package/src/interfaces/make-toggle.ts +9 -9
  52. package/src/interfaces/make-upload.ts +14 -14
  53. package/src/interfaces/modal.ts +51 -51
  54. package/src/interfaces/option.ts +3 -3
  55. package/src/interfaces/portal.ts +8 -8
  56. package/src/modal.tsx +174 -174
  57. package/src/tools/general.ts +6 -6
  58. package/tsconfig.json +13 -13
@@ -1,77 +1,77 @@
1
- import { IModalConfigLoader } from '../src/interfaces/modal'
2
-
3
- type IncomingProps = {
4
- reserved: string
5
- input1: string
6
- store?: boolean
7
- clear?: boolean
8
- }
9
-
10
- type ResultProps = IncomingProps
11
-
12
- export interface ISimpleModal {
13
- default: IModalConfigLoader<IncomingProps, ResultProps> //Define others modals if you want
14
- }
15
-
16
- const simpleModal: ISimpleModal = {
17
- default: (props, action) => {
18
- return {
19
- reservedData: { reserved: props.reserved }, //Put here any data that you want store and receive into modal output
20
- fields: [ //Put here any elements for render into modal
21
- {
22
- elementType: 'input',
23
- label: 'Input 1',
24
- defaultValue: props.input1,
25
- name: 'input1',
26
- validation: {
27
- required: true,
28
- message: 'This field is required',
29
- regex: undefined //Use regex for custom validation
30
- }
31
- },
32
- {
33
- elementType: 'group', //Put here groups of element into same line and customize using styles
34
- groups: [
35
- {
36
- elementType: 'toggle',
37
- label: 'Store',
38
- defaultValue: `${props.store ?? false}`,
39
- name: 'store',
40
- styles: {
41
- width: '50%'
42
- },
43
- validation: {
44
- required: false
45
- }
46
- },
47
- {
48
- elementType: 'toggle',
49
- label: 'Clear',
50
- defaultValue: `${props.clear ?? false}`,
51
- name: 'clear',
52
- styles: {
53
- width: '50%'
54
- },
55
- validation: {
56
- required: false
57
- }
58
- }
59
- ]
60
- },
61
- ],
62
- styles: { // Put here styles for modal like height or width
63
- width: '500px'
64
- },
65
- title: `Title of simple modal`, //Title of modal
66
- action: {
67
- name: 'Save', //Name of action button
68
- action //Function to receive data from modal
69
- },
70
- cancel: {
71
- name: 'Cancel', //Name of cancel button
72
- }
73
- }
74
- }
75
- }
76
-
1
+ import { IModalConfigLoader } from '../src/interfaces/modal'
2
+
3
+ type IncomingProps = {
4
+ reserved: string
5
+ input1: string
6
+ store?: boolean
7
+ clear?: boolean
8
+ }
9
+
10
+ type ResultProps = IncomingProps
11
+
12
+ export interface ISimpleModal {
13
+ default: IModalConfigLoader<IncomingProps, ResultProps> //Define others modals if you want
14
+ }
15
+
16
+ const simpleModal: ISimpleModal = {
17
+ default: (props, action) => {
18
+ return {
19
+ reservedData: { reserved: props.reserved }, //Put here any data that you want store and receive into modal output
20
+ fields: [ //Put here any elements for render into modal
21
+ {
22
+ elementType: 'input',
23
+ label: 'Input 1',
24
+ defaultValue: props.input1,
25
+ name: 'input1',
26
+ validation: {
27
+ required: true,
28
+ message: 'This field is required',
29
+ regex: undefined //Use regex for custom validation
30
+ }
31
+ },
32
+ {
33
+ elementType: 'group', //Put here groups of element into same line and customize using styles
34
+ groups: [
35
+ {
36
+ elementType: 'toggle',
37
+ label: 'Store',
38
+ defaultValue: `${props.store ?? false}`,
39
+ name: 'store',
40
+ styles: {
41
+ width: '50%'
42
+ },
43
+ validation: {
44
+ required: false
45
+ }
46
+ },
47
+ {
48
+ elementType: 'toggle',
49
+ label: 'Clear',
50
+ defaultValue: `${props.clear ?? false}`,
51
+ name: 'clear',
52
+ styles: {
53
+ width: '50%'
54
+ },
55
+ validation: {
56
+ required: false
57
+ }
58
+ }
59
+ ]
60
+ },
61
+ ],
62
+ styles: { // Put here styles for modal like height or width
63
+ width: '500px'
64
+ },
65
+ title: `Title of simple modal`, //Title of modal
66
+ action: {
67
+ name: 'Save', //Name of action button
68
+ action //Function to receive data from modal
69
+ },
70
+ cancel: {
71
+ name: 'Cancel', //Name of cancel button
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
77
  export default simpleModal
package/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { default as DynamicModal } from './src/modal';
2
- export type { IModalConfigLoader, IModalConfigProps, IModalRenderCondition, IModalField, IModalLiveDataCondition } from './src/interfaces/modal'
1
+ export { default as DynamicModal } from './src/modal';
2
+ export type { IModalConfigLoader, IModalConfigProps, IModalRenderCondition, IModalField, IModalLiveDataCondition } from './src/interfaces/modal'
3
3
  export { useModalHandler } from './src/hooks/modal-handler'
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
- {
2
- "name": "dynamic-modal",
3
- "version": "1.0.11",
4
- "description": "The dynamic-modal is a solution of creation differents modals into project using a json configuration file",
5
- "main": "index.js",
6
- "scripts": {
7
- "build": "tsc",
8
- "lint": "eslint .",
9
- "publish": "npm publish --access public",
10
- "test": "echo \"Error: no test specified\" && exit 1"
11
- },
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://gitlab.com/f.salazar/dynamic-modal.git"
15
- },
16
- "keywords": [
17
- "modal",
18
- "react",
19
- "next",
20
- "dynamic",
21
- "json"
22
- ],
23
- "author": "Francisco J. Salazar G",
24
- "license": "ISC",
25
- "bugs": {
26
- "url": "https://gitlab.com/f.salazar/dynamic-modal/issues"
27
- },
28
- "homepage": "https://gitlab.com/f.salazar/dynamic-modal#readme",
29
- "devDependencies": {
30
- "@eslint/js": "^9.13.0",
31
- "@types/react": "^18.3.12",
32
- "@types/react-dom": "^18.3.1",
33
- "@typescript-eslint/eslint-plugin": "^8.11.0",
34
- "@typescript-eslint/parser": "^8.11.0",
35
- "eslint": "^9.13.0",
36
- "eslint-plugin-react": "^7.37.2",
37
- "eslint-plugin-react-hooks": "^5.0.0",
38
- "globals": "^15.11.0",
39
- "typescript": "^5.0.0",
40
- "typescript-eslint": "^8.11.0"
41
- },
42
- "dependencies": {
43
- "@nextui-org/react": "^2.2.9",
44
- "react": "^18.0.0",
45
- "react-dom": " ^18.0.0",
46
- "react-hook-form": "^7.0.0"
47
- }
48
- }
1
+ {
2
+ "name": "dynamic-modal",
3
+ "version": "1.0.13",
4
+ "description": "The dynamic-modal is a solution of creation different modals into project using a json configuration file",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "lint": "eslint .",
9
+ "publish": "npm publish --access public",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://gitlab.com/f.salazar/dynamic-modal.git"
15
+ },
16
+ "keywords": [
17
+ "modal",
18
+ "react",
19
+ "next",
20
+ "dynamic",
21
+ "json"
22
+ ],
23
+ "author": "Francisco J. Salazar G",
24
+ "license": "ISC",
25
+ "bugs": {
26
+ "url": "https://gitlab.com/f.salazar/dynamic-modal/issues"
27
+ },
28
+ "homepage": "https://gitlab.com/f.salazar/dynamic-modal#readme",
29
+ "devDependencies": {
30
+ "@eslint/js": "^9.13.0",
31
+ "@types/react": "^18.3.12",
32
+ "@types/react-dom": "^18.3.1",
33
+ "@typescript-eslint/eslint-plugin": "^8.11.0",
34
+ "@typescript-eslint/parser": "^8.11.0",
35
+ "eslint": "^9.13.0",
36
+ "eslint-plugin-react": "^7.37.2",
37
+ "eslint-plugin-react-hooks": "^5.0.0",
38
+ "globals": "^15.11.0",
39
+ "typescript": "^5.0.0",
40
+ "typescript-eslint": "^8.11.0"
41
+ },
42
+ "dependencies": {
43
+ "@nextui-org/react": "^2.2.9",
44
+ "react": "^18.0.0",
45
+ "react-dom": " ^18.0.0",
46
+ "react-hook-form": "^7.0.0"
47
+ }
48
+ }
@@ -1,72 +1,72 @@
1
- import React, { ChangeEvent, FC, useMemo } from 'react'
2
- import { IFileResult, IInputUpload } from '../../interfaces/input-upload'
3
- import { generateId } from '../../tools/general'
4
-
5
- const InputUpload: FC<IInputUpload> = ({ onChange, readAsArrayBuffer, ...props }: IInputUpload) => {
6
-
7
- const onChangeHandler = (event: ChangeEvent<HTMLInputElement>) => {
8
- if (props.read && event.target.files) {
9
- readFileBlob(event.target.files[0], false)
10
- .then((result) => onChange(result))
11
- .catch((err) => {
12
- console.error('file read error', err)
13
- onChange({name:'', size: 0, data: ''})
14
- })
15
- } else {
16
- onChange(event.target.files)
17
- }
18
- }
19
-
20
- const readFileBlob = (blob: File, image: boolean): Promise<IFileResult> => {
21
- return new Promise((resolve, reject) => {
22
- const fileReader = new FileReader()
23
- if(image) fileReader.readAsDataURL(blob)
24
- else if (readAsArrayBuffer) fileReader.readAsArrayBuffer(blob)
25
- else fileReader.readAsText(blob)
26
-
27
- fileReader.onload = () => {
28
- const fileResult: IFileResult = {
29
- name: blob.name,
30
- size: blob.size,
31
- data: fileReader.result as string
32
- }
33
-
34
- resolve(fileResult)
35
- }
36
- fileReader.onerror = (error) => {
37
- reject(error)
38
- }
39
- })
40
- }
41
-
42
- const elementId = useMemo<string>(
43
- () => {
44
- return props.id ?? generateId()
45
- }, [props.id]
46
- )
47
-
48
- return (
49
- <div className='flex flex-col w-full gap-1 text-center'>
50
- {props.label && <label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" htmlFor={`file-input-${elementId}`}>{props.label}</label>}
51
- <input
52
- className="file:transition-all file:delay-150 block w-full text-sm text-slate-500
53
- file:mr-4 file:py-2 file:px-4 file:rounded-md
54
- file:border-0 file:text-sm file:font-semibold
55
- file:bg-gray-100 file:text-blue-600
56
- hover:file:bg-blue-700 hover:file:text-white cursor-pointer disabled:cursor-not-allowed"
57
- aria-describedby={`file-input-${elementId}-help`}
58
- id={`file-input-${elementId}`}
59
- type="file"
60
- onChange={onChangeHandler}
61
- {...props}
62
- />
63
- <p
64
- className="mt-1 text-sm text-gray-500 dark:text-gray-300 text-start"
65
- id={`file-input-${elementId}-help`}>
66
- {props.helpText?.toUpperCase()}
67
- </p>
68
- </div>
69
- )
70
- }
71
-
72
- export default InputUpload
1
+ import React, { ChangeEvent, FC, useMemo } from 'react'
2
+ import { IFileResult, IInputUpload } from '../../interfaces/input-upload'
3
+ import { generateId } from '../../tools/general'
4
+
5
+ const InputUpload: FC<IInputUpload> = ({ onChange, readAsArrayBuffer, ...props }: IInputUpload) => {
6
+
7
+ const onChangeHandler = (event: ChangeEvent<HTMLInputElement>) => {
8
+ if (props.read && event.target.files) {
9
+ readFileBlob(event.target.files[0], false)
10
+ .then((result) => onChange(result))
11
+ .catch((err) => {
12
+ console.error('file read error', err)
13
+ onChange({name:'', size: 0, data: ''})
14
+ })
15
+ } else {
16
+ onChange(event.target.files)
17
+ }
18
+ }
19
+
20
+ const readFileBlob = (blob: File, image: boolean): Promise<IFileResult> => {
21
+ return new Promise((resolve, reject) => {
22
+ const fileReader = new FileReader()
23
+ if(image) fileReader.readAsDataURL(blob)
24
+ else if (readAsArrayBuffer) fileReader.readAsArrayBuffer(blob)
25
+ else fileReader.readAsText(blob)
26
+
27
+ fileReader.onload = () => {
28
+ const fileResult: IFileResult = {
29
+ name: blob.name,
30
+ size: blob.size,
31
+ data: fileReader.result as string
32
+ }
33
+
34
+ resolve(fileResult)
35
+ }
36
+ fileReader.onerror = (error) => {
37
+ reject(error)
38
+ }
39
+ })
40
+ }
41
+
42
+ const elementId = useMemo<string>(
43
+ () => {
44
+ return props.id ?? generateId()
45
+ }, [props.id]
46
+ )
47
+
48
+ return (
49
+ <div className='flex flex-col w-full gap-1 text-center'>
50
+ {props.label && <label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" htmlFor={`file-input-${elementId}`}>{props.label}</label>}
51
+ <input
52
+ className="file:transition-all file:delay-150 block w-full text-sm text-slate-500
53
+ file:mr-4 file:py-2 file:px-4 file:rounded-md
54
+ file:border-0 file:text-sm file:font-semibold
55
+ file:bg-gray-100 file:text-blue-600
56
+ hover:file:bg-blue-700 hover:file:text-white cursor-pointer disabled:cursor-not-allowed"
57
+ aria-describedby={`file-input-${elementId}-help`}
58
+ id={`file-input-${elementId}`}
59
+ type="file"
60
+ onChange={onChangeHandler}
61
+ {...props}
62
+ />
63
+ <p
64
+ className="mt-1 text-sm text-gray-500 dark:text-gray-300 text-start"
65
+ id={`file-input-${elementId}-help`}>
66
+ {props.helpText?.toUpperCase()}
67
+ </p>
68
+ </div>
69
+ )
70
+ }
71
+
72
+ export default InputUpload
@@ -1,53 +1,54 @@
1
- import React, { FC, useEffect } from 'react'
2
- import { Controller } from 'react-hook-form'
3
- import { useFieldRender } from '../../hooks/field-render'
4
- import { generateId } from '../../tools/general'
5
- import { Autocomplete, AutocompleteItem } from '@nextui-org/react'
6
- import { IMakeAutoCompleteProps } from '../../interfaces/make-autocomplete'
7
-
8
- const MakeAutocomplete: FC<IMakeAutoCompleteProps> = ({ element, ...props }) => {
9
- const { render, enable, checkField, liveData, liveSearching } = useFieldRender({ element, ...props })
10
-
11
- useEffect(() => {
12
- const subscription = props.watch((value, { name, type }) => checkField(value, { name, type }))
13
- return () => subscription.unsubscribe()
14
- }, [checkField, props, props.watch])
15
-
16
- return (
17
- render
18
- ? <Controller
19
- control={props.control}
20
- name={element.name}
21
- rules={{
22
- required: element.validation.required,
23
- pattern: {
24
- value: element.validation.regex as RegExp ?? /(.*)/,
25
- message: element.validation.message ?? ''
26
- }
27
- }}
28
- render={({ field: { onChange, value }, fieldState: { invalid } }) => (
29
- <Autocomplete
30
- size='sm'
31
- {...element}
32
- isDisabled={element.disabled ?? !enable}
33
- id={element.id ?? generateId()}
34
- onSelectionChange={onChange}
35
- label={liveSearching ? 'Loading...' : element.label}
36
- selectedKey={value}
37
- color={invalid ? 'danger' : undefined}
38
- isInvalid={invalid}
39
- errorMessage={invalid ? (element.validation.message ?? '') : undefined}
40
- >
41
- {
42
- (liveData || (element.options ?? [])).map((opt) => (
43
- <AutocompleteItem key={opt.id} value={opt.id}>{opt.name}</AutocompleteItem>
44
- ))
45
- }
46
- </Autocomplete>
47
- )}
48
- />
49
- : <></>
50
- )
51
- }
52
-
53
- export default MakeAutocomplete
1
+ import React, { FC, useEffect } from 'react'
2
+ import { Controller } from 'react-hook-form'
3
+ import { useFieldRender } from '../../hooks/field-render'
4
+ import { generateId } from '../../tools/general'
5
+ import { Autocomplete, AutocompleteItem } from '@nextui-org/react'
6
+ import { IMakeAutoCompleteProps } from '../../interfaces/make-autocomplete'
7
+
8
+ const MakeAutocomplete: FC<IMakeAutoCompleteProps> = ({ element: { validation: { required, ...validation }, ...element }, ...props }) => {
9
+ const { render, enable, checkField, liveData, liveSearching } = useFieldRender({ ...props, element })
10
+
11
+ useEffect(() => {
12
+ const subscription = props.watch((value, { name, type }) => checkField(value, { name, type }))
13
+ return () => subscription.unsubscribe()
14
+ }, [checkField, props, props.watch])
15
+
16
+ return (
17
+ render
18
+ ? <Controller
19
+ control={props.control}
20
+ name={element.name}
21
+ rules={{
22
+ required,
23
+ pattern: {
24
+ value: validation.regex as RegExp ?? /(.*)/,
25
+ message: validation.message ?? ''
26
+ },
27
+ ...validation
28
+ }}
29
+ render={({ field: { onChange, value }, fieldState: { invalid } }) => (
30
+ <Autocomplete
31
+ size='sm'
32
+ {...element}
33
+ id={element.id ?? generateId()}
34
+ onSelectionChange={onChange}
35
+ label={liveSearching ? 'Loading...' : element.label}
36
+ selectedKey={value}
37
+ color={invalid ? 'danger' : undefined}
38
+ isInvalid={invalid}
39
+ errorMessage={invalid ? (validation.message ?? '') : undefined}
40
+ isDisabled={element.disabled ?? !enable}
41
+ >
42
+ {
43
+ (liveData || (element.options ?? [])).map((opt) => (
44
+ <AutocompleteItem key={opt.id} value={opt.id}>{opt.name}</AutocompleteItem>
45
+ ))
46
+ }
47
+ </Autocomplete>
48
+ )}
49
+ />
50
+ : <></>
51
+ )
52
+ }
53
+
54
+ export default MakeAutocomplete
@@ -1,17 +1,17 @@
1
- import React, { FC } from 'react'
2
- import { IMakeButtonProps } from '../../interfaces/make-button'
3
-
4
- const MakeButton: FC<IMakeButtonProps> = ({
5
- element: { text, ...element }
6
- }) => {
7
- return (
8
- <button
9
- className='transition-all delay-100 hover:translate-y-1 bg-blue-500 text-white hover:bg-blue-700 rounded w-11/12 h-[40px] p-2'
10
- {...element}
11
- >
12
- {text}
13
- </button>
14
- )
15
- }
16
-
17
- export default MakeButton
1
+ import React, { FC } from 'react'
2
+ import { IMakeButtonProps } from '../../interfaces/make-button'
3
+
4
+ const MakeButton: FC<IMakeButtonProps> = ({
5
+ element: { text, ...element }
6
+ }) => {
7
+ return (
8
+ <button
9
+ className='transition-all delay-100 hover:translate-y-1 bg-blue-500 text-white hover:bg-blue-700 rounded w-11/12 h-[40px] p-2'
10
+ {...element}
11
+ >
12
+ {text}
13
+ </button>
14
+ )
15
+ }
16
+
17
+ export default MakeButton
@@ -1,46 +1,47 @@
1
- import React, { FC, useEffect } from 'react'
2
- import { Controller } from 'react-hook-form'
3
- import { useFieldRender } from '../../hooks/field-render'
4
- import { IMakeInputProps } from '../../interfaces/make-field'
5
- import { Input } from '@nextui-org/react'
6
- import { generateId } from '../../tools/general'
7
-
8
- const MakeInput: FC<IMakeInputProps> = ({ element, ...props }) => {
9
- const { render, enable, checkField } = useFieldRender({ element, ...props })
10
-
11
- useEffect(() => {
12
- const subscription = props.watch((value, { name, type }) => checkField(value, { name, type }))
13
- return () => subscription.unsubscribe()
14
- }, [checkField, props])
15
-
16
- return (
17
- render
18
- ? <Controller
19
- control={props.control}
20
- name={element.name}
21
- rules={{
22
- required: element.validation.required,
23
- pattern: {
24
- value: element.validation.regex as RegExp ?? /(.*)/,
25
- message: element.validation.message ?? ''
26
- }
27
- }}
28
- render={({ field: { onChange, value }, fieldState: { invalid } }) => (
29
- <Input
30
- size='sm'
31
- {...element}
32
- id={element.id ?? generateId()}
33
- onChange={onChange}
34
- value={value ?? ''}
35
- color={invalid ? 'danger' : undefined}
36
- isInvalid={invalid}
37
- errorMessage={invalid ? (element.validation.message ?? '') : undefined}
38
- disabled={element.disabled ?? !enable}
39
- />
40
- )}
41
- />
42
- : null
43
- )
44
- }
45
-
46
- export default MakeInput
1
+ import React, { FC, useEffect } from 'react'
2
+ import { Controller } from 'react-hook-form'
3
+ import { useFieldRender } from '../../hooks/field-render'
4
+ import { IMakeInputProps } from '../../interfaces/make-field'
5
+ import { Input } from '@nextui-org/react'
6
+ import { generateId } from '../../tools/general'
7
+
8
+ const MakeInput: FC<IMakeInputProps> = ({ element: { validation: { required, ...validation }, ...element }, ...props }) => {
9
+ const { render, enable, checkField } = useFieldRender({ ...props, element })
10
+
11
+ useEffect(() => {
12
+ const subscription = props.watch((value, { name, type }) => checkField(value, { name, type }))
13
+ return () => subscription.unsubscribe()
14
+ }, [checkField, props])
15
+
16
+ return (
17
+ render
18
+ ? <Controller
19
+ control={props.control}
20
+ name={element.name}
21
+ rules={{
22
+ required,
23
+ pattern: {
24
+ value: validation.regex as RegExp ?? /(.*)/,
25
+ message: validation.message ?? ''
26
+ },
27
+ ...validation
28
+ }}
29
+ render={({ field: { onChange, value }, fieldState: { invalid } }) => (
30
+ <Input
31
+ size='sm'
32
+ {...element}
33
+ id={element.id ?? generateId()}
34
+ onChange={onChange}
35
+ value={value ?? ''}
36
+ color={invalid ? 'danger' : undefined}
37
+ isInvalid={invalid}
38
+ errorMessage={invalid ? (validation.message ?? '') : undefined}
39
+ isDisabled={element.disabled ?? !enable}
40
+ />
41
+ )}
42
+ />
43
+ : null
44
+ )
45
+ }
46
+
47
+ export default MakeInput