lib-pixelbuild 0.1.0
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/LICENSE +15 -0
- package/README.md +176 -0
- package/dist/builders/PageBuilder.d.ts +7 -0
- package/dist/builders/PageBuilder.js +40 -0
- package/dist/components/CardComponent.d.ts +4 -0
- package/dist/components/CardComponent.js +13 -0
- package/dist/components/CarouselComponent.d.ts +4 -0
- package/dist/components/CarouselComponent.js +7 -0
- package/dist/components/FormComponent.d.ts +4 -0
- package/dist/components/FormComponent.js +26 -0
- package/dist/components/ListComponent.d.ts +4 -0
- package/dist/components/ListComponent.js +23 -0
- package/dist/components/LoadingComponent.d.ts +1 -0
- package/dist/components/LoadingComponent.js +5 -0
- package/dist/components/MapComponent.d.ts +4 -0
- package/dist/components/MapComponent.js +18 -0
- package/dist/components/SliderComponent.d.ts +5 -0
- package/dist/components/SliderComponent.js +16 -0
- package/dist/components/SocialIconsComponent.d.ts +4 -0
- package/dist/components/SocialIconsComponent.js +19 -0
- package/dist/components/TextComponent.d.ts +4 -0
- package/dist/components/TextComponent.js +13 -0
- package/dist/constants/ButtonActionEnum.d.ts +4 -0
- package/dist/constants/ButtonActionEnum.js +5 -0
- package/dist/constants/ComponentEnum.d.ts +17 -0
- package/dist/constants/ComponentEnum.js +16 -0
- package/dist/constants/ElementEnum.d.ts +18 -0
- package/dist/constants/ElementEnum.js +17 -0
- package/dist/constants/InputValidateEnum.d.ts +8 -0
- package/dist/constants/InputValidateEnum.js +9 -0
- package/dist/elements/AlertElement.d.ts +4 -0
- package/dist/elements/AlertElement.js +19 -0
- package/dist/elements/ButtonElement.d.ts +4 -0
- package/dist/elements/ButtonElement.js +50 -0
- package/dist/elements/ElementColWrapper.d.ts +6 -0
- package/dist/elements/ElementColWrapper.js +5 -0
- package/dist/elements/FileElement.d.ts +4 -0
- package/dist/elements/FileElement.js +6 -0
- package/dist/elements/IconElement.d.ts +4 -0
- package/dist/elements/IconElement.js +13 -0
- package/dist/elements/ImageElement.d.ts +4 -0
- package/dist/elements/ImageElement.js +6 -0
- package/dist/elements/InputElement.d.ts +4 -0
- package/dist/elements/InputElement.js +24 -0
- package/dist/elements/LinkElement.d.ts +4 -0
- package/dist/elements/LinkElement.js +6 -0
- package/dist/elements/TextElement.d.ts +4 -0
- package/dist/elements/TextElement.js +13 -0
- package/dist/factories/ButtonActionFactory.d.ts +5 -0
- package/dist/factories/ButtonActionFactory.js +13 -0
- package/dist/factories/ComponentFactory.d.ts +5 -0
- package/dist/factories/ComponentFactory.js +36 -0
- package/dist/factories/ElementFactory.d.ts +5 -0
- package/dist/factories/ElementFactory.js +42 -0
- package/dist/factories/InputValidateFactory.d.ts +9 -0
- package/dist/factories/InputValidateFactory.js +21 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +15 -0
- package/dist/layouts/Footer.d.ts +4 -0
- package/dist/layouts/Footer.js +11 -0
- package/dist/layouts/Header.d.ts +4 -0
- package/dist/layouts/Header.js +8 -0
- package/dist/layouts/Menu.d.ts +5 -0
- package/dist/layouts/Menu.js +34 -0
- package/dist/layouts/SiteLayout.d.ts +4 -0
- package/dist/layouts/SiteLayout.js +7 -0
- package/dist/renderers/SectionRenderer.d.ts +4 -0
- package/dist/renderers/SectionRenderer.js +39 -0
- package/dist/services/AnalyticsService.d.ts +8 -0
- package/dist/services/AnalyticsService.js +28 -0
- package/dist/services/ApiService.d.ts +5 -0
- package/dist/services/ApiService.js +17 -0
- package/dist/services/CacheService.d.ts +5 -0
- package/dist/services/CacheService.js +16 -0
- package/dist/services/ConstructorService.d.ts +12 -0
- package/dist/services/ConstructorService.js +33 -0
- package/dist/services/EmailService.d.ts +9 -0
- package/dist/services/EmailService.js +44 -0
- package/dist/services/InputValidateService.d.ts +17 -0
- package/dist/services/InputValidateService.js +31 -0
- package/dist/stores/UseFormStore.d.ts +32 -0
- package/dist/stores/UseFormStore.js +51 -0
- package/dist/types/AuthenticateResponseType.d.ts +5 -0
- package/dist/types/AuthenticateResponseType.js +1 -0
- package/dist/types/ButtonPropertiesType.d.ts +11 -0
- package/dist/types/ButtonPropertiesType.js +1 -0
- package/dist/types/ColumnWidthType.d.ts +7 -0
- package/dist/types/ColumnWidthType.js +1 -0
- package/dist/types/ComponentType.d.ts +11 -0
- package/dist/types/ComponentType.js +1 -0
- package/dist/types/ElementType.d.ts +11 -0
- package/dist/types/ElementType.js +1 -0
- package/dist/types/FilePropertiesType.d.ts +4 -0
- package/dist/types/FilePropertiesType.js +1 -0
- package/dist/types/FooterPropertiesType.d.ts +5 -0
- package/dist/types/FooterPropertiesType.js +1 -0
- package/dist/types/FooterType.d.ts +6 -0
- package/dist/types/FooterType.js +1 -0
- package/dist/types/FormFieldsType.d.ts +4 -0
- package/dist/types/FormFieldsType.js +1 -0
- package/dist/types/HeaderPropertiesType.d.ts +5 -0
- package/dist/types/HeaderPropertiesType.js +1 -0
- package/dist/types/HeaderType.d.ts +6 -0
- package/dist/types/HeaderType.js +1 -0
- package/dist/types/ImagePropertiesType.d.ts +4 -0
- package/dist/types/ImagePropertiesType.js +1 -0
- package/dist/types/InputPropertiesType.d.ts +7 -0
- package/dist/types/InputPropertiesType.js +1 -0
- package/dist/types/LinkPropertiesType.d.ts +4 -0
- package/dist/types/LinkPropertiesType.js +1 -0
- package/dist/types/MailBodyType.d.ts +8 -0
- package/dist/types/MailBodyType.js +1 -0
- package/dist/types/PageType.d.ts +17 -0
- package/dist/types/PageType.js +1 -0
- package/dist/types/PlanWebsiteType.d.ts +9 -0
- package/dist/types/PlanWebsiteType.js +1 -0
- package/dist/types/PropertiesType.d.ts +27 -0
- package/dist/types/PropertiesType.js +1 -0
- package/dist/types/RawWebsiteType.d.ts +346 -0
- package/dist/types/RawWebsiteType.js +1 -0
- package/dist/types/SectionColumnType.d.ts +14 -0
- package/dist/types/SectionColumnType.js +1 -0
- package/dist/types/SectionType.d.ts +10 -0
- package/dist/types/SectionType.js +1 -0
- package/dist/types/SocialPropertiesType.d.ts +11 -0
- package/dist/types/SocialPropertiesType.js +1 -0
- package/dist/types/StylesType.d.ts +35 -0
- package/dist/types/StylesType.js +1 -0
- package/dist/types/UserType.d.ts +10 -0
- package/dist/types/UserType.js +1 -0
- package/dist/types/WebsitePropertiesType.d.ts +5 -0
- package/dist/types/WebsitePropertiesType.js +1 -0
- package/dist/types/WebsiteType.d.ts +23 -0
- package/dist/types/WebsiteType.js +1 -0
- package/dist/utils/InputValidators.d.ts +14 -0
- package/dist/utils/InputValidators.js +88 -0
- package/package.json +90 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Lucas da Silva
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# lib-pixelbuild
|
|
2
|
+
|
|
3
|
+
> **Para IA:** leia [docs/AI_CONTEXT.md](docs/AI_CONTEXT.md) antes de alterar esta biblioteca.
|
|
4
|
+
|
|
5
|
+
> **Status:** em construção — refatoração para novo padrão; mudanças grandes esperadas. O endpoint legado `/website/{id}/structure` foi removido da API; um novo contrato será definido.
|
|
6
|
+
|
|
7
|
+
Biblioteca React para construção dinâmica de sites a partir de estruturas e padrões pré-definidos. Ideal para reutilização, manutenção centralizada e rápida evolução de múltiplos projetos frontend.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ✨ Visão Geral
|
|
12
|
+
|
|
13
|
+
- **lib-pixelbuild** permite criar sites completos a partir de um modelo de dados padronizado, compondo páginas, componentes e elementos de forma dinâmica.
|
|
14
|
+
- Foco em **reutilização**, **manutenção centralizada** e **distribuição fácil** de novas funcionalidades para múltiplos projetos.
|
|
15
|
+
- Utiliza React, TypeScript e padrões modernos de desenvolvimento.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🚀 Instalação
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install lib-pixelbuild
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> **Peer dependencies**: Certifique-se de instalar também as dependências peer listadas no `package.json` (React, React Bootstrap, dompurify, zustand, etc).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🏗️ Estrutura do Projeto
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
src/
|
|
33
|
+
components/ # Componentes (Layout, Header, Footer, Form, etc)
|
|
34
|
+
elements/ # Elementos (Text, Image, Input, Button, etc)
|
|
35
|
+
constants/ # Enums e constantes de tipos
|
|
36
|
+
factories/ # Fábricas para instanciar componentes/elementos dinamicamente
|
|
37
|
+
services/ # Serviços utilitários (API, Cache, Email, Analytics, etc)
|
|
38
|
+
stores/ # Gerenciamento de estado
|
|
39
|
+
types/ # Tipos para todo o modelo de dados
|
|
40
|
+
utils/ # Funções utilitárias e validadores
|
|
41
|
+
index.ts # Exporta tudo que é público na lib
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 🧩 Como Funciona
|
|
47
|
+
|
|
48
|
+
- **Estrutura de Dados**: O site é definido por um objeto JSON (ver `RawWebsiteType`), contendo páginas, componentes e elementos.
|
|
49
|
+
- **Factories**: Fábricas constroem dinamicamente componentes e elementos a partir do JSON.
|
|
50
|
+
- **Componentes**: Renderizam partes do site (textos, listas, formulários, carrosséis, etc).
|
|
51
|
+
- **Elementos**: Unidades atômicas (input, botão, imagem, texto, etc).
|
|
52
|
+
- **Serviços**: Abstraem chamadas de API, cache local, envio de e-mail, validação, etc.
|
|
53
|
+
- **Gerenciamento de Estado**: Utiliza Zustand para formulários dinâmicos.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🛠️ Uso Básico
|
|
58
|
+
|
|
59
|
+
1. **Importe o que precisa:**
|
|
60
|
+
```ts
|
|
61
|
+
import { MainLayout, PageRenderer, ConstructorService } from 'lib-pixelbuild'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. **Busque a estrutura do site:**
|
|
65
|
+
```ts
|
|
66
|
+
const constructorService = new ConstructorService()
|
|
67
|
+
const websiteData = await constructorService.fetchWebsiteFromApi(websiteId, apiUrl)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. **Renderize:**
|
|
71
|
+
```tsx
|
|
72
|
+
<MainLayout website={websiteData}>
|
|
73
|
+
<PageRenderer ga4="GA_TRACKING_ID" title="Título" components={websiteData.pages[0].components} />
|
|
74
|
+
</MainLayout>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 🧪 Teste Local
|
|
80
|
+
|
|
81
|
+
Para desenvolver a biblioteca e ver as alterações automaticamente no projeto consumidor, use o fluxo abaixo.
|
|
82
|
+
|
|
83
|
+
### 1) Na biblioteca (`lib-pixelbuild`)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install
|
|
87
|
+
npm run build
|
|
88
|
+
npm link
|
|
89
|
+
npm run link:consumer-peers -- /caminho/para/site
|
|
90
|
+
npm run build:watch
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- `npm link` registra a lib globalmente na sua máquina.
|
|
94
|
+
- `npm run link:consumer-peers` força a lib linkada a usar as **mesmas cópias das peer dependencies** do projeto consumidor (ex.: `react`, `react-dom`, `react-router-dom`), evitando conflitos de contexto e `Invalid hook call`.
|
|
95
|
+
- `npm run build:watch` recompila automaticamente sempre que você alterar algo em `src/`.
|
|
96
|
+
- Antes de rodar o link, garanta que o consumidor já executou `npm install`.
|
|
97
|
+
|
|
98
|
+
### 2) No projeto consumidor
|
|
99
|
+
|
|
100
|
+
Rodar apenas o install, fazer todo o processo na lib e depois rodar o link e npm start
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm install
|
|
104
|
+
npm link lib-pixelbuild
|
|
105
|
+
npm start
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Quando você salvar mudanças na lib, o `dist/` será atualizado e o projeto consumidor refletirá as alterações.
|
|
109
|
+
|
|
110
|
+
> Se o `MainLayout` renderiza mas o `PageRenderer` não entra no `<Outlet />`, também pode ser duplicidade de `react-router-dom` no `npm link`. O comando `npm run link:consumer-peers -- /caminho/para/site` corrige isso ao alinhar peers da lib com o consumidor.
|
|
111
|
+
|
|
112
|
+
> Se o comando retornar `Nenhuma peer dependency encontrada no consumidor para linkar`, normalmente o caminho do projeto consumidor está incorreto ou as dependências ainda não foram instaladas nesse projeto.
|
|
113
|
+
|
|
114
|
+
### 3) (Opcional) Limpeza do link
|
|
115
|
+
|
|
116
|
+
Na lib:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run unlink:global
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
No consumidor:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm unlink lib-pixelbuild
|
|
126
|
+
npm install
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 🏷️ Scripts
|
|
132
|
+
|
|
133
|
+
- `npm run build` — Compila a biblioteca para produção.
|
|
134
|
+
- `npm run build:watch` — Compila em modo watch e aplica o ajuste ESM automaticamente em `dist`.
|
|
135
|
+
- `npm run lint` — Lint nos arquivos.
|
|
136
|
+
- `npm run lint:fix` — Corrige problemas de lint automaticamente.
|
|
137
|
+
- `npm run format` — Formata o código com Prettier.
|
|
138
|
+
- `npm run link:global` — Atalho para `npm link`.
|
|
139
|
+
- `npm run unlink:global` — Remove o link global local da lib.
|
|
140
|
+
- `npm run link:consumer-peers -- /caminho/consumidor` — Linka as `peerDependencies` do consumidor na lib (incluindo `react`, `react-dom` e `react-router-dom`).
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 📦 Publicação
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run build
|
|
148
|
+
|
|
149
|
+
npm publish --access public
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 📚 Tipos Exportados
|
|
155
|
+
|
|
156
|
+
A biblioteca exporta todos os tipos necessários para tipar dados, componentes e elementos dinamicamente.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 📋 Dependências Principais
|
|
161
|
+
|
|
162
|
+
- React
|
|
163
|
+
- React Bootstrap
|
|
164
|
+
- Zustand
|
|
165
|
+
- dompurify
|
|
166
|
+
- react-icons
|
|
167
|
+
- react-input-mask
|
|
168
|
+
- react-helmet-async
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 📝 Exemplo de Estrutura de Dados
|
|
173
|
+
|
|
174
|
+
Veja o tipo `RawWebsiteType` em `src/types/RawWebsiteType.ts` para um exemplo completo de como estruturar o JSON do site.
|
|
175
|
+
|
|
176
|
+
---
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WebsiteType } from '../types/WebsiteType.js';
|
|
2
|
+
import type { PageType } from '../types/PageType.js';
|
|
3
|
+
export declare function PageBuilder({ website, page, editionMode }: {
|
|
4
|
+
readonly website: WebsiteType;
|
|
5
|
+
readonly page: PageType;
|
|
6
|
+
readonly editionMode: boolean;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense } from 'react';
|
|
3
|
+
import { Helmet } from 'react-helmet-async';
|
|
4
|
+
import { Menu } from '../layouts/Menu.js';
|
|
5
|
+
import { SectionRenderer } from '../renderers/SectionRenderer.js';
|
|
6
|
+
export function PageBuilder({ website, page, editionMode }) {
|
|
7
|
+
const wStyles = Object.assign({}, (website.styles || {}));
|
|
8
|
+
const pStyles = Object.assign({}, (page.styles || {}));
|
|
9
|
+
const mergedStyles = Object.assign({}, wStyles);
|
|
10
|
+
for (const key of Object.keys(pStyles)) {
|
|
11
|
+
const val = pStyles[key];
|
|
12
|
+
if (val !== '' && val !== null && val !== undefined) {
|
|
13
|
+
mergedStyles[key] = val;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return (_jsxs(Suspense, { fallback: _jsx("div", { children: website.properties.loadingMessage }), children: [!editionMode && (_jsxs(Helmet, { children: [_jsx("title", { children: page.title }), _jsx("meta", { name: "description", content: page.title }), _jsx("meta", { property: "og:title", content: page.title }), _jsx("meta", { property: "og:description", content: page.title }), _jsx("meta", { property: "og:image", content: page.title })] })), _jsx(Menu, { page: page, websitePages: website.pages }), _jsxs("div", { style: {
|
|
17
|
+
backgroundColor: mergedStyles.backgroundColor,
|
|
18
|
+
color: mergedStyles.color,
|
|
19
|
+
backgroundImage: mergedStyles.backgroundGradientColorStart
|
|
20
|
+
? `linear-gradient(${mergedStyles.backgroundGradientColorStart}, ${mergedStyles.backgroundGradientColorEnd}), url(${mergedStyles.backgroundImage})`
|
|
21
|
+
: mergedStyles.backgroundImage
|
|
22
|
+
? `url(${mergedStyles.backgroundImage})`
|
|
23
|
+
: undefined,
|
|
24
|
+
backgroundSize: mergedStyles.backgroundSize,
|
|
25
|
+
backgroundPosition: mergedStyles.backgroundPosition,
|
|
26
|
+
width: mergedStyles.width,
|
|
27
|
+
height: mergedStyles.height,
|
|
28
|
+
fontSize: mergedStyles.fontSize,
|
|
29
|
+
fontWeight: mergedStyles.fontWeight,
|
|
30
|
+
textAlign: mergedStyles.textAlign,
|
|
31
|
+
paddingTop: mergedStyles.paddingTop,
|
|
32
|
+
paddingBottom: mergedStyles.paddingBottom,
|
|
33
|
+
paddingLeft: mergedStyles.paddingLeft,
|
|
34
|
+
paddingRight: mergedStyles.paddingRight,
|
|
35
|
+
marginTop: mergedStyles.marginTop,
|
|
36
|
+
marginBottom: mergedStyles.marginBottom,
|
|
37
|
+
borderRadius: mergedStyles.borderRadius,
|
|
38
|
+
minHeight: page.sections.length === 0 ? '200px' : undefined,
|
|
39
|
+
}, children: [_jsx(SectionRenderer, { sections: page.sections }), page.sections.length === 0 && editionMode && (_jsx("div", { style: { padding: '40px', textAlign: 'center', color: '#94a3b8' }, children: "Nenhuma se\u00E7\u00E3o configurada. Use o editor de layout para adicionar conte\u00FAdo." }))] })] }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Row, Container } from 'react-bootstrap';
|
|
4
|
+
import { ElementFactory } from '../factories/ElementFactory.js';
|
|
5
|
+
export function CardComponent({ component }) {
|
|
6
|
+
const elementFactory = new ElementFactory();
|
|
7
|
+
return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: component.elements
|
|
8
|
+
.sort((a, b) => a.sort - b.sort)
|
|
9
|
+
.map((element) => {
|
|
10
|
+
const e = elementFactory.build(element);
|
|
11
|
+
return React.cloneElement(e, { key: element.id });
|
|
12
|
+
}) }) }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Row, Col, Carousel } from 'react-bootstrap';
|
|
3
|
+
export function CarouselComponent({ component }) {
|
|
4
|
+
return (_jsx(Row, { children: _jsx(Col, { children: _jsx(Carousel, { indicators: false, className: "slider", children: component.elements
|
|
5
|
+
.sort((a, b) => a.sort - b.sort)
|
|
6
|
+
.map((element, index) => (_jsx(Carousel.Item, { children: _jsx("img", { src: String(element.properties.name || element.properties.src || ''), alt: String(element.properties.title || element.properties.alt || ''), style: { width: '100%', height: 'auto', objectFit: 'cover' } }) }, element.id || index))) }) }) }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
import { Form, Row } from 'react-bootstrap';
|
|
4
|
+
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
5
|
+
import { ElementFactory } from '../factories/ElementFactory.js';
|
|
6
|
+
export function FormComponent({ component }) {
|
|
7
|
+
const elementFactory = new ElementFactory();
|
|
8
|
+
const registerForm = UseFormStore((state) => state.registerForm);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
registerForm(component.id);
|
|
11
|
+
}, [registerForm, component.id]);
|
|
12
|
+
const handleSubmit = async (event) => {
|
|
13
|
+
try {
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console.error('Erro ao enviar o formulário:', error);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
return (_jsx(Form, { noValidate: true, onSubmit: handleSubmit, style: { textAlign: 'left' }, children: _jsx(Row, { style: { padding: '50px' }, children: component.elements
|
|
21
|
+
.sort((a, b) => a.sort - b.sort)
|
|
22
|
+
.map((element) => {
|
|
23
|
+
const e = elementFactory.build(element);
|
|
24
|
+
return React.cloneElement(e, { key: element.id });
|
|
25
|
+
}) }) }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Col } from 'react-bootstrap';
|
|
3
|
+
import { ElementFactory } from '../factories/ElementFactory.js';
|
|
4
|
+
import { ElementTypeEnum } from '../constants/ElementEnum.js';
|
|
5
|
+
export function ListComponent({ component }) {
|
|
6
|
+
const elementFactory = new ElementFactory();
|
|
7
|
+
const elements = component.elements.sort((a, b) => a.sort - b.sort);
|
|
8
|
+
const items = [];
|
|
9
|
+
for (let i = 0; i < elements.length; i++) {
|
|
10
|
+
const current = elements[i];
|
|
11
|
+
if (current.elementType === ElementTypeEnum.Icon) {
|
|
12
|
+
const next = elements[i + 1];
|
|
13
|
+
if ((next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Text || (next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Title) {
|
|
14
|
+
items.push({ icon: current, text: next, id: current.id });
|
|
15
|
+
i++;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
items.push({ icon: current, text: null, id: current.id });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return (_jsx(Col, { style: component.styles, children: _jsx("ul", { style: { listStyle: 'none', padding: 0, margin: 0 }, children: items.map(({ icon, text, id }) => (_jsxs("li", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: '8px' }, children: [_jsx("span", { children: elementFactory.build(icon) }), _jsx("span", { style: { fontSize: '22px' }, children: text ? elementFactory.build(text) : null })] }, id))) }) }));
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function LoadingComponent(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Container, Spinner } from 'react-bootstrap';
|
|
3
|
+
export function LoadingComponent() {
|
|
4
|
+
return (_jsxs(Container, { className: "d-flex flex-column align-items-center justify-content-center", style: { minHeight: '100vh' }, children: [_jsx("output", { "aria-busy": "true", children: _jsx(Spinner, { animation: "border" }) }), _jsx("p", { className: "mt-3", children: "CARREGANDO" })] }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Row, Col } from 'react-bootstrap';
|
|
3
|
+
export function MapComponent({ component }) {
|
|
4
|
+
const { lat, lng, zoom = 15, height = '400px' } = component.properties;
|
|
5
|
+
const src = lat && lng
|
|
6
|
+
? `https://maps.google.com/maps?q=${lat},${lng}&z=${zoom}&output=embed`
|
|
7
|
+
: null;
|
|
8
|
+
return (_jsx(Col, { style: component.styles, children: _jsx(Row, { children: _jsx(Col, { style: { padding: 0 }, children: src ? (_jsx("iframe", { title: "Localiza\u00E7\u00E3o", src: src, width: "100%", height: height, style: { border: 0, borderRadius: '4px' }, allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade" })) : (_jsx("div", { style: {
|
|
9
|
+
width: '100%',
|
|
10
|
+
height,
|
|
11
|
+
backgroundColor: '#e0e0e0',
|
|
12
|
+
display: 'flex',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
justifyContent: 'center',
|
|
15
|
+
borderRadius: '4px',
|
|
16
|
+
color: '#666',
|
|
17
|
+
}, children: "Mapa n\u00E3o configurado" })) }) }) }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Row, Col } from 'react-bootstrap';
|
|
3
|
+
import { useKeenSlider } from 'keen-slider/react.js';
|
|
4
|
+
import { ElementFactory } from '../factories/ElementFactory.js';
|
|
5
|
+
import 'keen-slider/keen-slider.min.css';
|
|
6
|
+
export function SliderComponent({ component }) {
|
|
7
|
+
const elementFactory = new ElementFactory();
|
|
8
|
+
const [ref] = useKeenSlider({
|
|
9
|
+
loop: true,
|
|
10
|
+
mode: 'snap',
|
|
11
|
+
slides: { perView: 1, spacing: 10 },
|
|
12
|
+
});
|
|
13
|
+
return (_jsx(Col, { style: component.styles, children: _jsx(Row, { id: "element-row", children: _jsx(Col, { children: _jsx("div", { ref: ref, className: "keen-slider", children: component.elements
|
|
14
|
+
.sort((a, b) => a.sort - b.sort)
|
|
15
|
+
.map((element) => (_jsx("div", { className: "keen-slider__slide", children: elementFactory.build(element) }, element.id))) }) }) }) }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Row, Col } from 'react-bootstrap';
|
|
3
|
+
import { FaFacebookF, FaInstagram, FaLink } from 'react-icons/fa';
|
|
4
|
+
export function SocialIconsComponent({ social }) {
|
|
5
|
+
var _a, _b, _c;
|
|
6
|
+
const all = [];
|
|
7
|
+
if ((_a = social.facebook) === null || _a === void 0 ? void 0 : _a.path) {
|
|
8
|
+
all.push({ id: 'facebook', url: social.facebook.path, icon: FaFacebookF, description: 'Logo do Facebook' });
|
|
9
|
+
}
|
|
10
|
+
if ((_b = social.instagram) === null || _b === void 0 ? void 0 : _b.path) {
|
|
11
|
+
all.push({ id: 'instagram', url: social.instagram.path, icon: FaInstagram, description: 'Logo do Instagram' });
|
|
12
|
+
}
|
|
13
|
+
if ((_c = social.linktree) === null || _c === void 0 ? void 0 : _c.path) {
|
|
14
|
+
all.push({ id: 'linktree', url: social.linktree.path, icon: FaLink, description: 'Logo do Linktree' });
|
|
15
|
+
}
|
|
16
|
+
if (all.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
return (_jsx(Row, { children: all.map((element) => (_jsx(Col, { className: "text-center social-icons", style: { color: '#FFCC00' }, children: _jsx("a", { href: element.url, target: "_blank", rel: "noreferrer", "aria-label": element.description, children: _jsx(element.icon, {}) }) }, element.id))) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Row, Container } from 'react-bootstrap';
|
|
4
|
+
import { ElementFactory } from '../factories/ElementFactory.js';
|
|
5
|
+
export function TextComponent({ component }) {
|
|
6
|
+
const elementFactory = new ElementFactory();
|
|
7
|
+
return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: component.elements
|
|
8
|
+
.sort((a, b) => a.sort - b.sort)
|
|
9
|
+
.map((element) => {
|
|
10
|
+
const e = elementFactory.build(element);
|
|
11
|
+
return React.cloneElement(e, { key: element.id });
|
|
12
|
+
}) }) }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ComponentTypeEnum: {
|
|
2
|
+
readonly TextWithImage: "text-with-image";
|
|
3
|
+
readonly Form: "form";
|
|
4
|
+
readonly Slider: "slider";
|
|
5
|
+
readonly Card: "card";
|
|
6
|
+
readonly Text: "text";
|
|
7
|
+
readonly Image: "image";
|
|
8
|
+
readonly Video: "video";
|
|
9
|
+
readonly Gallery: "gallery";
|
|
10
|
+
readonly Testimonials: "testimonials";
|
|
11
|
+
readonly Faq: "faq";
|
|
12
|
+
readonly HeroBanner: "hero-banner";
|
|
13
|
+
readonly SocialIcons: "social-icons";
|
|
14
|
+
readonly Map: "map";
|
|
15
|
+
readonly List: "list";
|
|
16
|
+
};
|
|
17
|
+
export type ComponentTypeSlug = (typeof ComponentTypeEnum)[keyof typeof ComponentTypeEnum];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const ComponentTypeEnum = {
|
|
2
|
+
TextWithImage: 'text-with-image',
|
|
3
|
+
Form: 'form',
|
|
4
|
+
Slider: 'slider',
|
|
5
|
+
Card: 'card',
|
|
6
|
+
Text: 'text',
|
|
7
|
+
Image: 'image',
|
|
8
|
+
Video: 'video',
|
|
9
|
+
Gallery: 'gallery',
|
|
10
|
+
Testimonials: 'testimonials',
|
|
11
|
+
Faq: 'faq',
|
|
12
|
+
HeroBanner: 'hero-banner',
|
|
13
|
+
SocialIcons: 'social-icons',
|
|
14
|
+
Map: 'map',
|
|
15
|
+
List: 'list',
|
|
16
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const ElementTypeEnum: {
|
|
2
|
+
readonly Input: "input";
|
|
3
|
+
readonly Textarea: "textarea";
|
|
4
|
+
readonly Select: "select";
|
|
5
|
+
readonly Button: "button";
|
|
6
|
+
readonly Image: "image";
|
|
7
|
+
readonly Icon: "icon";
|
|
8
|
+
readonly Title: "title";
|
|
9
|
+
readonly Text: "text";
|
|
10
|
+
readonly Link: "link";
|
|
11
|
+
readonly File: "file";
|
|
12
|
+
readonly Alert: "alert";
|
|
13
|
+
readonly Video: "video";
|
|
14
|
+
readonly Checkbox: "checkbox";
|
|
15
|
+
readonly Radio: "radio";
|
|
16
|
+
readonly Divider: "divider";
|
|
17
|
+
};
|
|
18
|
+
export type ElementTypeSlug = (typeof ElementTypeEnum)[keyof typeof ElementTypeEnum];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const ElementTypeEnum = {
|
|
2
|
+
Input: 'input',
|
|
3
|
+
Textarea: 'textarea',
|
|
4
|
+
Select: 'select',
|
|
5
|
+
Button: 'button',
|
|
6
|
+
Image: 'image',
|
|
7
|
+
Icon: 'icon',
|
|
8
|
+
Title: 'title',
|
|
9
|
+
Text: 'text',
|
|
10
|
+
Link: 'link',
|
|
11
|
+
File: 'file',
|
|
12
|
+
Alert: 'alert',
|
|
13
|
+
Video: 'video',
|
|
14
|
+
Checkbox: 'checkbox',
|
|
15
|
+
Radio: 'radio',
|
|
16
|
+
Divider: 'divider',
|
|
17
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { Alert } from 'react-bootstrap';
|
|
4
|
+
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
5
|
+
import { ElementColWrapper } from './ElementColWrapper.js';
|
|
6
|
+
export function AlertElement({ element }) {
|
|
7
|
+
const properties = element.properties;
|
|
8
|
+
const hidden = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.hidden; });
|
|
9
|
+
const registerElement = UseFormStore((state) => state.registerElement);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
registerElement(element.id, element.properties.componentId, {
|
|
12
|
+
type: 'alert',
|
|
13
|
+
hidden: Boolean(properties.startHidden)
|
|
14
|
+
});
|
|
15
|
+
}, [element.id, properties.startHidden, registerElement]);
|
|
16
|
+
if (hidden)
|
|
17
|
+
return null;
|
|
18
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsxs(Alert, { hidden: hidden, variant: String(properties.type || 'info'), style: element.styles, children: [_jsx(Alert.Heading, { children: String(properties.title || '') }), _jsx("p", { className: "mb-0", children: String(properties.message || '') })] }) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { Button, Spinner } from 'react-bootstrap';
|
|
4
|
+
import { ElementColWrapper } from './ElementColWrapper.js';
|
|
5
|
+
import { UseFormStore } from '../stores/UseFormStore.js';
|
|
6
|
+
import { ButtonActionFactory } from '../factories/ButtonActionFactory.js';
|
|
7
|
+
export function ButtonElement({ element }) {
|
|
8
|
+
var _a;
|
|
9
|
+
const properties = element.properties;
|
|
10
|
+
const hidden = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.hidden; });
|
|
11
|
+
const loading = UseFormStore((state) => { var _a; return (_a = state.elements[element.id]) === null || _a === void 0 ? void 0 : _a.loading; });
|
|
12
|
+
const showElement = UseFormStore((state) => state.showElement);
|
|
13
|
+
const hideElement = UseFormStore((state) => state.hideElement);
|
|
14
|
+
const registerElement = UseFormStore((state) => state.registerElement);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
registerElement(element.id, properties.componentId, {
|
|
17
|
+
type: 'button',
|
|
18
|
+
hidden: Boolean(properties.startHidden)
|
|
19
|
+
});
|
|
20
|
+
}, [element.id, properties.startHidden, registerElement]);
|
|
21
|
+
async function handleClick(event) {
|
|
22
|
+
var _a;
|
|
23
|
+
if (!properties.path) {
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
UseFormStore.getState().validateAllFields(properties.componentId);
|
|
26
|
+
const formData = UseFormStore.getState().getElementsByForm(properties.componentId);
|
|
27
|
+
const hasErrors = formData.some((e) => e.error);
|
|
28
|
+
if (hasErrors)
|
|
29
|
+
return false;
|
|
30
|
+
UseFormStore.getState().setElementState(element.id, { loading: true });
|
|
31
|
+
if (properties.actionId) {
|
|
32
|
+
const buttonActionFactory = new ButtonActionFactory();
|
|
33
|
+
await buttonActionFactory.build(properties.actionId, formData);
|
|
34
|
+
}
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
if (properties.hideOnClick)
|
|
37
|
+
hideElement(element.id);
|
|
38
|
+
if (properties.successMessageId)
|
|
39
|
+
showElement(properties.successMessageId);
|
|
40
|
+
if (properties.successActionId)
|
|
41
|
+
showElement(properties.successActionId);
|
|
42
|
+
UseFormStore.getState().setElementState(element.id, { loading: false });
|
|
43
|
+
}, (_a = properties.loadingTime) !== null && _a !== void 0 ? _a : 0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (hidden)
|
|
47
|
+
return null;
|
|
48
|
+
return (_jsx(ElementColWrapper, { element: element, children: _jsx(Button, { as: properties.path ? 'a' : 'button', type: properties.type === 'button' || properties.type === 'submit' || properties.type === 'reset'
|
|
49
|
+
? properties.type : undefined, variant: String(properties.type || 'primary'), href: String(properties.path || ''), target: properties.path ? '_blank' : undefined, rel: properties.path ? 'noopener noreferrer' : undefined, disabled: loading, onClick: handleClick, style: element.styles, children: loading ? (_jsxs(_Fragment, { children: [_jsx("output", { "aria-busy": "true", children: _jsx(Spinner, { as: "span", animation: "border", size: "sm", "aria-hidden": "true" }) }), ' ' + (String((_a = properties.message) !== null && _a !== void 0 ? _a : ''))] })) : (String(properties.title || '')) }) }));
|
|
50
|
+
}
|