@1urso/generic-editor 0.1.0 → 0.1.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 (2) hide show
  1. package/README.md +195 -147
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,216 +1,264 @@
1
1
  # Generic Editor
2
2
 
3
- Uma biblioteca React poderosa e agnóstica de framework para criação de layouts dinâmicos, geração de templates e edição visual. Projetada para ser integrada em qualquer aplicação React (Web, Electron, Tauri, Next.js, etc.).
3
+ Uma biblioteca React poderosa, agnóstica de framework e **100% personalizável** para criação de layouts dinâmicos, geração de templates e edição visual. Projetada para ser o motor de design dentro da sua aplicação (Web, Electron, Tauri, Next.js, etc.).
4
4
 
5
- ## Características
5
+ ---
6
6
 
7
- - **Editor Visual Drag & Drop**: Posicionamento livre, redimensionamento e rotação de elementos.
8
- - **Data Binding**: Suporte a variáveis dinâmicas (ex: `{{produto.nome}}`) para geração de templates.
9
- - **Framework Agnostic**: Funciona em qualquer ambiente React.
10
- - **JSON Based**: Entrada e saída puramente em JSON, facilitando persistência e integração com backends.
11
- - **Socket Ready**: Projetado para suportar atualizações em tempo real via WebSockets.
12
- - **Preview em Tempo Real**: Visualização instantânea de como o layout ficará renderizado.
7
+ ## 📚 Índice
13
8
 
