dynamic-modal
Version:
The dynamic-modal is a solution of creation different modals into project using a json configuration file
218 lines (187 loc) • 6.09 kB
Markdown
`dynamic-modal` es una librería construida en typescript para crear modales reutilizables en aplicaciones React y Next.js, utilizando JSON para configurar su estructura sin necesidad de escribir HTML. Esto facilita su construcción y personalización, permitiendo abrir y cerrar modales mediante un custom hook.
Para que `dynamic-modal` funcione correctamente, debes instalar las siguientes dependencias:
- React
Además, es compatible con **Next.js**.
Puedes instalar la librería a través de npm:
```bash
npm install dynamic-modal
```
Define los componentes que seran usados por el modal, crea el archivo y configura todos los componentes del modal. Aqui un ejemplo utilizando HeroUI (anteriormente NextUI):
```jsx
'use client'
import { Autocomplete, AutocompleteItem, Button, Input, Select, SelectItem, Switch, Textarea } from "@heroui/react"
import { IComponentState } from "dynamic-modal/src/interfaces/component-state"
export const ModalComponents: IComponentState = {
ModalButtonCancel: (props) => {
return (
<Button
{...props}
color={props.color as "default" | "primary" | "secondary" | "success" | "warning" | "danger" | undefined}
variant={'bordered'}
>
{props.text}
</Button>
)
},
ModalButtonAction: (props) => {
return (
<Button
{...props}
color={props.color as "default" | "primary" | "secondary" | "success" | "warning" | "danger" | undefined}
variant={'solid'}
>
{props.text}
</Button>)
},
Button: ({ text, ...props }) => {
return (
<Button
{...props}
color={props.color as "default" | "primary" | "secondary" | "success" | "warning" | "danger" | undefined}
variant={props.variant as "flat" | "bordered" | "solid" | "light" | "faded" | "shadow" | "ghost" | undefined}
>
{text}
</Button>)
},
Input: ({ invalid, error, disabled, onChange, ...props }) => {
return (
<Input
{...props}
onValueChange={onChange}
errorMessage={error?.message}
isInvalid={invalid}
isDisabled={disabled}
/>
)
},
Select: ({ options, invalid, error, isMulti, isSearch, disabled, onChange, value, ...props }) => {
return (
!isSearch ?
<Select
{...props}
selectedKeys={isMulti ? value : [value]}
onSelectionChange={onChange}
selectionMode={isMulti ? 'multiple' : 'single'}
errorMessage={error?.message}
isInvalid={invalid}
isDisabled={disabled}
>
{options.map((option) => (
<SelectItem key={option.id}>{option.name}</SelectItem>
))}
</Select> :
<Autocomplete
{...props}
selectedKey={value}
onSelectionChange={onChange}
errorMessage={error?.message}
isInvalid={invalid}
isDisabled={disabled}
>
{options.map((item) => (
<AutocompleteItem key={item.id}>{item.name}</AutocompleteItem>
))}
</Autocomplete>
)
},
Textarea: ({ invalid, error, disabled, ...props }) => {
return (
<Textarea
{...props}
errorMessage={error?.message}
isInvalid={invalid}
isDisabled={disabled}
/>
)
},
Toggle: ({ value, onChange, label, invalid, ...props }) => {
return(
<Switch {...props} isSelected={value} onValueChange={onChange}>
{label}
</Switch>
)
}
}
```
En el provider principal de tu aplicación Next.js, importa tus componentes del modal (definidos anteriormente) y envuelve tu aplicación con el componente `ComponentState` para que `dynamic-modal` funcione adecuadamente. Aquí un ejemplo:
```jsx
import { ComponentState } from 'dynamic-modal'
import { ModalComponents } from "@data/modal-component/modal-component"
function Provider({ children }: Readonly<{ children: ReactNode }>) {
return (
<ComponentState components={ModalComponents}>
<Component {...pageProps} />
</ComponentState>
)
}
export default Provider
```
En el layout principal crea el `portal` para el modal (este componente utiliza react portal)
```jsx
//imports...
export default function RootLayout ({
children
}: Readonly<{
children: ReactNode
}>) {
return (
<html lang="en">
<body className={inter.className}>
<Provider>
{children}
</Provider>
<div id='modal-portal'/>
</body>
</html>
)
}
```
Edita el archivo llamado `_document.tsx` y crea el `portal` para el modal (este componente utiliza react portal)
```jsx
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document () {
return (
<Html>
<Head />
<body>
<Main />
<div id='modal-portal'/>
<NextScript />
</body>
</Html>
)
}
```
Para controlar la apertura y cierre del modal, obtén el custom hook `useModalHandler` y llama a `openModal` cuando necesites mostrar el modal.
```jsx
import { useModalHandler, DynamicModal } from 'dynamic-modal'
import { Button } from '@nextui-org/react'
//Crea el modal, importa y usa
import testModal from '@modal-config/test'
function ExampleComponent() {
const { openModal, modalProps } = useModalHandler()
return (
<>
<Button
onClick={() => {
openModal(testModal.default({}, (data) => {
console.log('modal data', data)
}))
}}
>
Open modal
</Button>
<DynamicModal {...modalProps} />
</>
)
}
export default ExampleComponent
```
La carpeta `examples` en el repositorio contiene distintos modos de configuración para ayudarte a personalizar tu modal.