@meistrari/minuta-react 1.2.0 → 1.3.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/README.md +28 -7
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@ um `Blob` de `.docx`. Buscar o documento, persistir a edição e baixar o arquiv
|
|
|
35
35
|
| `chrome` | — | `{ header, footer, headerScope, footerScope, showPageNumber }` |
|
|
36
36
|
| `variables` | — | catálogo `{ key, label, description?, group? }[]` → liga o modo template |
|
|
37
37
|
| `uploadImage` | — | `(file) => Promise<{ src, vaultSrc } \| null>` |
|
|
38
|
+
| `imageFallback` | `'dataUri'` | `'none'` = upload falhou → não insere nada, só `onImageUploadError` |
|
|
39
|
+
| `onImageUploadError` | — | `(error, file) => void` |
|
|
38
40
|
| `toolbar` | `true` | `false` = você monta a sua sobre `ref.current.tiptap` |
|
|
39
41
|
| `blockClickWhileEditing` | `false` | dispara `onBlockClick` também em edição (padrão: só em leitura) |
|
|
40
42
|
| `onChange` | — | `(html) => void`, a cada edição |
|
|
@@ -81,13 +83,21 @@ de conta no defesa.ai:
|
|
|
81
83
|
|
|
82
84
|
```
|
|
83
85
|
GET /data/case/:id/html → { html, chrome, margins, source, editionId, variablesMarked, markedVariables }
|
|
84
|
-
POST /data/case/:id/editions { name, html } → cria a edição → { id, updatedAt, … }
|
|
85
|
-
PATCH /data/case/:id/editions/:id → salva → { updatedAt, updatedBy, … }
|
|
86
|
+
POST /data/case/:id/editions { name, html } → cria a edição → { id, updatedAt, contentHash, … }
|
|
87
|
+
PATCH /data/case/:id/editions/:id → salva → { updatedAt, updatedBy, contentHash, … }
|
|
86
88
|
{ html, baseUpdatedAt } 400 sem o token; 409 se outro salvou antes
|
|
89
|
+
GET /data/case/:id/editions → [{ id, updatedAt, updatedBy, contentHash, … }] sem html
|
|
87
90
|
POST /data/case/:id/editions/:id/versions → marco no histórico (o PATCH NÃO cria versão)
|
|
91
|
+
{ comment?, baseUpdatedAt? } com baseUpdatedAt: 409 se a revisão mudou; já versionada → 200 reused
|
|
88
92
|
POST /data/case/:id/docx → .docx do estado atual (a edição, se existir)
|
|
89
93
|
```
|
|
90
94
|
|
|
95
|
+
`contentHash` é o sha256 do `html` exatamente como foi gravado (o servidor não
|
|
96
|
+
normaliza): num save que deu timeout, compare com o hash do que você enviou
|
|
97
|
+
pela listagem, sem baixar o documento. `baseUpdatedAt` no `POST …/versions`
|
|
98
|
+
amarra o checkpoint à revisão que você viu: a versão nunca sai com o seu nome
|
|
99
|
+
e o texto que outra pessoa salvou depois, e repetir a chamada não duplica.
|
|
100
|
+
|
|
91
101
|
```tsx
|
|
92
102
|
// abrir
|
|
93
103
|
const doc = await api.get(`/case/${caseId}/html`)
|
|
@@ -178,17 +188,28 @@ salva a edição. Decisão de UX do seu app; as duas funcionam.
|
|
|
178
188
|
### Imagens inseridas pelo advogado
|
|
179
189
|
|
|
180
190
|
`uploadImage` devolve `{ src, vaultSrc }`: o editor grava a tag com o `src`
|
|
181
|
-
(presignado, expira) e `data-vault-src` (a `vault://`, durável).
|
|
182
|
-
|
|
191
|
+
(presignado, expira) e `data-vault-src` (a `vault://`, durável). Persista o
|
|
192
|
+
`getHTML()` como está: o `POST /data/case/:id/docx` usa o `data-vault-src` e
|
|
193
|
+
resolve `vault://` sozinho. Ao reabrir uma edição salva, renove os links antes
|
|
194
|
+
de mostrar:
|
|
183
195
|
|
|
184
196
|
```tsx
|
|
185
197
|
// resolver: POST /data/vault/download-url { vaultUrl } → { downloadUrl } (pelo seu backend)
|
|
186
198
|
await editor.current!.refreshVaultImages(vaultUrl => api.post('/vault/download-url', { vaultUrl }).then(r => r.downloadUrl))
|
|
187
199
|
```
|
|
188
200
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
Renova tanto `data-vault-src` quanto imagens salvas só com `src="vault://…"`
|
|
202
|
+
(que ganham o `data-vault-src`), mantendo a referência durável. Não entra no
|
|
203
|
+
undo nem dispara `onChange`: chame `getHTML()` depois se guarda uma cópia. O
|
|
204
|
+
`exportDocx()` do browser baixa pelo `src`, então renove antes de exportar.
|
|
205
|
+
|
|
206
|
+
Se o upload falhar (ou `uploadImage` devolver `null`), o padrão é embutir a
|
|
207
|
+
imagem em base64. Um app cujo documento canônico depende de `vault://` não
|
|
208
|
+
quer isso: `imageFallback="none"` não insere nada e `onImageUploadError` recebe
|
|
209
|
+
o erro e o arquivo para você mostrar e deixar tentar de novo.
|
|
210
|
+
|
|
211
|
+
`setVariableImage(id, src, vaultSrc)` grava o `data-vault-src` junto — use a
|
|
212
|
+
forma de três argumentos para a imagem sobreviver à expiração do `src`.
|
|
192
213
|
|
|
193
214
|
## Next.js (App Router)
|
|
194
215
|
|
package/dist/index.d.mts
CHANGED
|
@@ -32,6 +32,9 @@ interface MinutaEditorProps {
|
|
|
32
32
|
chrome?: Partial<MinutaChromeText>;
|
|
33
33
|
variables?: MinutaVariableCatalog;
|
|
34
34
|
uploadImage?: MinutaEditorOptions['uploadImage'];
|
|
35
|
+
/** `'dataUri'` (default) embute em base64 quando o upload falha; `'none'` não insere e avisa por `onImageUploadError` */
|
|
36
|
+
imageFallback?: MinutaEditorOptions['imageFallback'];
|
|
37
|
+
onImageUploadError?: MinutaEditorOptions['onImageUploadError'];
|
|
35
38
|
/** barra de formatação do pacote (default: true). `false` = monte a sua sobre `ref.tiptap` */
|
|
36
39
|
toolbar?: boolean;
|
|
37
40
|
showBlockOrigin?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,9 @@ interface MinutaEditorProps {
|
|
|
32
32
|
chrome?: Partial<MinutaChromeText>;
|
|
33
33
|
variables?: MinutaVariableCatalog;
|
|
34
34
|
uploadImage?: MinutaEditorOptions['uploadImage'];
|
|
35
|
+
/** `'dataUri'` (default) embute em base64 quando o upload falha; `'none'` não insere e avisa por `onImageUploadError` */
|
|
36
|
+
imageFallback?: MinutaEditorOptions['imageFallback'];
|
|
37
|
+
onImageUploadError?: MinutaEditorOptions['onImageUploadError'];
|
|
35
38
|
/** barra de formatação do pacote (default: true). `false` = monte a sua sobre `ref.tiptap` */
|
|
36
39
|
toolbar?: boolean;
|
|
37
40
|
showBlockOrigin?: boolean;
|
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,8 @@ const MinutaEditor = forwardRef((props, ref) => {
|
|
|
21
21
|
variables: props.variables,
|
|
22
22
|
// lido na hora do upload, não no mount: o host pode trocar a função
|
|
23
23
|
uploadImage: (file) => callbacks.current.uploadImage ? callbacks.current.uploadImage(file) : Promise.resolve(null),
|
|
24
|
+
imageFallback: props.imageFallback,
|
|
25
|
+
onImageUploadError: (error, file) => callbacks.current.onImageUploadError?.(error, file),
|
|
24
26
|
toolbar: props.toolbar,
|
|
25
27
|
showBlockOrigin: props.showBlockOrigin,
|
|
26
28
|
blockClickWhileEditing: props.blockClickWhileEditing,
|
|
@@ -64,6 +66,9 @@ const MinutaEditor = forwardRef((props, ref) => {
|
|
|
64
66
|
useEffect(() => {
|
|
65
67
|
instance.current?.setBlockClickWhileEditing(props.blockClickWhileEditing === true);
|
|
66
68
|
}, [props.blockClickWhileEditing]);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
instance.current?.setImageFallback(props.imageFallback ?? "dataUri");
|
|
71
|
+
}, [props.imageFallback]);
|
|
67
72
|
useImperativeHandle(ref, () => instance.current);
|
|
68
73
|
return createElement("div", {
|
|
69
74
|
ref: host,
|