lib-pixelbuild 0.1.4 → 0.2.1

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 (63) hide show
  1. package/README.md +102 -127
  2. package/dist/builders/PageBuilder.d.ts +3 -2
  3. package/dist/builders/PageBuilder.js +42 -33
  4. package/dist/components/CardComponent.d.ts +3 -3
  5. package/dist/components/CardComponent.js +71 -41
  6. package/dist/components/FormComponent.d.ts +3 -3
  7. package/dist/components/FormComponent.js +8 -14
  8. package/dist/components/ListComponent.d.ts +3 -2
  9. package/dist/components/ListComponent.js +20 -15
  10. package/dist/components/LoadingComponent.js +1 -1
  11. package/dist/components/MapComponent.js +19 -5
  12. package/dist/components/SliderComponent.js +59 -15
  13. package/dist/components/SocialIconsComponent.js +1 -1
  14. package/dist/components/TextComponent.d.ts +3 -3
  15. package/dist/components/TextComponent.js +6 -7
  16. package/dist/elements/AlertElement.js +4 -3
  17. package/dist/elements/ButtonElement.js +20 -17
  18. package/dist/elements/IconElement.d.ts +1 -2
  19. package/dist/elements/IconElement.js +8 -9
  20. package/dist/elements/IconMap.d.ts +2 -0
  21. package/dist/elements/IconMap.js +30 -0
  22. package/dist/elements/InputElement.js +19 -18
  23. package/dist/factories/ButtonActionFactory.d.ts +6 -1
  24. package/dist/factories/ButtonActionFactory.js +14 -4
  25. package/dist/index.d.ts +2 -6
  26. package/dist/index.js +1 -4
  27. package/dist/layouts/Header.d.ts +2 -1
  28. package/dist/layouts/Header.js +31 -5
  29. package/dist/layouts/SiteLayout.d.ts +2 -1
  30. package/dist/layouts/SiteLayout.js +2 -2
  31. package/dist/renderers/SectionRenderer.d.ts +3 -3
  32. package/dist/renderers/SectionRenderer.js +48 -30
  33. package/dist/services/EmailService.d.ts +10 -2
  34. package/dist/services/EmailService.js +27 -25
  35. package/dist/types/RawWebsiteType.d.ts +8 -184
  36. package/dist/utils/InputValidators.js +11 -11
  37. package/dist/utils/propertyUtils.d.ts +3 -0
  38. package/dist/utils/propertyUtils.js +28 -0
  39. package/package.json +33 -20
  40. package/dist/elements/FileElement.d.ts +0 -4
  41. package/dist/elements/FileElement.js +0 -6
  42. package/dist/services/ApiService.d.ts +0 -5
  43. package/dist/services/ApiService.js +0 -17
  44. package/dist/services/CacheService.d.ts +0 -5
  45. package/dist/services/CacheService.js +0 -16
  46. package/dist/services/ConstructorService.d.ts +0 -12
  47. package/dist/services/ConstructorService.js +0 -33
  48. package/dist/types/AuthenticateResponseType.d.ts +0 -5
  49. package/dist/types/AuthenticateResponseType.js +0 -1
  50. package/dist/types/ButtonPropertiesType.d.ts +0 -11
  51. package/dist/types/ButtonPropertiesType.js +0 -1
  52. package/dist/types/FilePropertiesType.d.ts +0 -4
  53. package/dist/types/FilePropertiesType.js +0 -1
  54. package/dist/types/ImagePropertiesType.d.ts +0 -4
  55. package/dist/types/ImagePropertiesType.js +0 -1
  56. package/dist/types/InputPropertiesType.d.ts +0 -7
  57. package/dist/types/InputPropertiesType.js +0 -1
  58. package/dist/types/LinkPropertiesType.d.ts +0 -4
  59. package/dist/types/LinkPropertiesType.js +0 -1
  60. package/dist/types/PlanWebsiteType.d.ts +0 -9
  61. package/dist/types/PlanWebsiteType.js +0 -1
  62. package/dist/types/UserType.d.ts +0 -10
  63. package/dist/types/UserType.js +0 -1
package/README.md CHANGED
@@ -1,176 +1,151 @@
1
1
  # lib-pixelbuild
2
2
 
