@sofereditor/react 0.9.0 → 0.10.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/dist/index.cjs +74 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.js +76 -41
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -417,8 +417,15 @@ declare function NodeView({ block, index, children, fragment, tableFragment }: N
|
|
|
417
417
|
*
|
|
418
418
|
* Keys are stable on `${blockIndex}-${runningOffset}` so React reconciliation
|
|
419
419
|
* survives split/merge of runs under collaboration.
|
|
420
|
+
*
|
|
421
|
+
* `baseOffset` shifts every emitted `data-embed-offset` (and key) by a fixed
|
|
422
|
+
* amount. Needed when `delta` is only a SLICE of a larger model range — e.g.
|
|
423
|
+
* one line of a célula-lista, where each `<li>` gets its own line-local delta
|
|
424
|
+
* but `data-embed-offset` must stay in CELL coordinates (contract with
|
|
425
|
+
* `Editor.tsx`'s embed-selection and `ImageResizeOverlay`'s DOM query).
|
|
426
|
+
* Defaults to 0, which reproduces the old line-local numbering exactly.
|
|
420
427
|
*/
|
|
421
|
-
declare function renderInline(delta: DeltaOp[], keyPrefix: number | string): ReactNode;
|
|
428
|
+
declare function renderInline(delta: DeltaOp[], keyPrefix: number | string, baseOffset?: number): ReactNode;
|
|
422
429
|
|
|
423
430
|
interface EditorProviderProps {
|
|
424
431
|
editor: UseEditorResult;
|
|
@@ -512,10 +519,11 @@ declare function applyDomSelection(root: HTMLElement, modelSel: Selection): void
|
|
|
512
519
|
* com o marcador (número/símbolo) como texto literal dentro de um span
|
|
513
520
|
* `mso-list:Ignore`. `parseWordListLevel` + a exclusão desse span tratam isso.
|
|
514
521
|
*
|
|
515
|
-
* fontFamily é deliberadamente NUNCA emitida: a escola padroniza
|
|
516
|
-
* documento tem sua própria tipografia
|
|
517
|
-
* descarta `w:rFonts`). fontSize É
|
|
518
|
-
* modelo já suporta a mark, a barra já
|
|
522
|
+
* fontFamily é deliberadamente NUNCA emitida: a escola padroniza uma fonte só,
|
|
523
|
+
* definida no CSS (`.ed-root`) e cada documento tem sua própria tipografia
|
|
524
|
+
* (mesma decisão de `import-docx`, que descarta `w:rFonts`). fontSize É
|
|
525
|
+
* preservado (ver `parseFontSizePt`): o modelo já suporta a mark, a barra já
|
|
526
|
+
* tem controle de tamanho, e descartar o
|
|
519
527
|
* tamanho perdia informação real (título de 37.5pt colado do Google Docs saía
|
|
520
528
|
* do tamanho do corpo). Unidades que dependem do contexto de herança do
|
|
521
529
|
* documento de origem (em/rem/%/larger/smaller/medium) não são resolvíveis
|
package/dist/index.d.ts
CHANGED
|
@@ -417,8 +417,15 @@ declare function NodeView({ block, index, children, fragment, tableFragment }: N
|
|
|
417
417
|
*
|
|
418
418
|
* Keys are stable on `${blockIndex}-${runningOffset}` so React reconciliation
|
|
419
419
|
* survives split/merge of runs under collaboration.
|
|
420
|
+
*
|
|
421
|
+
* `baseOffset` shifts every emitted `data-embed-offset` (and key) by a fixed
|
|
422
|
+
* amount. Needed when `delta` is only a SLICE of a larger model range — e.g.
|
|
423
|
+
* one line of a célula-lista, where each `<li>` gets its own line-local delta
|
|
424
|
+
* but `data-embed-offset` must stay in CELL coordinates (contract with
|
|
425
|
+
* `Editor.tsx`'s embed-selection and `ImageResizeOverlay`'s DOM query).
|
|
426
|
+
* Defaults to 0, which reproduces the old line-local numbering exactly.
|
|
420
427
|
*/
|
|
421
|
-
declare function renderInline(delta: DeltaOp[], keyPrefix: number | string): ReactNode;
|
|
428
|
+
declare function renderInline(delta: DeltaOp[], keyPrefix: number | string, baseOffset?: number): ReactNode;
|
|
422
429
|
|
|
423
430
|
interface EditorProviderProps {
|
|
424
431
|
editor: UseEditorResult;
|
|
@@ -512,10 +519,11 @@ declare function applyDomSelection(root: HTMLElement, modelSel: Selection): void
|
|
|
512
519
|
* com o marcador (número/símbolo) como texto literal dentro de um span
|
|
513
520
|
* `mso-list:Ignore`. `parseWordListLevel` + a exclusão desse span tratam isso.
|
|
514
521
|
*
|
|
515
|
-
* fontFamily é deliberadamente NUNCA emitida: a escola padroniza
|
|
516
|
-
* documento tem sua própria tipografia
|
|
517
|
-
* descarta `w:rFonts`). fontSize É
|
|
518
|
-
* modelo já suporta a mark, a barra já
|
|
522
|
+
* fontFamily é deliberadamente NUNCA emitida: a escola padroniza uma fonte só,
|
|
523
|
+
* definida no CSS (`.ed-root`) e cada documento tem sua própria tipografia
|
|
524
|
+
* (mesma decisão de `import-docx`, que descarta `w:rFonts`). fontSize É
|
|
525
|
+
* preservado (ver `parseFontSizePt`): o modelo já suporta a mark, a barra já
|
|
526
|
+
* tem controle de tamanho, e descartar o
|
|
519
527
|
* tamanho perdia informação real (título de 37.5pt colado do Google Docs saía
|
|
520
528
|
* do tamanho do corpo). Unidades que dependem do contexto de herança do
|
|
521
529
|
* documento de origem (em/rem/%/larger/smaller/medium) não são resolvíveis
|
package/dist/index.js
CHANGED
|
@@ -94,6 +94,11 @@ function isWrapAnchorImg(n) {
|
|
|
94
94
|
function isPhantomEmbed(n) {
|
|
95
95
|
return n.nodeType === Node.ELEMENT_NODE && n.dataset.embedPhantom === "true";
|
|
96
96
|
}
|
|
97
|
+
function isCellLineBoundary(n) {
|
|
98
|
+
if (n.nodeType !== Node.ELEMENT_NODE) return false;
|
|
99
|
+
const line = n.dataset.cellLine;
|
|
100
|
+
return line != null && Number(line) > 0;
|
|
101
|
+
}
|
|
97
102
|
function indexInParent(n) {
|
|
98
103
|
const parent = n.parentNode;
|
|
99
104
|
if (!parent) return 0;
|
|
@@ -121,6 +126,7 @@ function textOffsetWithin(container, node, offsetInNode) {
|
|
|
121
126
|
let done = false;
|
|
122
127
|
function visit(n) {
|
|
123
128
|
if (done) return;
|
|
129
|
+
if (isCellLineBoundary(n)) offset += 1;
|
|
124
130
|
if (n === target) {
|
|
125
131
|
if (n.nodeType === Node.TEXT_NODE) {
|
|
126
132
|
offset += targetOff;
|
|
@@ -221,6 +227,7 @@ function locatePoint(root, pos) {
|
|
|
221
227
|
let remaining = Math.max(0, pos.offset - containerStart);
|
|
222
228
|
let result = null;
|
|
223
229
|
let lastImg = null;
|
|
230
|
+
let lastBoundary = null;
|
|
224
231
|
let lastText = null;
|
|
225
232
|
function visit(n) {
|
|
226
233
|
if (result) return;
|
|
@@ -232,6 +239,7 @@ function locatePoint(root, pos) {
|
|
|
232
239
|
}
|
|
233
240
|
remaining -= len;
|
|
234
241
|
lastImg = null;
|
|
242
|
+
lastBoundary = null;
|
|
235
243
|
lastText = n;
|
|
236
244
|
return;
|
|
237
245
|
}
|
|
@@ -239,6 +247,25 @@ function locatePoint(root, pos) {
|
|
|
239
247
|
const el = n;
|
|
240
248
|
if (isRejectedSubtree(el, container)) return;
|
|
241
249
|
if (isImgEmbed(el) && isWrapAnchorImg(el)) return;
|
|
250
|
+
if (isCellLineBoundary(el)) {
|
|
251
|
+
if (remaining === 0) {
|
|
252
|
+
if (lastImg) {
|
|
253
|
+
const parent = lastImg.parentNode;
|
|
254
|
+
if (parent) {
|
|
255
|
+
result = { node: parent, offset: indexInParent(lastImg) + 1 };
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const prevLine = lastBoundary ?? el.previousElementSibling;
|
|
260
|
+
if (prevLine) {
|
|
261
|
+
result = { node: prevLine, offset: 0 };
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
remaining -= 1;
|
|
266
|
+
lastBoundary = el;
|
|
267
|
+
lastImg = null;
|
|
268
|
+
}
|
|
242
269
|
if (isImgEmbed(el) || isPhantomEmbed(el)) {
|
|
243
270
|
if (remaining === 0) {
|
|
244
271
|
const parent = el.parentNode;
|
|
@@ -249,6 +276,7 @@ function locatePoint(root, pos) {
|
|
|
249
276
|
}
|
|
250
277
|
remaining -= 1;
|
|
251
278
|
lastImg = el;
|
|
279
|
+
lastBoundary = null;
|
|
252
280
|
return;
|
|
253
281
|
}
|
|
254
282
|
for (const child of Array.from(el.childNodes)) {
|
|
@@ -258,7 +286,10 @@ function locatePoint(root, pos) {
|
|
|
258
286
|
}
|
|
259
287
|
visit(container);
|
|
260
288
|
if (result) return result;
|
|
261
|
-
if (
|
|
289
|
+
if (lastBoundary) {
|
|
290
|
+
return { node: lastBoundary, offset: 0 };
|
|
291
|
+
}
|
|
292
|
+
if (lastImg) {
|
|
262
293
|
const parent = lastImg.parentNode;
|
|
263
294
|
if (parent) return { node: parent, offset: indexInParent(lastImg) + 1 };
|
|
264
295
|
}
|
|
@@ -2815,7 +2846,9 @@ import { useMemo as useMemo2, useRef as useRef8 } from "react";
|
|
|
2815
2846
|
import {
|
|
2816
2847
|
answerLineStyle,
|
|
2817
2848
|
cellBorderStyle,
|
|
2849
|
+
deltaLength as deltaLength2,
|
|
2818
2850
|
normalizarLarguras as normalizarLarguras2,
|
|
2851
|
+
splitDeltaByLines,
|
|
2819
2852
|
tableRectSelection
|
|
2820
2853
|
} from "@sofereditor/core";
|
|
2821
2854
|
|
|
@@ -2827,11 +2860,11 @@ import {
|
|
|
2827
2860
|
splitUnderscoreRuns
|
|
2828
2861
|
} from "@sofereditor/core";
|
|
2829
2862
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2830
|
-
function renderInline(delta, keyPrefix) {
|
|
2863
|
+
function renderInline(delta, keyPrefix, baseOffset = 0) {
|
|
2831
2864
|
if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
|
|
2832
2865
|
return /* @__PURE__ */ jsx10("br", { "data-empty": "true" });
|
|
2833
2866
|
}
|
|
2834
|
-
let offset =
|
|
2867
|
+
let offset = baseOffset;
|
|
2835
2868
|
const wrapAnchors = [];
|
|
2836
2869
|
const body = [];
|
|
2837
2870
|
for (const op of delta) {
|
|
@@ -3499,6 +3532,27 @@ function clampListLevel(l) {
|
|
|
3499
3532
|
if (typeof l !== "number" || !Number.isFinite(l)) return 0;
|
|
3500
3533
|
return Math.max(0, Math.min(5, Math.trunc(l)));
|
|
3501
3534
|
}
|
|
3535
|
+
function renderCellContent(attrs, delta, keyPrefix) {
|
|
3536
|
+
const kind = attrs?.listKind;
|
|
3537
|
+
if (!kind) return renderInline(delta, keyPrefix);
|
|
3538
|
+
const linhas = splitDeltaByLines(delta);
|
|
3539
|
+
const Tag = kind === "ordered" ? "ol" : "ul";
|
|
3540
|
+
let baseOffset = 0;
|
|
3541
|
+
return /* @__PURE__ */ jsx12(
|
|
3542
|
+
Tag,
|
|
3543
|
+
{
|
|
3544
|
+
className: `ed-list ed-list-${kind}`,
|
|
3545
|
+
"data-list-kind": kind,
|
|
3546
|
+
start: kind === "ordered" && typeof attrs?.listStart === "number" ? attrs.listStart : void 0,
|
|
3547
|
+
style: attrs?.listStyle ? { listStyleType: attrs.listStyle } : void 0,
|
|
3548
|
+
children: linhas.map((linha, i) => {
|
|
3549
|
+
const li = /* @__PURE__ */ jsx12("li", { className: "ed-listitem", "data-cell-line": i, children: renderInline(linha, `${keyPrefix}-l${i}`, baseOffset) }, i);
|
|
3550
|
+
baseOffset += deltaLength2(linha) + 1;
|
|
3551
|
+
return li;
|
|
3552
|
+
})
|
|
3553
|
+
}
|
|
3554
|
+
);
|
|
3555
|
+
}
|
|
3502
3556
|
function TableView({ block, index, tableFragment }) {
|
|
3503
3557
|
const rows = clampPositive(block.attrs.rows);
|
|
3504
3558
|
const cols = clampPositive(block.attrs.cols);
|
|
@@ -3564,7 +3618,7 @@ function TableView({ block, index, tableFragment }) {
|
|
|
3564
3618
|
)
|
|
3565
3619
|
),
|
|
3566
3620
|
className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
|
|
3567
|
-
children:
|
|
3621
|
+
children: renderCellContent(cell?.attrs, delta, `t${index}-c${flat}`)
|
|
3568
3622
|
},
|
|
3569
3623
|
c
|
|
3570
3624
|
);
|
|
@@ -4403,6 +4457,10 @@ function useEditor(opts = {}) {
|
|
|
4403
4457
|
const isListActive = useCallback7(
|
|
4404
4458
|
(kind) => {
|
|
4405
4459
|
const sel = selectionRef.current;
|
|
4460
|
+
if (sel.focus.cellIndex != null && doc.isTable(sel.focus.blockIndex)) {
|
|
4461
|
+
const real = doc.realCellIndex(sel.focus.blockIndex, sel.focus.cellIndex);
|
|
4462
|
+
return real != null && doc.getCellAttrs(sel.focus.blockIndex, real).listKind === kind;
|
|
4463
|
+
}
|
|
4406
4464
|
const { start, end } = orderedRange(sel);
|
|
4407
4465
|
for (let i = start.blockIndex; i <= end.blockIndex; i++) {
|
|
4408
4466
|
if (doc.getBlockType(i) !== "listItem") return false;
|
|
@@ -5844,7 +5902,6 @@ function TableBorderPanel({
|
|
|
5844
5902
|
|
|
5845
5903
|
// src/Toolbar.tsx
|
|
5846
5904
|
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
5847
|
-
var FONT_FAMILIES = ["Arial"];
|
|
5848
5905
|
var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
|
|
5849
5906
|
var BLOCK_OPTIONS = [
|
|
5850
5907
|
{ value: "paragraph", label: "Par\xE1grafo", type: "paragraph" },
|
|
@@ -5918,11 +5975,6 @@ function Toolbar({ className }) {
|
|
|
5918
5975
|
const onHighlightChange = (e) => {
|
|
5919
5976
|
setMark("highlight", e.target.value);
|
|
5920
5977
|
};
|
|
5921
|
-
const onFontFamilyChange = (e) => {
|
|
5922
|
-
const v = e.target.value;
|
|
5923
|
-
if (v === "") removeMark("fontFamily");
|
|
5924
|
-
else setMark("fontFamily", v);
|
|
5925
|
-
};
|
|
5926
5978
|
const onFontSizeChange = (e) => {
|
|
5927
5979
|
const v = e.target.value;
|
|
5928
5980
|
if (v === "") removeMark("fontSize");
|
|
@@ -5983,7 +6035,6 @@ function Toolbar({ className }) {
|
|
|
5983
6035
|
);
|
|
5984
6036
|
const colorValue = typeof active.color === "string" ? active.color : "#000000";
|
|
5985
6037
|
const highlightValue = typeof active.highlight === "string" ? active.highlight : "#fff176";
|
|
5986
|
-
const fontFamilyValue = typeof active.fontFamily === "string" ? active.fontFamily : "";
|
|
5987
6038
|
const fontSizeValue = typeof active.fontSize === "string" ? active.fontSize : "";
|
|
5988
6039
|
const blockValue = blockSelectValue(blockType, blockLevel);
|
|
5989
6040
|
const selectedEmbed = editor.getSelectedEmbed();
|
|
@@ -6082,36 +6133,20 @@ function Toolbar({ className }) {
|
|
|
6082
6133
|
}
|
|
6083
6134
|
)
|
|
6084
6135
|
] }),
|
|
6085
|
-
/* @__PURE__ */
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
children:
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
),
|
|
6100
|
-
/* @__PURE__ */ jsxs15(
|
|
6101
|
-
"select",
|
|
6102
|
-
{
|
|
6103
|
-
className: "ed-toolbar-select",
|
|
6104
|
-
value: fontSizeValue,
|
|
6105
|
-
onChange: onFontSizeChange,
|
|
6106
|
-
onMouseDown: stop,
|
|
6107
|
-
"aria-label": "Tamanho da fonte",
|
|
6108
|
-
children: [
|
|
6109
|
-
/* @__PURE__ */ jsx15("option", { value: "", children: "Tamanho\u2026" }),
|
|
6110
|
-
FONT_SIZES.map((s) => /* @__PURE__ */ jsx15("option", { value: s, children: s }, s))
|
|
6111
|
-
]
|
|
6112
|
-
}
|
|
6113
|
-
)
|
|
6114
|
-
] }),
|
|
6136
|
+
/* @__PURE__ */ jsx15(Group, { children: /* @__PURE__ */ jsxs15(
|
|
6137
|
+
"select",
|
|
6138
|
+
{
|
|
6139
|
+
className: "ed-toolbar-select",
|
|
6140
|
+
value: fontSizeValue,
|
|
6141
|
+
onChange: onFontSizeChange,
|
|
6142
|
+
onMouseDown: stop,
|
|
6143
|
+
"aria-label": "Tamanho da fonte",
|
|
6144
|
+
children: [
|
|
6145
|
+
/* @__PURE__ */ jsx15("option", { value: "", children: "Tamanho\u2026" }),
|
|
6146
|
+
FONT_SIZES.map((s) => /* @__PURE__ */ jsx15("option", { value: s, children: s }, s))
|
|
6147
|
+
]
|
|
6148
|
+
}
|
|
6149
|
+
) }),
|
|
6115
6150
|
/* @__PURE__ */ jsx15(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ jsx15(
|
|
6116
6151
|
"button",
|
|
6117
6152
|
{
|