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.
- package/.idea/dynamic-modal.iml +12 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README-ES.md +119 -119
- package/README.md +119 -119
- package/dist/components/input-upload/input-upload.js +18 -8
- package/dist/components/make-autocomplete/make-autocomplete.js +24 -17
- package/dist/components/make-input/make-input.js +24 -17
- package/dist/components/make-multi-select/make-multi-select.js +24 -17
- package/dist/components/make-select/make-select.js +24 -17
- package/dist/components/make-textarea/make-textarea.js +23 -16
- package/dist/components/make-toggle/make-toggle.js +36 -14
- package/dist/components/make-upload/make-upload.js +20 -8
- package/dist/components/portal/portal.js +17 -7
- package/dist/interfaces/field.d.ts +7 -4
- package/dist/interfaces/input-upload.d.ts +1 -15
- package/dist/modal.js +17 -7
- package/eslint.config.mjs +13 -13
- package/examples/enable-if.ts +129 -129
- package/examples/live-data.ts +63 -63
- package/examples/render-if.ts +130 -130
- package/examples/simple.ts +76 -76
- package/index.ts +2 -2
- package/package.json +48 -48
- package/src/components/input-upload/input-upload.tsx +72 -72
- package/src/components/make-autocomplete/make-autocomplete.tsx +54 -53
- package/src/components/make-button/make-button.tsx +17 -17
- package/src/components/make-input/make-input.tsx +47 -46
- package/src/components/make-multi-select/make-multi-select.tsx +56 -55
- package/src/components/make-select/make-select.tsx +54 -53
- package/src/components/make-text/make-text.tsx +16 -16
- package/src/components/make-textarea/make-textarea.tsx +48 -47
- package/src/components/make-title/make-title.tsx +12 -12
- package/src/components/make-toggle/make-toggle.tsx +44 -44
- package/src/components/make-upload/make-upload.tsx +34 -41
- package/src/components/portal/portal.tsx +36 -36
- package/src/hooks/field-render.ts +108 -108
- package/src/hooks/modal-handler.ts +37 -37
- package/src/interfaces/field.ts +35 -31
- package/src/interfaces/input-upload.ts +21 -37
- package/src/interfaces/make-autocomplete.ts +13 -13
- package/src/interfaces/make-button.ts +20 -20
- package/src/interfaces/make-field-group.ts +13 -13
- package/src/interfaces/make-field.ts +14 -14
- package/src/interfaces/make-multi-select.ts +14 -14
- package/src/interfaces/make-select.ts +12 -12
- package/src/interfaces/make-text.ts +12 -12
- package/src/interfaces/make-textarea.ts +11 -11
- package/src/interfaces/make-title.ts +3 -3
- package/src/interfaces/make-toggle.ts +9 -9
- package/src/interfaces/make-upload.ts +14 -14
- package/src/interfaces/modal.ts +51 -51
- package/src/interfaces/option.ts +3 -3
- package/src/interfaces/portal.ts +8 -8
- package/src/modal.tsx +174 -174
- package/src/tools/general.ts +6 -6
- package/tsconfig.json +13 -13
package/examples/simple.ts
CHANGED
|
@@ -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.
|
|
4
|
-
"description": "The dynamic-modal is a solution of creation
|
|
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({
|
|
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:
|
|
25
|
-
message:
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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 ? (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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({
|
|
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:
|
|
25
|
-
message:
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|