3
- > **Para IA:** leia [docs/AI_CONTEXT.md](docs/AI_CONTEXT.md) antes de alterar esta biblioteca.
3
+ React render engine for schema-driven PixelBuild websites.
4
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.
5
+ ## Features
6
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.
7
+ - Schema-driven rendering pages, components, elements from JSON
8
+ - Dynamic component/element factories with lazy loading
9
+ - SEO via `react-helmet-async`
10
+ - Analytics via `react-ga4`
11
+ - Dynamic forms with validation (CPF, phone, email, etc.)
12
+ - Accessible image sliders (`keen-slider`)
13
+ - Email service with configurable credentials
14
+ - Zustand-powered dynamic form state management
8
15
 
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
16
+ ## Installation
20
17
 
21
18
  ```bash
22
19
  npm install lib-pixelbuild
23
20
  ```
24
21
 
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
22
+ **Peer dependencies** seu projeto precisa ter estas também:
30
23
 
31
24
  ```
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
25
+ react react-dom react-bootstrap bootstrap zustand react-router-dom
26
+ react-icons react-ga4 react-helmet-async react-imask dompurify keen-slider
42
27
  ```
43
28
 
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
29
+ ## Usage
80
30
 
81
- Para desenvolver a biblioteca e ver as alterações automaticamente no projeto consumidor, use o fluxo abaixo.
31
+ ```tsx
32
+ import { SiteLayout, PageBuilder } from 'lib-pixelbuild'
33
+ import type { WebsiteType, PageType } from 'lib-pixelbuild'
82
34
 
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
35
+ function App({ website }: { website: WebsiteType }) {
36
+ const page = website.pages[0]
37
+ return (
38
+ <SiteLayout website={website} imageBaseUrl="/images">
39
+ <PageBuilder website={website} page={page} editionMode={false} />
40
+ </SiteLayout>
41
+ )
42
+ }
91
43
  ```
92
44
 
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`.
45
+ ## Development hot-reload
97
46
 
98
- ### 2) No projeto consumidor
47
+ Os consumidores (`site-avalloneadvogados`, `app-pixelbuild`) têm `vite.config.js` configurado com alias para o **código-fonte TypeScript** da lib em modo dev:
99
48
 
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
49
+ ```js
50
+ 'lib-pixelbuild': path.resolve(__dirname, '../lib-pixelbuild/src/index.ts')
106
51
  ```
107
52
 
108
- Quando você salvar mudanças na lib, o `dist/` será atualizado e o projeto consumidor refletirá as alterações.
53
+ Isso significa que:
109
54
 
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.
55
+ 1. **A lib NÃO precisa ser buildada** durante o desenvolvimento
56
+ 2. Alterações no `src/` da lib refletem **instantaneamente** nos consumidores (hot-reload do Vite)
57
+ 3. As peer dependencies (`react`, `react-bootstrap`, etc.) são resolvidas do `node_modules` do consumidor via aliases
111
58
 
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.
59
+ **Pré-requisito:** o consumidor precisa ter todas as peer dependencies instaladas.
113
60
 
114
- ### 3) (Opcional) Limpeza do link
115
-
116
- Na lib:
61
+ ### Fluxo de desenvolvimento
117
62
 
118
63
  ```bash
119
- npm run unlink:global
120
- ```
64
+ # Terminal 1: lib (não precisa rodar nada, só editar os arquivos)
65
+ cd lib-pixelbuild
121
66
 
122
- No consumidor:
123
-
124
- ```bash
125
- npm unlink lib-pixelbuild
126
- npm install
67
+ # Terminal 2: consumidor
68
+ cd site-avalloneadvogados
69
+ npm run dev # hot-reload reflete alterações na lib automaticamente
127
70
  ```
128
71
 
129
- ---
72
+ ### Build para produção
130
73
 
131
- ## 🏷️ Scripts
74
+ ```bash
75
+ cd lib-pixelbuild
76
+ npm run build # compila dist/
132
77
 
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`).
78
+ cd site-avalloneadvogados
79
+ npm run build # usa o dist/ da lib (produção)
80
+ ```
141
81
 
142
- ---
82
+ Em produção, os `vite.config.js` não usam o alias de source — resolvem pelo `package.json` da lib (`file:` → `dist/index.js`).
143
83
 
144
- ## 📦 Publicação
84
+ ## Publicação
145
85
 
146
86
  ```bash
147
- npm run build
87
+ # 1. Build + testes
88
+ npm run build && npm test && npm run lint
148
89
 
90
+ # 2. Publicar
149
91
  npm publish --access public
150
92
  ```
151
93
 
152
- ---
94
+ O comando `prepublishOnly` já roda build, testes e lint automaticamente antes de publicar.
95
+
96
+ ## Scripts
97
+
98
+ | Script | Description |
99
+ |--------|-------------|
100
+ | `npm run build` | Compile to `dist/` + ESM fix |
101
+ | `npm run build:watch` | Watch mode |
102
+ | `npm run test` | Run vitest |
103
+ | `npm run typecheck` | `tsc --noEmit` |
104
+ | `npm run lint` | ESLint |
105
+ | `npm run format` | Prettier |
106
+ | `npm run prepare` | Husky + lint-staged (auto-run on install) |
107
+ | `npm run lint:fix` | ESLint auto-fix |
108
+ | `npm run link:global` | `npm link` para consumo local |
109
+ | `npm run unlink:global` | Remove o link global |
153
110
 
154
- ## 📚 Tipos Exportados
111
+ ## Project Structure
155
112
 
156
- A biblioteca exporta todos os tipos necessários para tipar dados, componentes e elementos dinamicamente.
113
+ ```
114
+ src/
115
+ builders/ PageBuilder — assembles pages from schema
116
+ components/ Card, Form, List, Map, Slider, Text, etc.
117
+ constants/ Type enums
118
+ elements/ Atomic elements — Button, Icon, Image, Input, Link, Text
119
+ factories/ ComponentFactory, ElementFactory, ButtonActionFactory
120
+ layouts/ SiteLayout, Header, Footer, Menu
121
+ services/ EmailService (configurable)
122
+ stores/ Zustand store for forms
123
+ types/ RawWebsiteType and related types
124
+ utils/ propertyUtils (type-safe accessors), InputValidators
125
+ ```
157
126
 
158
- ---
127
+ ## Public API
159
128
 
160
- ## 📋 Dependências Principais
129
+ ```ts
130
+ // Components
131
+ Header Footer SiteLayout
132
+ PageBuilder SectionRenderer LoadingComponent
161
133
 
162
- - React
163
- - React Bootstrap
164
- - Zustand
165
- - dompurify
166
- - react-icons
167
- - react-input-mask
168
- - react-helmet-async
134
+ // Factories
135
+ ComponentFactory ElementFactory
136
+ buttonActionFactory → configureEmail(config)
169
137
 
170
- ---
138
+ // Constants
139
+ ComponentTypeEnum ElementTypeEnum
140
+ analyticsService
171
141
 
172
- ## 📝 Exemplo de Estrutura de Dados
142
+ // Types
143
+ RawWebsiteType WebsiteType PageType SectionType
144
+ SectionColumnType ColumnWidthType ComponentType
145
+ ElementType PropertiesType StylesType
146
+ EmailServiceConfig
147
+ ```
173
148
 
174
- Veja o tipo `RawWebsiteType` em `src/types/RawWebsiteType.ts` para um exemplo completo de como estruturar o JSON do site.
149
+ ## Note
175
150
 
176
- ---
151
+ This library is under active development. Breaking changes expected until v1.0.
@@ -1,7 +1,8 @@
1
1
  import type { WebsiteType } from '../types/WebsiteType.js';
2
2
  import type { PageType } from '../types/PageType.js';
3
- export declare function PageBuilder({ website, page, editionMode }: {
3
+ declare const PageBuilder: import("react").NamedExoticComponent<{
4
4
  readonly website: WebsiteType;
5
5
  readonly page: PageType;
6
6
  readonly editionMode: boolean;
7
- }): import("react").JSX.Element;
7
+ }>;
8
+ export { PageBuilder };
@@ -1,40 +1,49 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Suspense } from 'react';
2
+ import { Suspense, memo, useMemo } from 'react';
3
3
  import { Helmet } from 'react-helmet-async';
4
- import { Menu } from '../layouts/Menu.js';
5
4
  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];
5
+ function mergeStyles(websiteStyles, pageStyles) {
6
+ const merged = Object.assign({}, websiteStyles);
7
+ for (const key of Object.keys(pageStyles)) {
8
+ const val = pageStyles[key];
12
9
  if (val !== '' && val !== null && val !== undefined) {
13
- mergedStyles[key] = val;
10
+ ;
11
+ merged[key] = val;
14
12
  }
15
13
  }
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, editionMode: editionMode }), 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." }))] })] }));
14
+ return merged;
40
15
  }
16
+ function toCssValue(val) {
17
+ if (typeof val === 'string' && val.length > 0)
18
+ return val;
19
+ return undefined;
20
+ }
21
+ const PageBuilder = memo(function PageBuilder({ website, page, editionMode }) {
22
+ const mergedStyles = useMemo(() => mergeStyles(website.styles, page.styles), [website.styles, page.styles]);
23
+ const pageStyle = useMemo(() => ({
24
+ backgroundColor: toCssValue(mergedStyles.backgroundColor),
25
+ color: toCssValue(mergedStyles.color),
26
+ backgroundImage: mergedStyles.backgroundGradientColorStart
27
+ ? `linear-gradient(${mergedStyles.backgroundGradientColorStart}, ${mergedStyles.backgroundGradientColorEnd}), url(${mergedStyles.backgroundImage})`
28
+ : mergedStyles.backgroundImage
29
+ ? `url(${mergedStyles.backgroundImage})`
30
+ : undefined,
31
+ backgroundSize: toCssValue(mergedStyles.backgroundSize),
32
+ backgroundPosition: toCssValue(mergedStyles.backgroundPosition),
33
+ width: toCssValue(mergedStyles.width),
34
+ height: toCssValue(mergedStyles.height),
35
+ fontSize: toCssValue(mergedStyles.fontSize),
36
+ fontWeight: toCssValue(mergedStyles.fontWeight),
37
+ textAlign: mergedStyles.textAlign,
38
+ paddingTop: toCssValue(mergedStyles.paddingTop),
39
+ paddingBottom: toCssValue(mergedStyles.paddingBottom),
40
+ paddingLeft: toCssValue(mergedStyles.paddingLeft),
41
+ paddingRight: toCssValue(mergedStyles.paddingRight),
42
+ marginTop: toCssValue(mergedStyles.marginTop),
43
+ marginBottom: toCssValue(mergedStyles.marginBottom),
44
+ borderRadius: toCssValue(mergedStyles.borderRadius),
45
+ minHeight: page.sections.length === 0 ? '200px' : undefined
46
+ }), [mergedStyles, page.sections.length]);
47
+ 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 })] })), _jsxs("div", { style: pageStyle, children: [_jsx(SectionRenderer, { sections: page.sections, editionMode: editionMode }), page.sections.length === 0 && editionMode && (_jsx("div", { style: { padding: '40px', textAlign: 'center', color: '#94a3b8' }, children: "No sections configured. Use the layout editor to add content." }))] })] }));
48
+ });
49
+ export { PageBuilder };
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
1
  import type { ComponentType } from '../types/ComponentType.js';
3
- export declare function CardComponent({ component }: {
2
+ declare const CardComponent: import("react").NamedExoticComponent<{
4
3
  readonly component: ComponentType;
5
- }): React.JSX.Element;
4
+ }>;
5
+ export { CardComponent };
@@ -1,47 +1,77 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
2
+ import { memo, useMemo } from 'react';
3
3
  import { Row, Container } from 'react-bootstrap';
4
4
  import { ElementFactory } from '../factories/ElementFactory.js';
5
5
  import { orderBySort } from '../utils/orderBySort.js';
6
6
  const elementFactory = new ElementFactory();
7
- export function CardComponent({ component }) {
8
- const props = component.properties || {};
9
- const cardOrder = [
10
- props.cardElement1,
11
- props.cardElement2,
12
- props.cardElement3,
13
- props.cardElement4,
14
- ].filter(Boolean);
15
- const orderedElements = cardOrder.length > 0
16
- ? cardOrder
17
- .map((type) => component.elements.find((el) => el.elementType === String(type)))
18
- .filter(Boolean)
19
- : orderBySort(component.elements);
20
- const applyCardStyles = (element) => {
21
- const overrides = {};
22
- if (element.elementType === 'icon') {
23
- if (props.cardIconColor)
24
- overrides.color = props.cardIconColor;
25
- if (props.cardIconSize)
26
- overrides.fontSize = props.cardIconSize;
27
- }
28
- else if (element.elementType === 'title') {
29
- if (props.cardTitleColor)
30
- overrides.color = props.cardTitleColor;
31
- if (props.cardTitleSize)
32
- overrides.fontSize = props.cardTitleSize;
33
- }
34
- else if (element.elementType === 'text') {
35
- if (props.cardTextColor)
36
- overrides.color = props.cardTextColor;
37
- if (props.cardTextSize)
38
- overrides.fontSize = props.cardTextSize;
39
- }
40
- return Object.assign(Object.assign({}, element), { styles: Object.assign(Object.assign({}, element.styles), overrides) });
41
- };
42
- return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: orderedElements.map((element) => {
43
- const enhanced = applyCardStyles(element);
44
- const e = elementFactory.build(enhanced);
45
- return React.cloneElement(e, { key: element.id });
46
- }) }) }));
7
+ function applyCardStyles(element, props) {
8
+ const overrides = {};
9
+ if (element.elementType === 'icon') {
10
+ if (props.cardIconColor)
11
+ overrides.color = props.cardIconColor;
12
+ if (props.cardIconSize)
13
+ overrides.fontSize = props.cardIconSize;
14
+ }
15
+ else if (element.elementType === 'title') {
16
+ if (props.cardTitleColor)
17
+ overrides.color = props.cardTitleColor;
18
+ if (props.cardTitleSize)
19
+ overrides.fontSize = props.cardTitleSize;
20
+ }
21
+ else if (element.elementType === 'text') {
22
+ if (props.cardTextColor)
23
+ overrides.color = props.cardTextColor;
24
+ if (props.cardTextSize)
25
+ overrides.fontSize = props.cardTextSize;
26
+ }
27
+ return Object.assign(Object.assign({}, element), { styles: Object.assign(Object.assign({}, element.styles), overrides) });
47
28
  }
29
+ const CardComponent = memo(function CardComponent({ component }) {
30
+ const { properties } = component;
31
+ const cardProps = useMemo(() => ({
32
+ cardElement1: properties === null || properties === void 0 ? void 0 : properties.cardElement1,
33
+ cardElement2: properties === null || properties === void 0 ? void 0 : properties.cardElement2,
34
+ cardElement3: properties === null || properties === void 0 ? void 0 : properties.cardElement3,
35
+ cardElement4: properties === null || properties === void 0 ? void 0 : properties.cardElement4,
36
+ cardIconColor: properties === null || properties === void 0 ? void 0 : properties.cardIconColor,
37
+ cardIconSize: properties === null || properties === void 0 ? void 0 : properties.cardIconSize,
38
+ cardTitleColor: properties === null || properties === void 0 ? void 0 : properties.cardTitleColor,
39
+ cardTitleSize: properties === null || properties === void 0 ? void 0 : properties.cardTitleSize,
40
+ cardTextColor: properties === null || properties === void 0 ? void 0 : properties.cardTextColor,
41
+ cardTextSize: properties === null || properties === void 0 ? void 0 : properties.cardTextSize
42
+ }), [
43
+ properties === null || properties === void 0 ? void 0 : properties.cardElement1,
44
+ properties === null || properties === void 0 ? void 0 : properties.cardElement2,
45
+ properties === null || properties === void 0 ? void 0 : properties.cardElement3,
46
+ properties === null || properties === void 0 ? void 0 : properties.cardElement4,
47
+ properties === null || properties === void 0 ? void 0 : properties.cardIconColor,
48
+ properties === null || properties === void 0 ? void 0 : properties.cardIconSize,
49
+ properties === null || properties === void 0 ? void 0 : properties.cardTitleColor,
50
+ properties === null || properties === void 0 ? void 0 : properties.cardTitleSize,
51
+ properties === null || properties === void 0 ? void 0 : properties.cardTextColor,
52
+ properties === null || properties === void 0 ? void 0 : properties.cardTextSize
53
+ ]);
54
+ const orderedElements = useMemo(() => {
55
+ const cardOrder = [
56
+ cardProps.cardElement1,
57
+ cardProps.cardElement2,
58
+ cardProps.cardElement3,
59
+ cardProps.cardElement4
60
+ ].filter((v) => typeof v === 'string' && v.length > 0);
61
+ if (cardOrder.length > 0) {
62
+ return cardOrder
63
+ .map((type) => component.elements.find((el) => el.elementType === type))
64
+ .filter((el) => el !== undefined);
65
+ }
66
+ return orderBySort(component.elements);
67
+ }, [
68
+ cardProps.cardElement1,
69
+ cardProps.cardElement2,
70
+ cardProps.cardElement3,
71
+ cardProps.cardElement4,
72
+ component.elements
73
+ ]);
74
+ const elements = useMemo(() => orderedElements.map((el) => applyCardStyles(el, cardProps)), [orderedElements, cardProps]);
75
+ return (_jsx(Container, { style: component.styles, children: _jsx(Row, { id: "element-row", children: elements.map((element) => elementFactory.build(element)) }) }));
76
+ });
77
+ export { CardComponent };
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
1
  import type { ComponentType } from '../types/ComponentType.js';
3
- export declare function FormComponent({ component }: {
2
+ declare const FormComponent: import("react").NamedExoticComponent<{
4
3
  readonly component: ComponentType;
5
- }): React.JSX.Element;
4
+ }>;
5
+ export { FormComponent };
@@ -1,25 +1,19 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useEffect } from 'react';
2
+ import { memo, useEffect, useMemo } from 'react';
3
3
  import { Form, Row } from 'react-bootstrap';
4
4
  import { UseFormStore } from '../stores/UseFormStore.js';
5
5
  import { ElementFactory } from '../factories/ElementFactory.js';
6
6
  import { orderBySort } from '../utils/orderBySort.js';
7
7
  const elementFactory = new ElementFactory();
8
- export function FormComponent({ component }) {
8
+ const FormComponent = memo(function FormComponent({ component }) {
9
9
  const registerForm = UseFormStore((state) => state.registerForm);
10
10
  useEffect(() => {
11
11
  registerForm(component.id);
12
12
  }, [registerForm, component.id]);
13
- const handleSubmit = async (event) => {
14
- try {
15
- event.preventDefault();
16
- }
17
- catch (error) {
18
- console.error('Erro ao enviar o formulário:', error);
19
- }
13
+ const elements = useMemo(() => orderBySort(component.elements), [component.elements]);
14
+ const handleSubmit = (event) => {
15
+ event.preventDefault();
20
16
  };
21
- return (_jsx(Form, { onSubmit: handleSubmit, children: _jsx(Row, { children: orderBySort(component.elements).map((element) => {
22
- const e = elementFactory.build(element, component.id);
23
- return React.cloneElement(e, { key: element.id });
24
- }) }) }));
25
- }
17
+ return (_jsx(Form, { onSubmit: handleSubmit, children: _jsx(Row, { children: elements.map((element) => elementFactory.build(element, component.id)) }) }));
18
+ });
19
+ export { FormComponent };
@@ -1,4 +1,5 @@
1
1
  import type { ComponentType } from '../types/ComponentType.js';
2
- export declare function ListComponent({ component }: {
2
+ declare const ListComponent: import("react").NamedExoticComponent<{
3
3
  readonly component: ComponentType;
4
- }): import("react").JSX.Element;
4
+ }>;
5
+ export { ListComponent };
@@ -1,24 +1,29 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { memo, useMemo } from 'react';
2
3
  import { Col } from 'react-bootstrap';
3
4
  import { ElementFactory } from '../factories/ElementFactory.js';
4
5
  import { ElementTypeEnum } from '../constants/ElementEnum.js';
5
6
  import { orderBySort } from '../utils/orderBySort.js';
6
7
  const elementFactory = new ElementFactory();
7
- export function ListComponent({ component }) {
8
- const elements = orderBySort(component.elements);
9
- const items = [];
10
- for (let i = 0; i < elements.length; i++) {
11
- const current = elements[i];
12
- if (current.elementType === ElementTypeEnum.Icon) {
13
- const next = elements[i + 1];
14
- if ((next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Text || (next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Title) {
15
- items.push({ icon: current, text: next, id: current.id });
16
- i++;
17
- }
18
- else {
19
- items.push({ icon: current, text: null, id: current.id });
8
+ const ListComponent = memo(function ListComponent({ component }) {
9
+ const elements = useMemo(() => orderBySort(component.elements), [component.elements]);
10
+ const items = useMemo(() => {
11
+ const result = [];
12
+ for (let i = 0; i < elements.length; i++) {
13
+ const current = elements[i];
14
+ if (current.elementType === ElementTypeEnum.Icon) {
15
+ const next = elements[i + 1];
16
+ if ((next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Text || (next === null || next === void 0 ? void 0 : next.elementType) === ElementTypeEnum.Title) {
17
+ result.push({ icon: current, text: next, id: current.id });
18
+ i++;
19
+ }
20
+ else {
21
+ result.push({ icon: current, text: null, id: current.id });
22
+ }
20
23
  }
21
24
  }
22
- }
25
+ return result;
26
+ }, [elements]);
23
27
  return (_jsx(Col, { style: component.styles, children: _jsx("ul", { style: { listStyle: 'none' }, 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))) }) }));
24
- }
28
+ });
29
+ export { ListComponent };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Container, Spinner } from 'react-bootstrap';
3
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" })] }));
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: "LOADING" })] }));
5
5
  }