mgcode-docx-editor 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 +21 -0
- package/README.md +277 -0
- package/dist/index.d.mts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +1483 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1463 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MGCODE
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# mgcode-docx-editor
|
|
2
|
+
|
|
3
|
+
Editor WYSIWYG de **templates .docx** feito do zero (contentEditable + `document.execCommand`),
|
|
4
|
+
com a "casca" (toolbar, régua, zoom) em Material UI. Autora um documento com
|
|
5
|
+
cabeçalho/rodapé fixos e corpo com placeholders `{{variavel}}`, e exporta um
|
|
6
|
+
`.docx` válido para o fluxo LibreOffice → PDF.
|
|
7
|
+
|
|
8
|
+
## Instalação
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install mgcode-docx-editor
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Peer dependencies (devem estar instaladas no projeto consumidor): `react`, `react-dom`,
|
|
15
|
+
`@mui/material`, `@mui/icons-material`, `@emotion/react`, `@emotion/styled`.
|
|
16
|
+
|
|
17
|
+
## API
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { useRef } from 'react';
|
|
21
|
+
import { DocxEditor, DocxEditorHandle } from 'mgcode-docx-editor';
|
|
22
|
+
|
|
23
|
+
const editorRef = useRef<DocxEditorHandle>(null);
|
|
24
|
+
|
|
25
|
+
<DocxEditor
|
|
26
|
+
ref={editorRef}
|
|
27
|
+
documentBuffer={documentBuffer ?? undefined} // importar .docx existente
|
|
28
|
+
document={documentBuffer ? undefined : documentModel} // ou criar a partir de modelo
|
|
29
|
+
mode="editing" // 'editing' | 'viewing'
|
|
30
|
+
showToolbar
|
|
31
|
+
showRuler
|
|
32
|
+
showZoomControl
|
|
33
|
+
/>;
|
|
34
|
+
|
|
35
|
+
// Salvar:
|
|
36
|
+
const buffer = await editorRef.current?.save(); // Promise<ArrayBuffer> (.docx)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Props (`DocxEditorProps`)
|
|
40
|
+
|
|
41
|
+
| Prop | Tipo | Descrição |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `documentBuffer` | `ArrayBuffer?` | Importa um `.docx` existente. Tem precedência sobre `document`. |
|
|
44
|
+
| `document` | `DocumentModel?` | Cria/edita a partir de um modelo estruturado. |
|
|
45
|
+
| `mode` | `'editing' \| 'viewing'` | Editável ou somente leitura. |
|
|
46
|
+
| `showToolbar` | `boolean?` | Exibe a barra de ferramentas. |
|
|
47
|
+
| `showRuler` | `boolean?` | Exibe a régua funcional. |
|
|
48
|
+
| `showZoomControl` | `boolean?` | Exibe o controle de zoom. |
|
|
49
|
+
|
|
50
|
+
### Handle imperativo (`DocxEditorHandle`, via `ref`)
|
|
51
|
+
|
|
52
|
+
- `save(): Promise<ArrayBuffer>` — serializa o conteúdo atual para `.docx`.
|
|
53
|
+
- `getModel(): DocumentModel` — retorna o modelo atual (`header`/`body`/`footer`/`variables`).
|
|
54
|
+
|
|
55
|
+
### `DocumentModel`
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
interface DocumentModel {
|
|
59
|
+
header?: string; // HTML do cabeçalho fixo (ex.: logo)
|
|
60
|
+
body: string; // HTML do corpo (contém {{variaveis}})
|
|
61
|
+
footer?: string; // HTML do rodapé fixo
|
|
62
|
+
variables?: string[]; // nomes para o menu "Inserir variável"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Arquitetura
|
|
67
|
+
|
|
68
|
+
- **Editor**: três regiões `contentEditable` (header/body/footer) + `execCommand`.
|
|
69
|
+
- **Página**: **A4** (794×1123 px a 96dpi na tela; 11906×16838 twips no export,
|
|
70
|
+
via `PAGE_SIZE_A4_TWIPS` em `docx/generate.ts`).
|
|
71
|
+
- **Exportação** (`save()`): `@turbodocx/html-to-docx` (MIT) converte o HTML das
|
|
72
|
+
regiões em `.docx`, com cabeçalho/rodapé como partes do Word e margens da régua
|
|
73
|
+
como `w:pgMar`. Ver `docx/generate.ts`.
|
|
74
|
+
- **Importação** (`documentBuffer`): `mammoth` (BSD-2) converte o `.docx` em HTML.
|
|
75
|
+
Ver `docx/importDocx.ts`.
|
|
76
|
+
- **Régua**: arrasta margens de página (→ margens da seção do `.docx`) e recuos de
|
|
77
|
+
parágrafo. Conversões px↔twips em `docx/units.ts`.
|
|
78
|
+
|
|
79
|
+
### Polyfill de `Buffer` (imagens no browser)
|
|
80
|
+
|
|
81
|
+
O bundle browser da `@turbodocx/html-to-docx` usa o global `Buffer` do Node para
|
|
82
|
+
decodificar imagens base64; CRA/webpack 5 não polyfilla globais do Node, o que
|
|
83
|
+
causava `"Buffer is not defined"` ao salvar documentos com imagens. Correção:
|
|
84
|
+
dependência `buffer` (feross/buffer, MIT) e `ensureBufferGlobal()` chamado no
|
|
85
|
+
início de `modelToDocx()` em `docx/generate.ts` — atribui `globalThis.Buffer` ao
|
|
86
|
+
polyfill se indefinido. É feito em tempo de chamada (não de import), então
|
|
87
|
+
funciona independentemente da ordem de carregamento e não sobrescreve um
|
|
88
|
+
`Buffer` já existente (Node/Jest).
|
|
89
|
+
|
|
90
|
+
### Paginação visual (estilo Word)
|
|
91
|
+
|
|
92
|
+
O editor renderiza N caixas "papel" A4 posicionadas absolutamente
|
|
93
|
+
(`data-page-index` em cada uma, para testes/automação), mas o corpo continua
|
|
94
|
+
sendo **um único `contentEditable` contínuo** atravessando todas as páginas —
|
|
95
|
+
o DOM nunca é dividido, então cursor, undo e `execCommand` seguem funcionando.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
┌─ página 0 ──────────────┐
|
|
99
|
+
│ header REAL (editável) │ ← 48px da borda (distância do Word)
|
|
100
|
+
│ corpo contínuo… │
|
|
101
|
+
│ footer REAL (editável) │
|
|
102
|
+
├─ gap 24px ──────────────┤
|
|
103
|
+
┌─ página 1+ ─────────────┐
|
|
104
|
+
│ espelho header (RO) │ ← aria-hidden, dangerouslySetInnerHTML
|
|
105
|
+
│ …corpo continua │ sincronizado a cada input
|
|
106
|
+
│ espelho footer (RO) │
|
|
107
|
+
└─────────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- **Quebra por bloco**: `docx/pagination.ts` (módulo puro, sem DOM no cálculo).
|
|
111
|
+
`computePageLayout(blocks, {usableHeightPx, interPageGapPx})` decide, para cada
|
|
112
|
+
bloco top-level do corpo, se ele cruzaria a zona do rodapé; se sim (e couber
|
|
113
|
+
inteiro numa página), um **espaçador** não-editável é inserido antes dele
|
|
114
|
+
(`createSpacerElement()`: div com `data-page-spacer`, `contenteditable=false`),
|
|
115
|
+
empurrando-o para a próxima página.
|
|
116
|
+
- **Contrato de coordenadas**: `BlockBox.top` é em coordenadas **sem
|
|
117
|
+
espaçadores**; a medição do DOM em `DocxEditor.tsx` subtrai a altura acumulada
|
|
118
|
+
dos espaçadores acima de cada bloco antes de chamar `computePageLayout`.
|
|
119
|
+
- **Recomputação**: a cada input, mudança de margens/régua, import de `.docx` e
|
|
120
|
+
`load` de imagem (listener em fase de captura), com throttle via
|
|
121
|
+
`requestAnimationFrame` (`schedulePagination`). O ciclo é auto-corrigível:
|
|
122
|
+
remove todos os espaçadores e reinsere do zero.
|
|
123
|
+
- **Header/footer editáveis** vivem apenas na página 1, nas áreas de margem;
|
|
124
|
+
páginas 2+ mostram espelhos somente leitura sincronizados a cada edição.
|
|
125
|
+
- **Sem rastro no modelo**: `buildModel()`/`save()` removem os espaçadores via
|
|
126
|
+
`stripPageSpacers()` — a paginação é puramente visual e o round-trip do HTML
|
|
127
|
+
do corpo é exato (há teste para isso).
|
|
128
|
+
|
|
129
|
+
### Indicador de região em edição (estilo Word)
|
|
130
|
+
|
|
131
|
+
`DocxEditor.tsx` mantém o estado `focusedRegion: 'header' | 'body' | 'footer' | null`
|
|
132
|
+
(atualizado em `onRegionFocus`/`onRegionBlur`):
|
|
133
|
+
|
|
134
|
+
- Ao focar o **cabeçalho ou rodapé**, a região ganha contorno tracejado
|
|
135
|
+
(`outline: 1px dashed`, cor primária) + etiqueta `Chip` MUI ("Cabeçalho"/"Rodapé"),
|
|
136
|
+
e o **corpo esmaece** (`opacity: 0.45`, via a flag derivada `editingChrome`).
|
|
137
|
+
- Ao editar o **corpo**, header/footer reais e os espelhos das páginas 2+ esmaecem
|
|
138
|
+
levemente (`opacity: 0.55`).
|
|
139
|
+
|
|
140
|
+
É indicação puramente visual — não altera modelo nem exportação.
|
|
141
|
+
|
|
142
|
+
### Variáveis `{{...}}`
|
|
143
|
+
|
|
144
|
+
São inseridas como **texto literal contíguo** (via Range API, não `execCommand`),
|
|
145
|
+
garantindo que o LibreOffice/docxtemplater consiga substituí-las — o token nunca é
|
|
146
|
+
quebrado entre runs do Word. Há teste dedicado para isso em
|
|
147
|
+
`docx/__tests__/generate.test.ts`.
|
|
148
|
+
|
|
149
|
+
### Campos de página do Word (`[[PAGINA]]` / `[[TOTAL_PAGINAS]]`)
|
|
150
|
+
|
|
151
|
+
Módulo `docx/pageFields.ts`. O usuário insere **tokens literais** `[[PAGINA]]` e
|
|
152
|
+
`[[TOTAL_PAGINAS]]` que, na exportação, viram campos nativos do Word
|
|
153
|
+
(PAGE/NUMPAGES) que o Word/LibreOffice atualizam sozinhos.
|
|
154
|
+
|
|
155
|
+
- **Sintaxe `[[...]]` é deliberada**: diferente de `{{...}}` para o docxtemplater
|
|
156
|
+
**nunca** tentar substituí-los no pipeline.
|
|
157
|
+
- **Inserção**: menu "Variável" da toolbar (agora **sempre visível**, mesmo sem
|
|
158
|
+
`variables`), itens "Nº da página" e "Total de páginas" → prop
|
|
159
|
+
`onInsertPageField` do `Toolbar.tsx` → `handleInsertPageField` em
|
|
160
|
+
`DocxEditor.tsx`, que insere via Range API (contíguo, como as variáveis).
|
|
161
|
+
Sem região focada, o fallback é o **rodapé** (onde campos de página fazem sentido).
|
|
162
|
+
- **Exportação** (`modelToDocx` em `docx/generate.ts`): se `hasPageFieldTokens()`
|
|
163
|
+
detecta tokens no header/footer do modelo, o `.docx` gerado pela lib é
|
|
164
|
+
pós-processado com **JSZip**: em cada `word/header*.xml` e `word/footer*.xml`,
|
|
165
|
+
`injectPageFields()` substitui cada token por
|
|
166
|
+
`<w:fldSimple w:instr=" PAGE ">` / `" NUMPAGES "`. Sem tokens, o buffer sai
|
|
167
|
+
intacto (nenhum reprocessamento do zip).
|
|
168
|
+
- **Processamento run a run** (invariante crítico): `injectPageFields()` itera
|
|
169
|
+
o XML com `RUN_PATTERN`, que casa **um `<r>…</r>` inteiro por vez** — o lazy
|
|
170
|
+
até o primeiro `</r>` nunca atravessa runs vizinhos, porque runs não aninham
|
|
171
|
+
em OOXML. Cada run com token é reconstruído por `rebuildRun()` +
|
|
172
|
+
`splitTextByTokens()` como uma sequência ordenada de runs de texto e
|
|
173
|
+
`fldSimple`, copiando o `rPr` original para dentro de cada pedaço — a
|
|
174
|
+
formatação (negrito, fonte etc.) é preservada. **Por que run a run**: a
|
|
175
|
+
implementação antiga usava um único regex sobre o XML inteiro cujo grupo
|
|
176
|
+
lazy do `rPr` podia "esticar" por cima de runs vizinhos quando havia um run
|
|
177
|
+
anterior com formatação não vazia — o resultado era XML embaralhado
|
|
178
|
+
(`fldSimple` aninhado, texto duplicado) e o Word **recusava o arquivo**. Há
|
|
179
|
+
teste de regressão dedicado em `docx/__tests__/pageFields.test.ts`.
|
|
180
|
+
- **Dois formatos de OOXML**: `RUN_PATTERN`/`rebuildRun()` aceitam XML
|
|
181
|
+
prefixado (`<w:r>`, como no document.xml) **e** em namespace default sem
|
|
182
|
+
prefixo (`<r>`, formato dos header/footer gerados pela
|
|
183
|
+
`@turbodocx/html-to-docx`). No caso sem prefixo, o `fldSimple` declara
|
|
184
|
+
`xmlns:w` no próprio elemento, exigido pelo atributo `w:instr`.
|
|
185
|
+
- **Valor em cache**: o campo carrega o texto "1", exibido até o Word/LibreOffice
|
|
186
|
+
atualizar os campos.
|
|
187
|
+
- **Preview no editor**: nos espelhos das páginas 2+, `withPagePreview()` em
|
|
188
|
+
`DocxEditor.tsx` troca os tokens pelos números reais ("Página 2 de 3"); na
|
|
189
|
+
página 1 (regiões editáveis) os tokens ficam visíveis como texto.
|
|
190
|
+
|
|
191
|
+
### Redimensionamento de imagens
|
|
192
|
+
|
|
193
|
+
Implementado em `DocxEditor.tsx` (estado `selectedImg` + `frame`), sem tocar no
|
|
194
|
+
`execCommand`:
|
|
195
|
+
|
|
196
|
+
- **Seleção**: delegação de clique na coluna de páginas (`handleColumnClick`) —
|
|
197
|
+
clicar num `<img>` dentro de qualquer região `contentEditable` seleciona a
|
|
198
|
+
imagem; clicar fora deseleciona. Em `mode="viewing"` não há seleção.
|
|
199
|
+
- **Moldura**: uma overlay absoluta sobre a coluna de páginas
|
|
200
|
+
(`data-testid="image-resize-frame"`) com 4 alças de canto
|
|
201
|
+
(`data-testid="image-resize-handle"`). `updateFrame()` posiciona a moldura a
|
|
202
|
+
partir de `getBoundingClientRect()` da imagem, **dividindo pelo zoom** (a
|
|
203
|
+
coluna é escalada via `transform: scale`, mas a overlay vive em coordenadas
|
|
204
|
+
sem zoom). A moldura tem `pointer-events: none`; só as alças são interativas.
|
|
205
|
+
- **Drag** (`startResize`): durante o arraste só a **largura** é gravada
|
|
206
|
+
(`style.width` em px, `height: auto` mantém a proporção); o delta do mouse é
|
|
207
|
+
compensado pelo zoom e a largura é limitada entre 20px e a largura da região.
|
|
208
|
+
No `mouseup`, a altura é **fixada em px** (`style.height`) e
|
|
209
|
+
`handleContentChanged()` dispara repaginação + sincronização dos espelhos.
|
|
210
|
+
- **Caminho até o `.docx`**: a exportação (`@turbodocx/html-to-docx`) lê o
|
|
211
|
+
`style="width/height"` em px da imagem e converte px→EMU (1px = 9525 EMU) no
|
|
212
|
+
`wp:extent` — o tamanho redimensionado vai para o arquivo. Há teste de
|
|
213
|
+
caracterização em `docx/__tests__/generate.test.ts`.
|
|
214
|
+
- **Deseleção automática**: ao clicar fora, ao reimportar um `.docx`
|
|
215
|
+
(`docVersion` muda) ou se a imagem sair do DOM (`img.isConnected` é checado
|
|
216
|
+
em `updateFrame()`); a moldura também é reposicionada quando layout, margens
|
|
217
|
+
ou espelhos mudam.
|
|
218
|
+
|
|
219
|
+
## Licenças das dependências (todas permissivas / uso comercial livre)
|
|
220
|
+
|
|
221
|
+
- `@turbodocx/html-to-docx` — MIT
|
|
222
|
+
- `mammoth` — BSD-2-Clause
|
|
223
|
+
- `@mui/material` / `@mui/icons-material` — MIT
|
|
224
|
+
- `buffer` (feross/buffer, polyfill do global `Buffer`) — MIT
|
|
225
|
+
- `jszip` (pós-processamento dos campos de página no `.docx`) — MIT
|
|
226
|
+
|
|
227
|
+
## Limitações conhecidas (v1)
|
|
228
|
+
|
|
229
|
+
- `document` e `documentBuffer` são valores **iniciais** (componente não controlado,
|
|
230
|
+
como editores em geral). Trocar essas props depois de montado **não** re-sincroniza
|
|
231
|
+
o conteúdo já editado, exceto por um novo `documentBuffer` (que dispara reimportação).
|
|
232
|
+
- Import de `.docx` externo via `mammoth` recupera apenas o **corpo**; cabeçalho e
|
|
233
|
+
rodapé de arquivos de terceiros não são reconstruídos. Para templates criados por
|
|
234
|
+
este editor, o `DocumentModel` é a fonte de verdade.
|
|
235
|
+
- `document.execCommand` é depreciado (porém suportado em todos os browsers atuais);
|
|
236
|
+
é a escolha deliberada para um editor "do zero" sem framework de edição.
|
|
237
|
+
- Colar conteúdo do Word ainda não é sanitizado (escopo futuro).
|
|
238
|
+
- **Paginação por bloco apenas**: um parágrafo nunca é dividido no meio entre
|
|
239
|
+
páginas — o bloco inteiro é empurrado. Blocos mais altos que a área útil de
|
|
240
|
+
uma página **não** são divididos e transbordam sobre a página seguinte.
|
|
241
|
+
- Os espelhos de cabeçalho/rodapé nas páginas 2+ são somente leitura; a edição
|
|
242
|
+
acontece nas regiões reais da página 1.
|
|
243
|
+
|
|
244
|
+
## Testes
|
|
245
|
+
|
|
246
|
+
- `docx/__tests__/units.test.ts` — conversões de unidade.
|
|
247
|
+
- `docx/__tests__/generate.test.ts` — `.docx` válido, texto/variável preservados,
|
|
248
|
+
header/footer, contiguidade do `{{token}}`, imagem base64 → `word/media`,
|
|
249
|
+
`w:pgSz` A4, `save()` funciona com `globalThis.Buffer` removido (polyfill),
|
|
250
|
+
tokens `[[PAGINA]]`/`[[TOTAL_PAGINAS]]` viram `fldSimple` PAGE/NUMPAGES no
|
|
251
|
+
footer (sem tokens vazados), documento sem tokens sai intacto, e
|
|
252
|
+
caracterização do `wp:extent`: `style="width/height"` em px na imagem vira
|
|
253
|
+
EMU no `.docx` (1px = 9525 EMU).
|
|
254
|
+
- `docx/__tests__/pageFields.test.ts` — `injectPageFields()`: divisão do run
|
|
255
|
+
preservando texto ao redor e `rPr`, múltiplos tokens no mesmo run, XML com e
|
|
256
|
+
sem prefixo `w:` (declaração de `xmlns:w`), XML sem tokens inalterado,
|
|
257
|
+
`hasPageFieldTokens()`, e **regressão do docx corrompido**: "não embaralha o
|
|
258
|
+
XML quando há run anterior com formatação" (o regex antigo atravessava runs
|
|
259
|
+
e gerava `fldSimple` aninhado/texto duplicado).
|
|
260
|
+
- `docx/__tests__/pagination.test.ts` — `computePageLayout` (quebras, espaçadores,
|
|
261
|
+
blocos maiores que a página, contagem de páginas).
|
|
262
|
+
- `docx/__tests__/importDocx.test.ts` — round-trip de importação.
|
|
263
|
+
- `__tests__/DocxEditor.test.tsx` — `save()`, render, inserção de variável, modo
|
|
264
|
+
leitura, `getModel()` remove espaçadores com round-trip exato do corpo,
|
|
265
|
+
etiqueta de foco (Chip "Cabeçalho"/"Rodapé" ao focar a região), inserção dos
|
|
266
|
+
campos de página pelo menu "Variável", seleção de imagem (clique mostra a
|
|
267
|
+
moldura com 4 alças; clique fora deseleciona).
|
|
268
|
+
|
|
269
|
+
A formatação via `execCommand`, o arraste da régua e a paginação visual
|
|
270
|
+
(múltiplas páginas, rodapé ancorado no pé da página, salvar com imagem sem erro
|
|
271
|
+
de `Buffer`) são validados em **browser real** via script Playwright, pois o
|
|
272
|
+
jsdom não implementa `execCommand` nem layout real. Também validados no browser:
|
|
273
|
+
etiquetas e esmaecimento de foco, preview "Página 2 de 2" nos espelhos,
|
|
274
|
+
`fldSimple` no `footer.xml` do `.docx` salvo (1 PAGE + 1 NUMPAGES, runs
|
|
275
|
+
balanceados, sem aninhamento — todas as partes XML do zip validadas com parser
|
|
276
|
+
rigoroso .NET) e o drag de resize de imagem ponta a ponta (arrastar a alça
|
|
277
|
+
altera a largura e o `wp:extent` exportado corresponde ao tamanho arrastado).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface DocumentModel {
|
|
4
|
+
/** HTML do cabeçalho fixo (ex.: logo). Opcional. */
|
|
5
|
+
header?: string;
|
|
6
|
+
/** HTML do corpo do documento. Contém os placeholders {{variavel}}. */
|
|
7
|
+
body: string;
|
|
8
|
+
/** HTML do rodapé fixo. Opcional. */
|
|
9
|
+
footer?: string;
|
|
10
|
+
/** Nomes de variáveis disponíveis para inserir (ex.: ["patientName"]). */
|
|
11
|
+
variables?: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Margens da página em twips (1/1440 pol), como o Word/OOXML espera. */
|
|
14
|
+
interface PageMarginsTwips {
|
|
15
|
+
top: number;
|
|
16
|
+
right: number;
|
|
17
|
+
bottom: number;
|
|
18
|
+
left: number;
|
|
19
|
+
}
|
|
20
|
+
type DocxEditorMode = 'editing' | 'viewing';
|
|
21
|
+
interface DocxEditorProps {
|
|
22
|
+
/** Importa um .docx existente (tem precedência sobre `document`). */
|
|
23
|
+
documentBuffer?: ArrayBuffer;
|
|
24
|
+
/** Cria/edita a partir de um modelo estruturado. */
|
|
25
|
+
document?: DocumentModel;
|
|
26
|
+
mode: DocxEditorMode;
|
|
27
|
+
showToolbar?: boolean;
|
|
28
|
+
showRuler?: boolean;
|
|
29
|
+
showZoomControl?: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface DocxEditorHandle {
|
|
32
|
+
/** Serializa o conteúdo atual para um .docx (ArrayBuffer). */
|
|
33
|
+
save(): Promise<ArrayBuffer>;
|
|
34
|
+
/** Retorna o modelo atual do editor. */
|
|
35
|
+
getModel(): DocumentModel;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare const DocxEditor: react.ForwardRefExoticComponent<DocxEditorProps & react.RefAttributes<DocxEditorHandle>>;
|
|
39
|
+
|
|
40
|
+
export { type DocumentModel, DocxEditor, type DocxEditorHandle, type DocxEditorMode, type DocxEditorProps, type PageMarginsTwips };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface DocumentModel {
|
|
4
|
+
/** HTML do cabeçalho fixo (ex.: logo). Opcional. */
|
|
5
|
+
header?: string;
|
|
6
|
+
/** HTML do corpo do documento. Contém os placeholders {{variavel}}. */
|
|
7
|
+
body: string;
|
|
8
|
+
/** HTML do rodapé fixo. Opcional. */
|
|
9
|
+
footer?: string;
|
|
10
|
+
/** Nomes de variáveis disponíveis para inserir (ex.: ["patientName"]). */
|
|
11
|
+
variables?: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Margens da página em twips (1/1440 pol), como o Word/OOXML espera. */
|
|
14
|
+
interface PageMarginsTwips {
|
|
15
|
+
top: number;
|
|
16
|
+
right: number;
|
|
17
|
+
bottom: number;
|
|
18
|
+
left: number;
|
|
19
|
+
}
|
|
20
|
+
type DocxEditorMode = 'editing' | 'viewing';
|
|
21
|
+
interface DocxEditorProps {
|
|
22
|
+
/** Importa um .docx existente (tem precedência sobre `document`). */
|
|
23
|
+
documentBuffer?: ArrayBuffer;
|
|
24
|
+
/** Cria/edita a partir de um modelo estruturado. */
|
|
25
|
+
document?: DocumentModel;
|
|
26
|
+
mode: DocxEditorMode;
|
|
27
|
+
showToolbar?: boolean;
|
|
28
|
+
showRuler?: boolean;
|
|
29
|
+
showZoomControl?: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface DocxEditorHandle {
|
|
32
|
+
/** Serializa o conteúdo atual para um .docx (ArrayBuffer). */
|
|
33
|
+
save(): Promise<ArrayBuffer>;
|
|
34
|
+
/** Retorna o modelo atual do editor. */
|
|
35
|
+
getModel(): DocumentModel;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare const DocxEditor: react.ForwardRefExoticComponent<DocxEditorProps & react.RefAttributes<DocxEditorHandle>>;
|
|
39
|
+
|
|
40
|
+
export { type DocumentModel, DocxEditor, type DocxEditorHandle, type DocxEditorMode, type DocxEditorProps, type PageMarginsTwips };
|