14
- ## Instalação
9
+ 1. [Instalação e Configuração](#instalação-e-configuração)
10
+ 2. [Guia do Usuário (Interface Visual)](#guia-do-usuário-interface-visual)
11
+ - [Manipulação Básica](#manipulação-básica)
12
+ - [Menu de Contexto e Estilização](#menu-de-contexto-e-estilização)
13
+ - [Trabalhando com Textos e Fontes](#trabalhando-com-textos-e-fontes)
14
+ - [Trabalhando com Imagens](#trabalhando-com-imagens)
15
+ 3. [Guia do Desenvolvedor (Integração)](#guia-do-desenvolvedor-integração)
16
+ - [Inicialização e Props](#inicialização-e-props)
17
+ - [Data Binding e Variáveis](#data-binding-e-variáveis)
18
+ - [Modos: Item Único vs. Lista](#modos-item-único-vs-lista)
19
+ - [Estrutura do JSON](#estrutura-do-json)
20
+ - [Gerando HTML (Backend/Print)](#gerando-html-backendprint)
21
+ 4. [API Reference](#api-reference)
22
+
23
+ ---
24
+
25
+ ## Instalação e Configuração
26
+
27
+ ### 1. Instale o pacote
15
28
 
16
29
  ```bash
17
- npm install generic-editor
30
+ npm install @1urso/generic-editor
18
31
  # ou
19
- yarn add generic-editor
32
+ yarn add @1urso/generic-editor
20
33
  ```
21
34
 
22
- ### Peer Dependencies
35
+ ### 2. Instale as dependências (Peer Dependencies)
23
36
 
24
- Certifique-se de ter as seguintes dependências instaladas em seu projeto, pois o editor depende delas para UI e funcionalidades:
37
+ O editor utiliza bibliotecas modernas para garantir performance e acessibilidade. Você precisa instalá-las no seu projeto:
25
38
 
26
39
  ```bash
27
40
  npm install @radix-ui/themes @radix-ui/react-icons react-resizable-panels re-resizable framer-motion @dnd-kit/core
28
41
  ```
29
42
 
30
- E não esqueça de importar os estilos do Radix UI no topo da sua aplicação:
43
+ ### 3. Importe os Estilos
44
+
45
+ No arquivo de entrada da sua aplicação (ex: `main.tsx`, `App.tsx` ou `layout.tsx` no Next.js), importe o CSS do Radix UI:
31
46
 
32
47
  ```tsx
33
- import '@radix-ui/themes/styles.css';
48
+ import "@radix-ui/themes/styles.css";
34
49
  ```
35
50
 
36
- ## Como Usar
51
+ ---
52
+
53
+ ## Guia do Usuário (Interface Visual)
54
+
55
+ Esta seção descreve as funcionalidades disponíveis para o **usuário final** que utilizará o editor na sua plataforma.
56
+
57
+ ### Manipulação Básica
58
+
59
+ O editor oferece uma experiência similar a ferramentas de design como Canva ou Figma:
60
+
61
+ - **Adicionar Elementos**: Utilize a barra lateral (ou botões que você implementar) para arrastar ou clicar e adicionar Textos, Imagens ou Caixas.
62
+ - **Mover**: Clique e arraste qualquer elemento para reposicioná-lo.
63
+ - **Redimensionar**: Clique no elemento para selecioná-lo. Puxe as alças (quadrados azuis) nas bordas ou cantos para alterar o tamanho.
64
+ - **Rotacionar**: Ao selecionar um elemento, uma alça circular aparecerá acima dele. Clique e arraste para girar livremente.
65
+ - **Deletar**: Selecione um elemento e pressione a tecla `Delete` ou use o menu de contexto.
66
+
67
+ ### Menu de Contexto e Estilização
68
+
69
+ **Clique com o botão direito** em qualquer elemento para abrir o menu de opções avançadas.
70
+
71
+ #### Opções Gerais (Todos os Elementos)
72
+
73
+ - **Duplicar**: Cria uma cópia exata do elemento próximo ao original.
74
+ - **Remover**: Exclui o elemento.
75
+ - **Camadas**:
76
+ - _Trazer para frente_: Coloca o elemento sobre todos os outros.
77
+ - _Enviar para trás_: Coloca o elemento atrás de todos.
78
+ - **Cor de Fundo**: Altera a cor de fundo do elemento (inclui transparente).
79
+ - **Bordas**:
80
+ - _Arredondamento_: De 0px (quadrado) até 50% (círculo/oval).
81
+ - _Espessura_: Adiciona borda sólida de 1px a 4px.
82
+
83
+ ### Configurações e Dados de Teste
84
+
85
+ No topo da barra lateral esquerda, o botão **Configurações** (ícone de engrenagem) permite simular como o layout ficará com dados reais.
37
86
 
38
- ### Exemplo Básico
87
+ - **Aba Configuração da Lista**:
88
+ - _Propriedade para Ordenar_: Define qual campo será usado para ordenar a lista (ex: `preco`, `nome`).
89
+ - _Ordem_: Crescente ou Decrescente.
90
+ - **Aba Dados Mockados**:
91
+ - _Dados para Lista_: Um array JSON `[...]` para testar o modo lista.
92
+ - _Dados Únicos_: Um objeto JSON `{...}` para testar o modo único.
93
+ > Edite esses JSONs para ver o layout reagir em tempo real às suas variáveis.
94
+
95
+ ### Trabalhando com Textos e Fontes
96
+
97
+ Ao clicar com o botão direito em um elemento de **Texto**:
98
+
99
+ - **Editar Texto**: Abre uma janela para digitar o conteúdo. É aqui que você insere variáveis (ex: Nome do Cliente) clicando nos botões disponíveis.
100
+ - **Fonte**: Selecione entre diversas fontes seguras para web (Arial, Helvetica, etc) e Google Fonts populares (Roboto, Open Sans, Montserrat).
101
+ - _Importar Google Font_: Permite digitar o nome de qualquer fonte do Google Fonts (ex: "Pacifico") e o editor a carregará automaticamente.
102
+ - **Tamanho**: Ajuste de 12px a 64px.
103
+ - **Cor do Texto**: Paleta de cores pré-definida.
104
+ - **Peso**: Normal ou Negrito.
105
+ - **Alinhamento**: Esquerda, Centro ou Direita.
106
+
107
+ ### Trabalhando com Imagens
108
+
109
+ Ao clicar com o botão direito em um elemento de **Imagem**:
110
+
111
+ - **Alterar Imagem**:
112
+ - _Upload_: Carregue uma imagem do seu computador.
113
+ - _URL_: Cole um link direto para uma imagem da web.
114
+ - **Ajuste (Object Fit)**:
115
+ - _Ajustar (Contain)_: A imagem inteira é mostrada dentro da caixa, mantendo a proporção (pode sobrar espaço em branco).
116
+ - _Esticar (Fill)_: A imagem preenche toda a caixa, podendo ser cortada ou distorcida dependendo da proporção.
117
+ - **Vincular Dados**: Conecta a imagem a uma variável dinâmica (ex: Foto do Produto).
118
+
119
+ ---
120
+
121
+ ## Guia do Desenvolvedor (Integração)
122
+
123
+ ### Inicialização e Props
124
+
125
+ Para iniciar o editor, você deve fornecer a configuração de `layout` que dita quais dados (variáveis) estarão disponíveis para o usuário.
39
126
 
40
127
  ```tsx
41
- import React, { useState } from 'react';
42
- import { EditorContent } from 'generic-editor';
43
-
44
- const MyPage = () => {
45
- // Configuração das variáveis disponíveis para o usuário arrastar/usar
46
- const layoutConfig = {
47
- props: [
48
- { name: 'Nome do Produto', dataName: 'productName' },
49
- { name: 'Preço', dataName: 'price' },
50
- { name: 'Imagem URL', dataName: 'imageUrl' }
51
- ]
52
- };
53
-
54
- const handleSave = (jsonState: string) => {
55
- console.log("Layout salvo:", jsonState);
56
- // Envie para sua API, salve em arquivo, etc.
57
- };
128
+ import { EditorContent } from "@1urso/generic-editor";
129
+
130
+ const config = {
131
+ isList: false, // Modo único (ex: Crachá) ou Lista (ex: Catálogo)
132
+ name: "Crachá de Funcionário",
133
+ props: [
134
+ // Define as variáveis que aparecerão no botão "Inserir Variável"
135
+ { name: "Nome Completo", dataName: "nome" },
136
+ { name: "Cargo", dataName: "cargo" },
137
+ { name: "Foto de Perfil", dataName: "fotoUrl" },
138
+ ],
139
+ };
58
140
 
141
+ function App() {
59
142
  return (
60
- <div style={{ height: '100vh' }}>
61
- <EditorContent
62
- layout={layoutConfig}
63
- onSave={handleSave}
64
- />
143
+ <div style={{ height: "100vh", width: "100%" }}>
144
+ <EditorContent layout={config} onSave={(json) => saveToBackend(json)} />
65
145
  </div>
66
146
  );
67
- };
147
+ }
68
148
  ```
69
149
 
70
- ## API Reference
150
+ ### Data Binding e Variáveis
71
151
 
72
- ### `<EditorContent />`
152
+ O editor utiliza um sistema de interpolação baseado em chaves duplas `{{chave}}`.
73
153
 
74
- Componente principal do editor.
154
+ 1. **Inserção**: O usuário não precisa digitar `{{...}}` manualmente. Na janela de edição de texto, ele verá botões (badges) com os nomes amigáveis (ex: "Nome Completo"). Ao clicar, o código `{{nome}}` é inserido.
155
+ 2. **Renderização**:
156
+ - Se `data = { nome: "Maria" }`, o texto "Olá {{nome}}" vira "Olá Maria".
157
+ - Se a variável não existir nos dados, o editor mantém o texto original `{{nome}}` ou exibe vazio, dependendo da configuração.
75
158
 
76
- | Prop | Tipo | Obrigatório | Descrição |
77
- |------|------|-------------|-----------|
78
- | `layout` | `ILayout` | Sim | Configuração das variáveis disponíveis para data-binding. |
79
- | `initialState` | `any` (JSON string ou Objeto) | Não | Estado inicial do editor. Útil para carregar layouts salvos ou atualizações via socket. |
80
- | `onSave` | `(json: string) => void` | Não | Callback disparado quando o usuário clica em "Salvar". Retorna o estado completo em JSON. |
159
+ ### Modos: Item Único vs. Lista
81
160
 
82
- ### Interfaces
161
+ A propriedade `isList` muda drasticamente como o editor e o gerador de HTML se comportam.
83
162
 
84
- #### `ILayout`
163
+ #### `isList: false` (Modo Único)
85
164
 
86
- Define as propriedades disponíveis para o usuário utilizar no layout (Data Binding).
165
+ - **Uso**: Certificados, Crachás, Banners, Capas.
166
+ - **Dados**: Espera um **Objeto Único** `{ nome: 'João', cargo: 'Dev' }`.
167
+ - **Canvas**: Mostra uma única página/arte.
87
168
 
88
- ```typescript
89
- interface ILayout {
90
- props: IProp[];
91
- }
169
+ #### `isList: true` (Modo Lista)
92
170
 
93
- interface IProp {
94
- name: string; // Nome visível para o usuário (ex: "Nome do Cliente")
95
- dataName: string; // Chave da variável no JSON de dados (ex: "customerName") -> gera {{customerName}}
96
- }
97
- ```
171
+ - **Uso**: Listas de Preços, Catálogos, Etiquetas de Gôndola, Relatórios.
172
+ - **Dados**: Espera um **Array de Objetos** `[{ nome: 'A' }, { nome: 'B' }]`.
173
+ - **Canvas**:
174
+ - O usuário desenha o "Item Modelo" (Template).
175
+ - O editor repete esse modelo verticalmente para cada item do array de dados mockados.
176
+ - Permite visualizar como a lista se comporta com múltiplos itens.
98
177
 
99
- ## Estrutura de Dados (JSON)
178
+ ### Estrutura do JSON
100
179
 
101
- O editor exporta e importa um JSON com a seguinte estrutura:
180
+ O output do `onSave` é um JSON pronto para ser armazenado.
102
181
 
103
182
  ```json
104
183
  {
184
+ "isList": false,
105
185
  "elements": [
106
186
  {
107
- "id": "uuid-1234",
108
- "type": "text", // ou 'image', 'box'
109
- "content": "Olá {{name}}",
187
+ "id": "uuid-v4",
188
+ "type": "text", // 'text' | 'image' | 'box'
189
+ "content": "Nome: {{nome}}",
110
190
  "x": 50,
111
191
  "y": 100,
112
192
  "width": 200,
113
- "height": 50,
193
+ "height": 40,
114
194
  "rotation": 0,
115
- "style": { "color": "#000000" }
195
+ "style": {
196
+ "color": "#000000",
197
+ "fontSize": "16px",
198
+ "fontFamily": "Roboto",
199
+ "textAlign": "center"
200
+ },
201
+ "dataBinding": "nome" // Opcional, usado para vínculo direto
116
202
  }
117
203
  ],
118
- "listSettings": { ... },
119
- "mockData": [ ... ],
120
- "isList": false
204
+ "listSettings": {
205
+ "sortProp": "nome",
206
+ "sortOrder": "asc"
207
+ }
121
208
  }
122
209
  ```
123
210
 
124
- ## Guias de Integração
125
-
126
- ### 1. Integração com WebSockets (Real-time)
211
+ ### Gerando HTML (Backend/Print)
127
212
 
128
- O editor reage a mudanças na prop `initialState`. Isso permite que você conecte o editor a um WebSocket e atualize o layout em tempo real quando outro usuário fizer alterações (colaboração básica) ou carregar dados remotamente.
213
+ Para gerar o resultado final (para imprimir, salvar PDF ou enviar por email), use a função `generateHTML`. Ela roda em qualquer ambiente JS (Node, Browser, etc).
129
214
 
130
- ```tsx
131
- import React, { useEffect, useState } from 'react';
132
- import { EditorContent } from 'generic-editor';
133
- import { io } from 'socket.io-client';
134
-
135
- const socket = io('http://localhost:3000');
215
+ ```typescript
216
+ import { generateHTML } from "@1urso/generic-editor";
136
217
 
137
- const SocketEditor = () => {
138
- const [remoteState, setRemoteState] = useState(null);
218
+ // 1. Carregue o layout e os dados
219
+ const layout = JSON.parse(db.getLayout());
220
+ const dados = db.getFuncionarios(); // Array ou Objeto
139
221
 
140
- useEffect(() => {
141
- // Escuta atualizações do servidor
142
- socket.on('layout-update', (data) => {
143
- setRemoteState(data);
144
- });
222
+ // 2. Gere o HTML
223
+ const htmlString = generateHTML(layout.elements, dados, {
224
+ isList: layout.isList, // Importante passar o modo correto
225
+ listSettings: layout.listSettings,
226
+ });
145
227
 
146
- return () => socket.off('layout-update');
147
- }, []);
228
+ // 3. Injete onde precisar
229
+ document.getElementById("preview").innerHTML = htmlString;
230
+ ```
148
231
 
149
- const handleSave = (jsonState) => {
150
- // Envia alterações para o servidor
151
- socket.emit('save-layout', jsonState);
152
- };
232
+ ---
153
233
 
154
- return (
155
- <EditorContent
156
- layout={{ props: [] }}
157
- initialState={remoteState} // O editor atualizará quando remoteState mudar
158
- onSave={handleSave}
159
- />
160
- );
161
- };
162
- ```
234
+ ## API Reference
163
235
 
164
- > **Nota**: O editor faz um "merge" inteligente ao receber `initialState`, mas para colaboração em tempo real (estilo Google Docs), recomenda-se gerenciar conflitos no backend ou usar bibliotecas como Yjs, passando apenas o estado final consolidado para o `initialState`.
236
+ ### Componente `<EditorContent />`
165
237
 
166
- ### 2. Integração com Electron / Tauri (File System)
238
+ | Propriedade | Tipo | Obrigatório | Padrão | Descrição |
239
+ | -------------- | ------------------------ | ----------- | ------ | --------------------------------------------- |
240
+ | `layout` | `ILayout` | **Sim** | - | Configuração inicial das variáveis e modo. |
241
+ | `initialState` | `any` | Não | `null` | Estado JSON para carregar um layout salvo. |
242
+ | `onSave` | `(json: string) => void` | Não | - | Callback acionado ao clicar no botão Salvar. |
243
+ | `mockData` | `any[]` | Não | `[]` | Dados para preview imediato durante a edição. |
167
244
 
168
- Para aplicativos desktop, você pode usar o `onSave` para escrever diretamente no disco.
245
+ ### Tipos TypeScript
169
246
 
170
- ```tsx
171
- // Exemplo Tauri / Electron
172
- import { writeFile, readTextFile } from '@tauri-apps/api/fs'; // ou 'fs' do Node no Electron
173
-
174
- const DesktopEditor = () => {
175
- const [fileContent, setFileContent] = useState(null);
176
-
177
- useEffect(() => {
178
- // Carregar arquivo ao abrir
179
- readTextFile('path/to/layout.json').then(content => {
180
- setFileContent(content);
181
- });
182
- }, []);
183
-
184
- const handleSave = async (jsonState) => {
185
- await writeFile({
186
- path: 'path/to/layout.json',
187
- contents: jsonState
188
- });
189
- alert('Salvo com sucesso no disco!');
190
- };
247
+ #### `ILayout`
191
248
 
192
- return (
193
- <EditorContent
194
- layout={{ props: [] }}
195
- initialState={fileContent}
196
- onSave={handleSave}
197
- />
198
- );
199
- };
249
+ ```typescript
250
+ interface ILayout {
251
+ name: string; // Nome do layout (metadado)
252
+ isList?: boolean; // Define o comportamento padrão (Lista ou Único)
253
+ props: IProp[]; // Lista de variáveis disponíveis
254
+ }
200
255
  ```
201
256
 
202
- ### 3. Integração com Backend (REST API)
257
+ #### `IProp`
203
258
 
204
- ```tsx
205
- const CloudEditor = () => {
206
- const handleSave = async (jsonState) => {
207
- await fetch('/api/layouts/123', {
208
- method: 'PUT',
209
- headers: { 'Content-Type': 'application/json' },
210
- body: jsonState // Envia o JSON completo
211
- });
212
- };
213
-
214
- return <EditorContent layout={...} onSave={handleSave} />;
215
- };
259
+ ```typescript
260
+ interface IProp {
261
+ name: string; // Rótulo visível (ex: "Preço do Produto")
262
+ dataName: string; // Chave do objeto (ex: "product_price")
263
+ }
216
264
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1urso/generic-editor",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },