@meistrari/minuta-editor 1.0.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 +141 -0
- package/dist/chunks/docxExport.mjs +1282 -0
- package/dist/docx.d.mts +5 -0
- package/dist/docx.d.ts +5 -0
- package/dist/docx.mjs +5 -0
- package/dist/index.d.mts +413 -0
- package/dist/index.d.ts +413 -0
- package/dist/index.mjs +1887 -0
- package/dist/shared/minuta-editor.b2512170.mjs +711 -0
- package/dist/shared/minuta-editor.e223a421.d.mts +166 -0
- package/dist/shared/minuta-editor.e223a421.d.ts +166 -0
- package/dist/style.css +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
import { Node } from '@tiptap/pm/model';
|
|
3
|
+
import { EditorView } from '@tiptap/pm/view';
|
|
4
|
+
import { PluginKey, Plugin } from '@tiptap/pm/state';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Engine de paginação da PoC.
|
|
8
|
+
*
|
|
9
|
+
* O documento continua linear no ProseMirror; as "páginas" nascem de widget
|
|
10
|
+
* decorations ("chrome") inseridas ENTRE os nós internos dos blocos:
|
|
11
|
+
* cada chrome preenche o resto da área útil da página (filler), desenha o
|
|
12
|
+
* rodapé (nº da página) dentro da margem inferior, a faixa de separação
|
|
13
|
+
* entre páginas e o cabeçalho (logo do template) dentro da margem superior
|
|
14
|
+
* da página seguinte.
|
|
15
|
+
*
|
|
16
|
+
* A medição roda fora do plugin (componente agenda via rAF) em coordenadas
|
|
17
|
+
* de layout (offsetTop/offsetHeight — imunes ao CSS zoom da folha) e
|
|
18
|
+
* NORMALIZADAS: a altura de todo chrome existente é subtraída, então o
|
|
19
|
+
* algoritmo sempre enxerga o fluxo "sem paginação" e converge (recomputar
|
|
20
|
+
* com chrome na tela produz os mesmos breaks → sem loop de layout).
|
|
21
|
+
*
|
|
22
|
+
* Regras de quebra:
|
|
23
|
+
* - quebra somente entre nós (parágrafo/título/ilha) — nó mais alto que a
|
|
24
|
+
* página flui e as páginas internas são contadas, sem chrome no meio;
|
|
25
|
+
* - keep-with-next: título não fica órfão no fim da página (a quebra sobe
|
|
26
|
+
* para antes do título).
|
|
27
|
+
*/
|
|
28
|
+
interface PocPageConfig {
|
|
29
|
+
pageHeight: number;
|
|
30
|
+
margins: {
|
|
31
|
+
top: number;
|
|
32
|
+
right: number;
|
|
33
|
+
bottom: number;
|
|
34
|
+
left: number;
|
|
35
|
+
};
|
|
36
|
+
gap: number;
|
|
37
|
+
headerLogoUrl?: string | null;
|
|
38
|
+
headerPosition?: 'left' | 'center' | 'right';
|
|
39
|
+
/** texto editável do cabeçalho (ao lado do logo) */
|
|
40
|
+
headerText?: string;
|
|
41
|
+
/** texto editável do rodapé (lado esquerdo; o nº de página fica à direita) */
|
|
42
|
+
footerText?: string;
|
|
43
|
+
/** onde o conteúdo do cabeçalho aparece: todas as páginas ou só a primeira */
|
|
44
|
+
headerScope?: 'all' | 'first';
|
|
45
|
+
/** onde o conteúdo custom do rodapé aparece (o nº de página é sempre em todas) */
|
|
46
|
+
footerScope?: 'all' | 'first';
|
|
47
|
+
/** numeração "Página N de M" no rodapé — opcional por conjunto de cabeçalho */
|
|
48
|
+
showPageNumber?: boolean;
|
|
49
|
+
/** bump força a reconstrução do chrome (muda a key das decorations) */
|
|
50
|
+
version?: number;
|
|
51
|
+
}
|
|
52
|
+
/** nota de rodapé que cai numa página (o marcador está no corpo dela) */
|
|
53
|
+
interface PocPageNote {
|
|
54
|
+
n: number;
|
|
55
|
+
/** conteúdo em HTML de ênfase (b/i/u/br) — já sanitizado no render */
|
|
56
|
+
text: string;
|
|
57
|
+
/** corpo declarado no template, em pontos (default: 8pt, como o Word) */
|
|
58
|
+
size?: number | null;
|
|
59
|
+
/**
|
|
60
|
+
* posição do MARCADOR no documento. Só é usada para repartir as notas
|
|
61
|
+
* quando a quebra cai no meio do parágrafo: a nota mora na página da
|
|
62
|
+
* chamada, então as que ficam depois do corte viajam para a página nova.
|
|
63
|
+
*/
|
|
64
|
+
at?: number;
|
|
65
|
+
}
|
|
66
|
+
interface PocPageBreak {
|
|
67
|
+
pos: number;
|
|
68
|
+
filler: number;
|
|
69
|
+
pageNo: number;
|
|
70
|
+
/**
|
|
71
|
+
* quebra no MEIO de um parágrafo (entre linhas). O DOCX não recebe
|
|
72
|
+
* pageBreakBefore nessas: partir o parágrafo em dois no Word entregaria
|
|
73
|
+
* ao advogado um arquivo que não reflui quando ele edita o texto. Aqui o
|
|
74
|
+
* Word quebra naturalmente, e o preview só antecipa onde.
|
|
75
|
+
*/
|
|
76
|
+
soft?: boolean;
|
|
77
|
+
/** notas cujos marcadores estão nesta página — desenhadas acima do rodapé */
|
|
78
|
+
notes?: PocPageNote[];
|
|
79
|
+
/** altura reservada pelas notas (já descontada do filler) */
|
|
80
|
+
notesH?: number;
|
|
81
|
+
}
|
|
82
|
+
interface PagState {
|
|
83
|
+
breaks: PocPageBreak[];
|
|
84
|
+
total: number;
|
|
85
|
+
/** parágrafos-marcador "PAGEBREAK" (quebra manual do template) */
|
|
86
|
+
markers: {
|
|
87
|
+
from: number;
|
|
88
|
+
to: number;
|
|
89
|
+
}[];
|
|
90
|
+
}
|
|
91
|
+
declare const pocPageKey: PluginKey<PagState>;
|
|
92
|
+
declare const PAGINATE_META = "poc-paginate";
|
|
93
|
+
declare function pocChromeFlowHeight(cfg: PocPageConfig): number;
|
|
94
|
+
/**
|
|
95
|
+
* o chrome tem dois formatos: canvas (elementos posicionados, coordenadas no
|
|
96
|
+
* frame da PÁGINA — vem do editor estilo Word) e flow legado (texto corrido)
|
|
97
|
+
*/
|
|
98
|
+
declare function isPocChromeCanvas(html: string | undefined | null): boolean;
|
|
99
|
+
declare function buildPocHeaderEl(cfg: PocPageConfig): HTMLElement;
|
|
100
|
+
declare function buildPocFooterEl(cfg: PocPageConfig, pageNo: number, total: number): HTMLElement;
|
|
101
|
+
/** área de notas de rodapé: filete + notas, no pé da área útil (como no Word) */
|
|
102
|
+
declare function buildPocNotesEl(notes: PocPageNote[]): HTMLElement;
|
|
103
|
+
declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: HTMLElement): {
|
|
104
|
+
breaks: PocPageBreak[];
|
|
105
|
+
total: number;
|
|
106
|
+
markers: {
|
|
107
|
+
from: number;
|
|
108
|
+
to: number;
|
|
109
|
+
}[];
|
|
110
|
+
lastNotes: PocPageNote[];
|
|
111
|
+
};
|
|
112
|
+
declare function isPocFlexRow(node: Node): boolean;
|
|
113
|
+
/** conteúdo visível = texto, imagem com src preenchido ou svg (imgs vazias do pipeline não contam) */
|
|
114
|
+
declare function pocNodeHasVisibleContent(node: Node): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* A célula/linha PINTA alguma coisa (borda ou fundo)?
|
|
117
|
+
*
|
|
118
|
+
* Uma coluna sem texto mas com borda não é espaço sobrando: é estrutura. A
|
|
119
|
+
* folha de rosto da Telefônica desenha uma timeline com `border-right` numa
|
|
120
|
+
* coluna VAZIA (o eixo central) e `border-bottom` alternando entre as duas —
|
|
121
|
+
* colapsar a coluna "vazia" apaga o eixo e centraliza o que devia ficar
|
|
122
|
+
* alternando esquerda/direita.
|
|
123
|
+
*/
|
|
124
|
+
declare function pocNodePaintsBox(node: Node): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Índice da única célula com conteúdo da linha, ou null se a linha não pode
|
|
127
|
+
* ser colapsada. Fonte única da regra: o preview (decorations .poc-lone-row)
|
|
128
|
+
* e o export DOCX chamam esta função — se divergirem, o Word deixa de bater
|
|
129
|
+
* com a tela.
|
|
130
|
+
*/
|
|
131
|
+
declare function pocLoneCellIndex(row: Node): number | null;
|
|
132
|
+
interface PocLoneRow {
|
|
133
|
+
rowFrom: number;
|
|
134
|
+
rowTo: number;
|
|
135
|
+
cellFrom: number;
|
|
136
|
+
cellTo: number;
|
|
137
|
+
}
|
|
138
|
+
declare function computePocLoneRows(doc: Node): PocLoneRow[];
|
|
139
|
+
declare function breaksEqual(a: PocPageBreak[], b: PocPageBreak[]): boolean;
|
|
140
|
+
declare function PocPaginationPlugin(cfg: PocPageConfig): Plugin<PagState>;
|
|
141
|
+
|
|
142
|
+
interface PocDocxChrome {
|
|
143
|
+
headerText?: string;
|
|
144
|
+
footerText?: string;
|
|
145
|
+
headerLogoUrl?: string | null;
|
|
146
|
+
headerPosition?: 'left' | 'center' | 'right';
|
|
147
|
+
/** cabeçalho em todas as páginas ou só na primeira */
|
|
148
|
+
headerScope?: 'all' | 'first';
|
|
149
|
+
/** conteúdo custom do rodapé (o nº de página aparece sempre) */
|
|
150
|
+
footerScope?: 'all' | 'first';
|
|
151
|
+
/** numeração "Página N de M" no rodapé (default: ligada) */
|
|
152
|
+
showPageNumber?: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface PocDocxExportOptions {
|
|
155
|
+
/** quebras calculadas pelo engine de paginação do preview → paginação 1:1 */
|
|
156
|
+
breaks?: PocPageBreak[];
|
|
157
|
+
}
|
|
158
|
+
declare function pocExportDocx(editor: Editor, margins: {
|
|
159
|
+
top: number;
|
|
160
|
+
right: number;
|
|
161
|
+
bottom: number;
|
|
162
|
+
left: number;
|
|
163
|
+
}, chrome?: PocDocxChrome, options?: PocDocxExportOptions): Promise<Blob>;
|
|
164
|
+
|
|
165
|
+
export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, computePocBreaks as k, isPocFlexRow as l, pocNodeHasVisibleContent as m, pocNodePaintsBox as n, pocLoneCellIndex as o, pocPageKey as p, computePocLoneRows as r, breaksEqual as s, PocPaginationPlugin as t, pocExportDocx as u };
|
|
166
|
+
export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as q };
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
import { Node } from '@tiptap/pm/model';
|
|
3
|
+
import { EditorView } from '@tiptap/pm/view';
|
|
4
|
+
import { PluginKey, Plugin } from '@tiptap/pm/state';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Engine de paginação da PoC.
|
|
8
|
+
*
|
|
9
|
+
* O documento continua linear no ProseMirror; as "páginas" nascem de widget
|
|
10
|
+
* decorations ("chrome") inseridas ENTRE os nós internos dos blocos:
|
|
11
|
+
* cada chrome preenche o resto da área útil da página (filler), desenha o
|
|
12
|
+
* rodapé (nº da página) dentro da margem inferior, a faixa de separação
|
|
13
|
+
* entre páginas e o cabeçalho (logo do template) dentro da margem superior
|
|
14
|
+
* da página seguinte.
|
|
15
|
+
*
|
|
16
|
+
* A medição roda fora do plugin (componente agenda via rAF) em coordenadas
|
|
17
|
+
* de layout (offsetTop/offsetHeight — imunes ao CSS zoom da folha) e
|
|
18
|
+
* NORMALIZADAS: a altura de todo chrome existente é subtraída, então o
|
|
19
|
+
* algoritmo sempre enxerga o fluxo "sem paginação" e converge (recomputar
|
|
20
|
+
* com chrome na tela produz os mesmos breaks → sem loop de layout).
|
|
21
|
+
*
|
|
22
|
+
* Regras de quebra:
|
|
23
|
+
* - quebra somente entre nós (parágrafo/título/ilha) — nó mais alto que a
|
|
24
|
+
* página flui e as páginas internas são contadas, sem chrome no meio;
|
|
25
|
+
* - keep-with-next: título não fica órfão no fim da página (a quebra sobe
|
|
26
|
+
* para antes do título).
|
|
27
|
+
*/
|
|
28
|
+
interface PocPageConfig {
|
|
29
|
+
pageHeight: number;
|
|
30
|
+
margins: {
|
|
31
|
+
top: number;
|
|
32
|
+
right: number;
|
|
33
|
+
bottom: number;
|
|
34
|
+
left: number;
|
|
35
|
+
};
|
|
36
|
+
gap: number;
|
|
37
|
+
headerLogoUrl?: string | null;
|
|
38
|
+
headerPosition?: 'left' | 'center' | 'right';
|
|
39
|
+
/** texto editável do cabeçalho (ao lado do logo) */
|
|
40
|
+
headerText?: string;
|
|
41
|
+
/** texto editável do rodapé (lado esquerdo; o nº de página fica à direita) */
|
|
42
|
+
footerText?: string;
|
|
43
|
+
/** onde o conteúdo do cabeçalho aparece: todas as páginas ou só a primeira */
|
|
44
|
+
headerScope?: 'all' | 'first';
|
|
45
|
+
/** onde o conteúdo custom do rodapé aparece (o nº de página é sempre em todas) */
|
|
46
|
+
footerScope?: 'all' | 'first';
|
|
47
|
+
/** numeração "Página N de M" no rodapé — opcional por conjunto de cabeçalho */
|
|
48
|
+
showPageNumber?: boolean;
|
|
49
|
+
/** bump força a reconstrução do chrome (muda a key das decorations) */
|
|
50
|
+
version?: number;
|
|
51
|
+
}
|
|
52
|
+
/** nota de rodapé que cai numa página (o marcador está no corpo dela) */
|
|
53
|
+
interface PocPageNote {
|
|
54
|
+
n: number;
|
|
55
|
+
/** conteúdo em HTML de ênfase (b/i/u/br) — já sanitizado no render */
|
|
56
|
+
text: string;
|
|
57
|
+
/** corpo declarado no template, em pontos (default: 8pt, como o Word) */
|
|
58
|
+
size?: number | null;
|
|
59
|
+
/**
|
|
60
|
+
* posição do MARCADOR no documento. Só é usada para repartir as notas
|
|
61
|
+
* quando a quebra cai no meio do parágrafo: a nota mora na página da
|
|
62
|
+
* chamada, então as que ficam depois do corte viajam para a página nova.
|
|
63
|
+
*/
|
|
64
|
+
at?: number;
|
|
65
|
+
}
|
|
66
|
+
interface PocPageBreak {
|
|
67
|
+
pos: number;
|
|
68
|
+
filler: number;
|
|
69
|
+
pageNo: number;
|
|
70
|
+
/**
|
|
71
|
+
* quebra no MEIO de um parágrafo (entre linhas). O DOCX não recebe
|
|
72
|
+
* pageBreakBefore nessas: partir o parágrafo em dois no Word entregaria
|
|
73
|
+
* ao advogado um arquivo que não reflui quando ele edita o texto. Aqui o
|
|
74
|
+
* Word quebra naturalmente, e o preview só antecipa onde.
|
|
75
|
+
*/
|
|
76
|
+
soft?: boolean;
|
|
77
|
+
/** notas cujos marcadores estão nesta página — desenhadas acima do rodapé */
|
|
78
|
+
notes?: PocPageNote[];
|
|
79
|
+
/** altura reservada pelas notas (já descontada do filler) */
|
|
80
|
+
notesH?: number;
|
|
81
|
+
}
|
|
82
|
+
interface PagState {
|
|
83
|
+
breaks: PocPageBreak[];
|
|
84
|
+
total: number;
|
|
85
|
+
/** parágrafos-marcador "PAGEBREAK" (quebra manual do template) */
|
|
86
|
+
markers: {
|
|
87
|
+
from: number;
|
|
88
|
+
to: number;
|
|
89
|
+
}[];
|
|
90
|
+
}
|
|
91
|
+
declare const pocPageKey: PluginKey<PagState>;
|
|
92
|
+
declare const PAGINATE_META = "poc-paginate";
|
|
93
|
+
declare function pocChromeFlowHeight(cfg: PocPageConfig): number;
|
|
94
|
+
/**
|
|
95
|
+
* o chrome tem dois formatos: canvas (elementos posicionados, coordenadas no
|
|
96
|
+
* frame da PÁGINA — vem do editor estilo Word) e flow legado (texto corrido)
|
|
97
|
+
*/
|
|
98
|
+
declare function isPocChromeCanvas(html: string | undefined | null): boolean;
|
|
99
|
+
declare function buildPocHeaderEl(cfg: PocPageConfig): HTMLElement;
|
|
100
|
+
declare function buildPocFooterEl(cfg: PocPageConfig, pageNo: number, total: number): HTMLElement;
|
|
101
|
+
/** área de notas de rodapé: filete + notas, no pé da área útil (como no Word) */
|
|
102
|
+
declare function buildPocNotesEl(notes: PocPageNote[]): HTMLElement;
|
|
103
|
+
declare function computePocBreaks(view: EditorView, cfg: PocPageConfig, sheet: HTMLElement): {
|
|
104
|
+
breaks: PocPageBreak[];
|
|
105
|
+
total: number;
|
|
106
|
+
markers: {
|
|
107
|
+
from: number;
|
|
108
|
+
to: number;
|
|
109
|
+
}[];
|
|
110
|
+
lastNotes: PocPageNote[];
|
|
111
|
+
};
|
|
112
|
+
declare function isPocFlexRow(node: Node): boolean;
|
|
113
|
+
/** conteúdo visível = texto, imagem com src preenchido ou svg (imgs vazias do pipeline não contam) */
|
|
114
|
+
declare function pocNodeHasVisibleContent(node: Node): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* A célula/linha PINTA alguma coisa (borda ou fundo)?
|
|
117
|
+
*
|
|
118
|
+
* Uma coluna sem texto mas com borda não é espaço sobrando: é estrutura. A
|
|
119
|
+
* folha de rosto da Telefônica desenha uma timeline com `border-right` numa
|
|
120
|
+
* coluna VAZIA (o eixo central) e `border-bottom` alternando entre as duas —
|
|
121
|
+
* colapsar a coluna "vazia" apaga o eixo e centraliza o que devia ficar
|
|
122
|
+
* alternando esquerda/direita.
|
|
123
|
+
*/
|
|
124
|
+
declare function pocNodePaintsBox(node: Node): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Índice da única célula com conteúdo da linha, ou null se a linha não pode
|
|
127
|
+
* ser colapsada. Fonte única da regra: o preview (decorations .poc-lone-row)
|
|
128
|
+
* e o export DOCX chamam esta função — se divergirem, o Word deixa de bater
|
|
129
|
+
* com a tela.
|
|
130
|
+
*/
|
|
131
|
+
declare function pocLoneCellIndex(row: Node): number | null;
|
|
132
|
+
interface PocLoneRow {
|
|
133
|
+
rowFrom: number;
|
|
134
|
+
rowTo: number;
|
|
135
|
+
cellFrom: number;
|
|
136
|
+
cellTo: number;
|
|
137
|
+
}
|
|
138
|
+
declare function computePocLoneRows(doc: Node): PocLoneRow[];
|
|
139
|
+
declare function breaksEqual(a: PocPageBreak[], b: PocPageBreak[]): boolean;
|
|
140
|
+
declare function PocPaginationPlugin(cfg: PocPageConfig): Plugin<PagState>;
|
|
141
|
+
|
|
142
|
+
interface PocDocxChrome {
|
|
143
|
+
headerText?: string;
|
|
144
|
+
footerText?: string;
|
|
145
|
+
headerLogoUrl?: string | null;
|
|
146
|
+
headerPosition?: 'left' | 'center' | 'right';
|
|
147
|
+
/** cabeçalho em todas as páginas ou só na primeira */
|
|
148
|
+
headerScope?: 'all' | 'first';
|
|
149
|
+
/** conteúdo custom do rodapé (o nº de página aparece sempre) */
|
|
150
|
+
footerScope?: 'all' | 'first';
|
|
151
|
+
/** numeração "Página N de M" no rodapé (default: ligada) */
|
|
152
|
+
showPageNumber?: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface PocDocxExportOptions {
|
|
155
|
+
/** quebras calculadas pelo engine de paginação do preview → paginação 1:1 */
|
|
156
|
+
breaks?: PocPageBreak[];
|
|
157
|
+
}
|
|
158
|
+
declare function pocExportDocx(editor: Editor, margins: {
|
|
159
|
+
top: number;
|
|
160
|
+
right: number;
|
|
161
|
+
bottom: number;
|
|
162
|
+
left: number;
|
|
163
|
+
}, chrome?: PocDocxChrome, options?: PocDocxExportOptions): Promise<Blob>;
|
|
164
|
+
|
|
165
|
+
export { PAGINATE_META as e, pocChromeFlowHeight as f, buildPocHeaderEl as g, buildPocFooterEl as h, isPocChromeCanvas as i, buildPocNotesEl as j, computePocBreaks as k, isPocFlexRow as l, pocNodeHasVisibleContent as m, pocNodePaintsBox as n, pocLoneCellIndex as o, pocPageKey as p, computePocLoneRows as r, breaksEqual as s, PocPaginationPlugin as t, pocExportDocx as u };
|
|
166
|
+
export type { PocPageConfig as P, PocDocxChrome as a, PocDocxExportOptions as b, PocPageNote as c, PocPageBreak as d, PocLoneRow as q };
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.poc-editor-root .poc-ins{background:rgba(34,197,94,.16);text-decoration:underline;text-decoration-color:#16a34a}.poc-editor-root .poc-del{background:rgba(239,68,68,.12);color:#b91c1c;text-decoration:line-through}.poc-editor-root .poc-bubble-btn{border-radius:6px;font-size:13px;padding:4px 8px;transition:all .15s;transition-timing-function:ease}.poc-editor-root .poc-toolbar{align-items:center;display:flex;flex-wrap:wrap;gap:2px;padding:4px 12px}@media (max-width:640px){.poc-editor-root .poc-toolbar{flex-wrap:nowrap;overflow-x:auto;padding:4px 8px;scrollbar-width:none}.poc-editor-root .poc-toolbar::-webkit-scrollbar{display:none}.poc-editor-root .poc-toolbar>*{flex:none}}.poc-editor-root .poc-tool{align-items:center;border-radius:6px;display:flex;font-size:13px;height:28px;justify-content:center;min-width:28px;padding-left:6px;padding-right:6px;position:relative;transition:all .15s;transition-timing-function:ease}.poc-editor-root .poc-tool-sep{background:#dee3e7;height:20px;margin:0 6px;width:1px}.poc-editor-root .poc-tool-select{border-radius:6px;font-size:12px;height:28px;padding-left:6px;padding-right:6px}.poc-editor-root .poc-color-underline{background:#dc2626;border-radius:1px;bottom:4px;height:3px;left:7px;position:absolute;right:7px}.poc-editor-root .poc-palette{background:#fff;border:.5px solid #dee3e7;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.12);display:flex;flex-wrap:wrap;gap:2px;left:0;padding:8px;position:absolute;top:32px;width:230px;z-index:50}.poc-editor-root .poc-palette-swatch{border:1px solid rgba(0,0,0,.1);border-radius:3px;cursor:pointer;height:19px;width:19px}.poc-editor-root .poc-palette-swatch:hover{transform:scale(1.2)}.poc-editor-root .poc-palette-custom{align-items:center;color:#565d69;cursor:pointer;display:flex;font-size:12px;margin-top:6px;width:100%}.poc-editor-root .poc-color-swatch{border:1px solid rgba(0,0,0,.12);border-radius:4px;cursor:pointer;height:16px;margin:0 2px;width:16px}.poc-editor-root .poc-color-swatch:hover{transform:scale(1.15)}.poc-editor-root .poc-first-header{align-items:center;cursor:pointer;display:flex;gap:12px;position:absolute;top:0}.poc-editor-root .poc-first-header[style*=center]{justify-content:center}.poc-editor-root .poc-first-header[style*=right]{justify-content:flex-end}.poc-editor-root .poc-first-header:hover,.poc-editor-root .poc-last-footer:hover,.poc-editor-root .poc-page-footerarea:hover,.poc-editor-root .poc-page-headerarea:hover{background:rgba(99,102,241,.06);outline:1px dashed #c7d2fe}.poc-editor-root .poc-last-footer{align-items:center;bottom:0;color:#94a3b8;cursor:pointer;display:flex;font-size:11px;justify-content:space-between;position:absolute}.poc-editor-root .poc-chrome-text{color:#64748b;font-size:11px}.poc-editor-root .poc-chrome-text img{display:inline-block;max-height:48px;max-width:200px;vertical-align:middle}.poc-editor-root .poc-pagebreak-marker{border-top:1px dashed #a5b4fc;font-size:0!important;height:16px;line-height:0!important;margin:6px 0!important;position:relative}.poc-editor-root .poc-pagebreak-marker:after{background:#fff;color:#818cf8;content:"quebra de página do template";font-size:10px;left:50%;line-height:16px;padding:0 8px;position:absolute;top:-8px;transform:translateX(-50%)}.poc-editor-root .poc-page-chrome{display:block;pointer-events:none;text-align:initial;text-indent:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.poc-editor-root .poc-page-footerarea,.poc-editor-root .poc-page-headerarea{cursor:pointer;pointer-events:auto}.poc-editor-root .poc-page-footerarea{align-items:center;color:#94a3b8;display:flex;font-size:11px;justify-content:space-between}.poc-editor-root .poc-page-gapband{background:#eceef1;box-shadow:inset 0 6px 6px -6px rgba(0,0,0,.25),inset 0 -6px 6px -6px rgba(0,0,0,.25)}.poc-editor-root .poc-page-headerarea{align-items:center;display:flex}.poc-editor-root .poc-page-headerarea[style*=center]{justify-content:center}.poc-editor-root .poc-page-headerarea[style*=right]{justify-content:flex-end}.poc-editor-root .ProseMirror{white-space:pre-wrap;word-wrap:break-word}.poc-editor-root h1{color:#0f172a;font-size:24px;font-weight:640;letter-spacing:-.3px;line-height:32px;margin:0 0 20px}.poc-editor-root h2{color:#0f172a;font-size:19px;font-weight:620;letter-spacing:-.2px;line-height:26px;margin:28px 0 14px}.poc-editor-root h3{color:#0f172a;font-size:17px;font-weight:600;letter-spacing:-.1px;line-height:24px;margin:24px 0 12px}.poc-editor-root h1:first-child,.poc-editor-root h2:first-child,.poc-editor-root h3:first-child{margin-top:0}.poc-editor-root strong{font-weight:540}.poc-editor-root p{color:#000;line-height:28px;line-height:1.7em;margin-bottom:.75em;text-align:justify}.poc-editor-root blockquote,.poc-editor-root p{font-size:18px;font-weight:400;letter-spacing:-.4px}.poc-editor-root blockquote{line-height:28px;margin-bottom:2em;margin-left:35%}.poc-editor-root ol,.poc-editor-root ul{margin-bottom:2em}.poc-editor-root li{list-style-position:inside;margin-bottom:16px;margin-left:48px}.poc-editor-root ul>li{list-style-type:disc}.poc-editor-root ol>li{list-style-type:decimal}.poc-editor-root table{border:.5px solid #d4d9df;max-width:100%;table-layout:fixed;width:100%}.poc-editor-root th{font-weight:700}.poc-editor-root td,.poc-editor-root th{color:inherit;font-size:inherit;overflow-wrap:anywhere;padding:12px;text-align:left}.poc-editor-root td{line-height:inherit}.poc-editor-root td p,.poc-editor-root th p{color:inherit;font-size:inherit;line-height:inherit;margin-bottom:0}.poc-editor-root img{display:block;max-width:100%}.poc-editor-root .poc-island--img>img,.poc-editor-root .poc-island>img:only-child{margin-left:auto;margin-right:auto}.poc-editor-root .poc-chrome-canvas{overflow:hidden}.poc-editor-root .poc-chrome-canvas [data-el]{position:absolute}.poc-editor-root .poc-chrome-canvas [data-el=text]{color:#64748b;font-size:11px;line-height:1.4;text-align:left;white-space:pre-wrap}.poc-editor-root img[data-vault-src]{animation:poc-img-loading 1.4s ease-in-out infinite}@keyframes poc-img-loading{0%,to{opacity:.5}50%{opacity:.9}}.poc-editor-root .poc-lone-row{justify-content:center!important}.poc-editor-root .poc-lone-row>:not(.poc-lone-cell){flex:0 0 0!important;min-width:0!important;padding:0!important}.poc-editor-root .poc-lone-row>.poc-lone-cell{align-items:center!important;flex:0 0 auto!important;max-width:100%;min-width:0}.poc-editor-root [data-horizontal-align=left] .poc-island--img>img,.poc-editor-root [data-horizontal-align=left] .poc-island>img:only-child{margin-left:0}.poc-editor-root [data-horizontal-align=right] .poc-island--img>img,.poc-editor-root [data-horizontal-align=right] .poc-island>img:only-child{margin-right:0}.poc-editor-root .poc-review-cursor .poc-minuta-block{cursor:pointer}.poc-editor-root .poc-minuta-block{border-radius:4px;position:relative}.poc-editor-root .poc-minuta-block:hover{outline:1px dashed #c7d2fe;outline-offset:6px}.poc-editor-root .poc-no-block-origin .poc-minuta-block:hover{outline:none}.poc-editor-root .poc-no-block-origin .poc-minuta-block:hover:before{content:none}.poc-editor-root .poc-minuta-block:hover:before{background:#eef2ff;border:1px solid #c7d2fe;border-radius:4px;color:#6366f1;content:attr(data-block-title);font-size:10px;letter-spacing:.04em;padding:1px 8px;pointer-events:none;position:absolute;right:0;text-transform:uppercase;top:-22px;z-index:3}.poc-editor-root .poc-varchip{background:rgba(59,130,246,.06);border-radius:3px;box-shadow:inset 0 0 0 1px rgba(59,130,246,.25);cursor:pointer;transition:background .15s ease}.poc-editor-root .poc-varchip:hover{background:rgba(59,130,246,.16)}.poc-editor-root .poc-tplvar{background:rgba(251,191,36,.16);border-radius:3px;box-shadow:inset 0 0 0 1px rgba(180,83,9,.35);color:#78350f;display:inline;padding:0 2px;white-space:pre-wrap}.poc-editor-root .poc-tplvar--unknown{background:rgba(244,63,94,.12);box-shadow:inset 0 0 0 1px rgba(190,18,60,.45);color:#881337;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.poc-editor-root .ProseMirror-selectednode.poc-tplvar{box-shadow:inset 0 0 0 2px rgba(180,83,9,.75)}.poc-editor-root .poc-missing-image .missing-image-warning:hover{background-color:rgba(254,174,0,.09);border-color:rgba(223,139,13,.85)}.poc-editor-root .poc-missing-image__remove{background:hsla(0,0%,100%,.75);border:none;border-radius:999px;color:#773613;cursor:pointer;font-size:16px;height:22px;line-height:1;opacity:0;position:absolute;right:4px;top:4px;transition:opacity .15s ease,background .15s ease;width:22px}.poc-editor-root .poc-missing-image:hover .poc-missing-image__remove{opacity:1}.poc-editor-root .poc-missing-image__remove:hover{background:rgba(254,174,0,.35)}.poc-editor-root .poc-missing-image.ProseMirror-selectednode .missing-image-warning{outline:2px solid rgba(223,139,13,.9);outline-offset:2px}.poc-editor-root .poc-page-notes{color:#1c242d;font-size:10.67px;line-height:1.25;padding-top:6px}.poc-editor-root .poc-page-notes:before{border-top:.5px solid #9aa4ae;content:"";display:block;margin-bottom:6px;width:30%}.poc-editor-root .poc-page-note{color:#1c242d;font-size:10.67px;font-weight:400;line-height:1.25;margin:0;text-align:justify}.poc-editor-root .poc-page-note sup{font-size:.8em;line-height:0;vertical-align:super}.poc-editor-root .poc-page-note a{color:#0563c1;text-decoration:underline}.poc-editor-root .poc-footnote{color:#1d4ed8;cursor:help;font-size:.7em;line-height:0;vertical-align:super}.poc-editor-root .poc-island{position:relative}.poc-editor-root .poc-island--img{cursor:grab}.poc-editor-root .poc-img-handle{background:#3b82f6;border:2px solid #fff;border-radius:3px;bottom:-6px;box-shadow:0 1px 3px rgba(0,0,0,.3);cursor:nwse-resize;height:12px;opacity:0;position:absolute;right:-6px;transition:opacity .12s ease;width:12px}.poc-editor-root .poc-island--img.ProseMirror-selectednode .poc-img-handle,.poc-editor-root .poc-island--img:hover .poc-img-handle{opacity:1}.poc-editor-root .poc-island.ProseMirror-selectednode{outline:2px solid #93c5fd;outline-offset:2px}.poc-editor-root .h-full{height:100%}.poc-editor-root .w-full{width:100%}.poc-editor-root .w-1px{width:1px}.poc-editor-root .w-64px{width:64px}.poc-editor-root .h-16px{height:16px}.poc-editor-root .flex{display:flex}.poc-editor-root .flex-col{flex-direction:column}.poc-editor-root .flex-1{flex:1 1 0%}.poc-editor-root .items-center{align-items:center}.poc-editor-root .gap-2px{gap:2px}.poc-editor-root .min-h-0{min-height:0}.poc-editor-root .overflow-y-auto{overflow-y:auto}.poc-editor-root .relative{position:relative}.poc-editor-root .hidden{display:none}.poc-editor-root .inline-block{display:inline-block}.poc-editor-root .align-middle{vertical-align:middle}.poc-editor-root .ml-auto{margin-left:auto}.poc-editor-root .mx-auto{margin-left:auto;margin-right:auto}.poc-editor-root .mx-2px{margin-left:2px;margin-right:2px}.poc-editor-root .p-2px{padding:2px}.poc-editor-root .py-24px{padding-bottom:24px;padding-top:24px}.poc-editor-root .bg-white{background:#fff}.poc-editor-root .bg-gray-120{background:#ebedf0}.poc-editor-root .bg-gray-200{background:#e5e7eb}.poc-editor-root .border{border-style:solid;border-width:1px}.poc-editor-root .border-gray-200{border-color:#e5e7eb}.poc-editor-root .rounded-8px{border-radius:8px}.poc-editor-root .shadow-md{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1)}.poc-editor-root .shadow-lg{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1)}.poc-editor-root .font-bold{font-weight:700}.poc-editor-root .font-semibold{font-weight:600}.poc-editor-root .italic{font-style:italic}.poc-editor-root .underline{text-decoration:underline}.poc-editor-root .line-through{text-decoration:line-through}.poc-editor-root .text-red-600{color:#dc2626}.poc-editor-root .body-13-regular{font-size:13px;font-weight:400}.poc-editor-root{font-family:Inter Variable,Inter,-apple-system,Segoe UI,Roboto,sans-serif}.poc-editor-root .poc-toolbar{background:#fafbfc;border-bottom:.5px solid #dee3e7}.poc-editor-root .poc-tool{background:transparent;border:none;cursor:pointer}.poc-editor-root .poc-tool:hover{background:#ebedf0}.poc-editor-root .poc-tool--on{background:#e2e8f0}.poc-editor-root .poc-tool-select{background:#fff;border:.5px solid #d4d9df;cursor:pointer}.poc-editor-root .ProseMirror{outline:none}.poc-editor-root td,.poc-editor-root th{border:.5px solid #d4d9df}.poc-editor-root .poc-footnote-pop{background:#fff;border:.5px solid #d4d9df;border-radius:10px;box-shadow:0 10px 25px -5px rgba(0,0,0,.18);padding:10px 12px;position:absolute;width:364px;z-index:40}.poc-editor-root .poc-footnote-pop__head{color:#6b7280;font-size:11px;font-weight:650;letter-spacing:.04em;margin-bottom:6px;text-transform:uppercase}.poc-editor-root .poc-footnote-pop__toolbar{align-items:center;display:flex;gap:4px;margin-bottom:6px}.poc-editor-root .poc-footnote-pop__tool{background:transparent;border:none;border-radius:6px;color:#374151;cursor:pointer;font-size:12px;height:24px;width:24px}.poc-editor-root .poc-footnote-pop__tool:hover{background:rgba(28,36,45,.06)}.poc-editor-root .poc-footnote-pop__sep{background:#e5e7eb;height:16px;margin:0 2px;width:1px}.poc-editor-root .poc-footnote-pop__select{background:#fff;border:1px solid #e5e7eb;border-radius:6px;color:#374151;font-size:11px;height:24px;max-width:108px;outline:none}.poc-editor-root .poc-footnote-pop__select--narrow{max-width:58px}.poc-editor-root .poc-footnote-pop__swatch{border:1px solid rgba(0,0,0,.15);border-radius:4px;cursor:pointer;height:14px;padding:0;width:14px}.poc-editor-root .poc-footnote-pop__input{border:1px solid #e5e7eb;border-radius:8px;color:#111827;font-size:12.5px;line-height:1.5;max-height:160px;min-height:58px;outline:none;overflow-y:auto;padding:6px 8px;width:100%}.poc-editor-root .poc-footnote-pop__input:focus{border-color:#a5b4fc}.poc-editor-root .poc-footnote-pop__input:empty:before{color:#9ca3af;content:attr(data-placeholder)}.poc-editor-root .poc-footnote-pop__actions{align-items:center;display:flex;gap:8px;margin-top:8px}.poc-editor-root .poc-footnote-pop__spacer{flex:1}.poc-editor-root .poc-footnote-pop__actions button{background:transparent;border:none;border-radius:8px;color:#565d69;cursor:pointer;font-size:12px;font-weight:500;padding:4px 12px}.poc-editor-root .poc-footnote-pop__remove{color:#b91c1c!important}.poc-editor-root .poc-footnote-pop__save{background:rgba(0,0,0,.88)!important;color:#fff!important}.poc-editor-root{display:flex;flex-direction:column;height:100%;width:100%}.poc-editor-root .w-118px{width:118px}.poc-editor-root .poc-varpicker{background:#fff;border:1px solid #e5e7eb;border-radius:10px;box-shadow:0 12px 24px -8px rgba(0,0,0,.25);display:flex;flex-direction:column;font-size:13px;max-height:300px;overflow:hidden;position:absolute;width:320px;z-index:60}.poc-editor-root .poc-varpicker__search{border:0;border-bottom:1px solid #f3f4f6;font-family:inherit;font-size:13px;outline:none;padding:10px 12px}.poc-editor-root .poc-varpicker__hint{border-bottom:1px solid #f3f4f6;color:#6b7280;font-size:12px;padding:8px 12px}.poc-editor-root .poc-varpicker__list{flex:1;min-height:0;overflow-y:auto;padding:4px}.poc-editor-root .poc-varpicker__empty{color:#6b7280;font-size:12px;margin:0;padding:12px}.poc-editor-root .poc-varpicker__group{color:#9ca3af;font-size:11px;font-weight:600;letter-spacing:.04em;padding:8px 8px 4px;text-transform:uppercase}.poc-editor-root .poc-varpicker__item{background:none;border:0;border-radius:6px;cursor:pointer;display:grid;font-family:inherit;gap:2px 8px;grid-template-columns:1fr auto;padding:6px 8px;text-align:left;width:100%}.poc-editor-root .poc-varpicker__item--on{background:#f3f4f6}.poc-editor-root .poc-varpicker__label{color:#111827;font-weight:500}.poc-editor-root .poc-varpicker__key{color:#9ca3af;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.poc-editor-root .poc-varpicker__desc{color:#6b7280;display:-webkit-box;font-size:11px;grid-column:1/-1;-webkit-line-clamp:2;line-height:1.4;overflow:hidden;-webkit-box-orient:vertical}.poc-editor-root [hidden]{display:none!important}.poc-editor-root .poc-varchip--flash{background:rgba(59,130,246,.35);transition:background .9s ease}
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meistrari/minuta-editor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Editor de minuta do defesa.ai sem framework: folha A4 paginada, edição rica, placeholders de variável e export DOCX fiel ao preview — monta em qualquer app (React, Vue, vanilla)",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/meistrari/case-defense-builder.git",
|
|
8
|
+
"directory": "packages/minuta-editor"
|
|
9
|
+
},
|
|
10
|
+
"license": "UNLICENSED",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"*.css"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.mts",
|
|
18
|
+
"import": "./dist/index.mjs"
|
|
19
|
+
},
|
|
20
|
+
"./docx": {
|
|
21
|
+
"types": "./dist/docx.d.mts",
|
|
22
|
+
"import": "./dist/docx.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./style.css": "./dist/style.css"
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.mjs",
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"prepack": "bun run build",
|
|
33
|
+
"build": "unbuild && node scripts/add-type-refs.mjs",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"test:pack": "node scripts/verify-pack.mjs"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@tiptap/core": "2.11.9",
|
|
39
|
+
"@tiptap/extension-blockquote": "2.11.9",
|
|
40
|
+
"@tiptap/extension-bold": "2.11.9",
|
|
41
|
+
"@tiptap/extension-bubble-menu": "2.11.9",
|
|
42
|
+
"@tiptap/extension-bullet-list": "2.11.9",
|
|
43
|
+
"@tiptap/extension-code": "2.11.9",
|
|
44
|
+
"@tiptap/extension-code-block": "2.11.9",
|
|
45
|
+
"@tiptap/extension-dropcursor": "2.11.9",
|
|
46
|
+
"@tiptap/extension-gapcursor": "2.11.9",
|
|
47
|
+
"@tiptap/extension-hard-break": "2.11.9",
|
|
48
|
+
"@tiptap/extension-heading": "2.11.9",
|
|
49
|
+
"@tiptap/extension-history": "2.11.9",
|
|
50
|
+
"@tiptap/extension-horizontal-rule": "2.11.9",
|
|
51
|
+
"@tiptap/extension-italic": "2.11.9",
|
|
52
|
+
"@tiptap/extension-list-item": "2.11.9",
|
|
53
|
+
"@tiptap/extension-ordered-list": "2.11.9",
|
|
54
|
+
"@tiptap/extension-paragraph": "2.11.9",
|
|
55
|
+
"@tiptap/extension-strike": "2.11.9",
|
|
56
|
+
"@tiptap/extension-table": "2.11.9",
|
|
57
|
+
"@tiptap/extension-table-cell": "2.11.9",
|
|
58
|
+
"@tiptap/extension-table-header": "2.11.9",
|
|
59
|
+
"@tiptap/extension-table-row": "2.11.9",
|
|
60
|
+
"@tiptap/extension-text": "2.11.9",
|
|
61
|
+
"@tiptap/pm": "2.11.9",
|
|
62
|
+
"docx": "9.7.1",
|
|
63
|
+
"tippy.js": "6.3.7"
|
|
64
|
+
},
|
|
65
|
+
"overrides": {
|
|
66
|
+
"@tiptap/core": "2.11.9",
|
|
67
|
+
"@tiptap/pm": "2.11.9",
|
|
68
|
+
"@tiptap/extension-blockquote": "2.11.9",
|
|
69
|
+
"@tiptap/extension-bold": "2.11.9",
|
|
70
|
+
"@tiptap/extension-bubble-menu": "2.11.9",
|
|
71
|
+
"@tiptap/extension-bullet-list": "2.11.9",
|
|
72
|
+
"@tiptap/extension-code": "2.11.9",
|
|
73
|
+
"@tiptap/extension-code-block": "2.11.9",
|
|
74
|
+
"@tiptap/extension-document": "2.11.9",
|
|
75
|
+
"@tiptap/extension-dropcursor": "2.11.9",
|
|
76
|
+
"@tiptap/extension-floating-menu": "2.11.9",
|
|
77
|
+
"@tiptap/extension-gapcursor": "2.11.9",
|
|
78
|
+
"@tiptap/extension-hard-break": "2.11.9",
|
|
79
|
+
"@tiptap/extension-heading": "2.11.9",
|
|
80
|
+
"@tiptap/extension-history": "2.11.9",
|
|
81
|
+
"@tiptap/extension-horizontal-rule": "2.11.9",
|
|
82
|
+
"@tiptap/extension-italic": "2.11.9",
|
|
83
|
+
"@tiptap/extension-list-item": "2.11.9",
|
|
84
|
+
"@tiptap/extension-ordered-list": "2.11.9",
|
|
85
|
+
"@tiptap/extension-paragraph": "2.11.9",
|
|
86
|
+
"@tiptap/extension-strike": "2.11.9",
|
|
87
|
+
"@tiptap/extension-text": "2.11.9",
|
|
88
|
+
"@tiptap/extension-text-style": "2.11.9"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"typescript": "5.9.3",
|
|
92
|
+
"unbuild": "2.0.0"
|
|
93
|
+
},
|
|
94
|
+
"publishConfig": {
|
|
95
|
+
"access": "public"
|
|
96
|
+
}
|
|
97
|
+
}
|