@extend-ai/react-docx 0.6.5 → 0.6.6
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 +221 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +221 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12187,7 +12187,15 @@ var defaultStarterModel = {
|
|
|
12187
12187
|
headerSections: [],
|
|
12188
12188
|
footerSections: [],
|
|
12189
12189
|
paragraphStyles: [
|
|
12190
|
-
{
|
|
12190
|
+
{
|
|
12191
|
+
id: "Normal",
|
|
12192
|
+
name: "Body",
|
|
12193
|
+
isDefault: true,
|
|
12194
|
+
// Word's blank-document default body typeface. Without this the body
|
|
12195
|
+
// default fell through to a heading font / Times New Roman and did not
|
|
12196
|
+
// match the "Calibri" shown in the toolbar.
|
|
12197
|
+
runStyle: { fontFamily: "Calibri", fontSizePt: 11 }
|
|
12198
|
+
},
|
|
12191
12199
|
{
|
|
12192
12200
|
id: "Heading1",
|
|
12193
12201
|
name: "Heading 1",
|
|
@@ -12330,7 +12338,7 @@ function resolveDocumentInheritedFontFamily(model) {
|
|
|
12330
12338
|
return cssFontFamily(defaultStyleFontFamily);
|
|
12331
12339
|
}
|
|
12332
12340
|
const paragraphStyleFontFamily = paragraphStyles.find(
|
|
12333
|
-
(style) => Boolean(style.runStyle?.fontFamily?.trim())
|
|
12341
|
+
(style) => style.headingLevel === void 0 && Boolean(style.runStyle?.fontFamily?.trim())
|
|
12334
12342
|
)?.runStyle?.fontFamily;
|
|
12335
12343
|
if (paragraphStyleFontFamily) {
|
|
12336
12344
|
return cssFontFamily(paragraphStyleFontFamily);
|
|
@@ -14565,7 +14573,17 @@ function nodeAlreadyEndsAtExplicitPageBoundary(node) {
|
|
|
14565
14573
|
}
|
|
14566
14574
|
return paragraphHasExplicitPageBreak2(node) || paragraphHasPageBreakBefore2(node) || sectionBreakAfterParagraphStartsNewPage(node);
|
|
14567
14575
|
}
|
|
14576
|
+
var docxHardPageBreakStartNodeIndexesByModel = /* @__PURE__ */ new WeakMap();
|
|
14568
14577
|
function collectDocxHardPageBreakStartNodeIndexes(model) {
|
|
14578
|
+
const cached = docxHardPageBreakStartNodeIndexesByModel.get(model);
|
|
14579
|
+
if (cached) {
|
|
14580
|
+
return cached;
|
|
14581
|
+
}
|
|
14582
|
+
const result = computeDocxHardPageBreakStartNodeIndexes(model);
|
|
14583
|
+
docxHardPageBreakStartNodeIndexesByModel.set(model, result);
|
|
14584
|
+
return result;
|
|
14585
|
+
}
|
|
14586
|
+
function computeDocxHardPageBreakStartNodeIndexes(model) {
|
|
14569
14587
|
const breaks = collectTopLevelExplicitPageBreakStartNodeIndexes(model.nodes);
|
|
14570
14588
|
const sections = resolveDocumentSectionsFromMetadata(model.metadata);
|
|
14571
14589
|
for (let sectionIndex = 1; sectionIndex < sections.length; sectionIndex += 1) {
|
|
@@ -14589,7 +14607,17 @@ function collectDocxHardPageBreakStartNodeIndexes(model) {
|
|
|
14589
14607
|
}
|
|
14590
14608
|
return breaks;
|
|
14591
14609
|
}
|
|
14610
|
+
var docxSectionStartPageBreakNodeIndexesByModel = /* @__PURE__ */ new WeakMap();
|
|
14592
14611
|
function collectDocxSectionStartPageBreakNodeIndexes(model) {
|
|
14612
|
+
const cached = docxSectionStartPageBreakNodeIndexesByModel.get(model);
|
|
14613
|
+
if (cached) {
|
|
14614
|
+
return cached;
|
|
14615
|
+
}
|
|
14616
|
+
const result = computeDocxSectionStartPageBreakNodeIndexes(model);
|
|
14617
|
+
docxSectionStartPageBreakNodeIndexesByModel.set(model, result);
|
|
14618
|
+
return result;
|
|
14619
|
+
}
|
|
14620
|
+
function computeDocxSectionStartPageBreakNodeIndexes(model) {
|
|
14593
14621
|
const breaks = /* @__PURE__ */ new Set();
|
|
14594
14622
|
const sections = resolveDocumentSectionsFromMetadata(model.metadata);
|
|
14595
14623
|
for (let sectionIndex = 1; sectionIndex < sections.length; sectionIndex += 1) {
|
|
@@ -29986,6 +30014,8 @@ function DocxEditorViewer({
|
|
|
29986
30014
|
const fileDragDepthRef = React.useRef(0);
|
|
29987
30015
|
const tableDraftLayoutRefreshRafRef = React.useRef(null);
|
|
29988
30016
|
const activeRangeFlushFrameRef = React.useRef(null);
|
|
30017
|
+
const pendingEditableCaretRef = React.useRef(null);
|
|
30018
|
+
const pointerSelectionDragRef = React.useRef({ down: false, moved: false });
|
|
29989
30019
|
const deferredCollapsedSelectionSyncTimeoutRef = React.useRef(
|
|
29990
30020
|
null
|
|
29991
30021
|
);
|
|
@@ -34034,14 +34064,62 @@ function DocxEditorViewer({
|
|
|
34034
34064
|
});
|
|
34035
34065
|
}, [resolveParagraphBoundaryFromSelectionPoint]);
|
|
34036
34066
|
const setActiveRangeFromSelection = React.useCallback(() => {
|
|
34067
|
+
const session = editor.selectionSessionKind;
|
|
34068
|
+
const rootElement = viewerRootRef.current;
|
|
34069
|
+
const activeElement = document.activeElement;
|
|
34070
|
+
const editorHasFocus = Boolean(
|
|
34071
|
+
activeElement instanceof HTMLElement && activeElement.isContentEditable && rootElement && rootElement.contains(activeElement)
|
|
34072
|
+
);
|
|
34073
|
+
const liveSelection = window.getSelection();
|
|
34074
|
+
const anchorNode = liveSelection?.anchorNode ?? null;
|
|
34075
|
+
const collapsedElementAnchor = Boolean(
|
|
34076
|
+
liveSelection && liveSelection.isCollapsed && liveSelection.rangeCount > 0 && anchorNode && anchorNode.nodeType !== Node.TEXT_NODE
|
|
34077
|
+
);
|
|
34078
|
+
const selectionDropped = Boolean(
|
|
34079
|
+
editorHasFocus && (!liveSelection || liveSelection.rangeCount === 0)
|
|
34080
|
+
);
|
|
34081
|
+
if (collapsedElementAnchor || selectionDropped) {
|
|
34082
|
+
if (session === "keyboard" || session === "composition") {
|
|
34083
|
+
return;
|
|
34084
|
+
}
|
|
34085
|
+
const anchorElement = anchorNode instanceof Element ? anchorNode : anchorNode?.parentElement ?? null;
|
|
34086
|
+
const destroyedHost = anchorElement?.closest(
|
|
34087
|
+
"[data-docx-paragraph-host='true']"
|
|
34088
|
+
) ?? (editorHasFocus ? activeElement.closest(
|
|
34089
|
+
"[data-docx-paragraph-host='true']"
|
|
34090
|
+
) : null);
|
|
34091
|
+
const lastGoodRange = cloneTextRange(editor.activeTextRange);
|
|
34092
|
+
if (lastGoodRange && destroyedHost) {
|
|
34093
|
+
const normalizedLastGood = normalizeTextRange(lastGoodRange);
|
|
34094
|
+
const lastGoodHost = resolveParagraphHostElement(
|
|
34095
|
+
normalizedLastGood.start.location
|
|
34096
|
+
);
|
|
34097
|
+
if (lastGoodHost === destroyedHost) {
|
|
34098
|
+
setSelectionFromDocxBoundaries(
|
|
34099
|
+
normalizedLastGood.start,
|
|
34100
|
+
normalizedLastGood.end
|
|
34101
|
+
);
|
|
34102
|
+
}
|
|
34103
|
+
}
|
|
34104
|
+
return;
|
|
34105
|
+
}
|
|
34037
34106
|
const range = resolveActiveRangeFromDomSelection();
|
|
34038
34107
|
if (!range) {
|
|
34108
|
+
if (editorHasFocus && editor.activeTextRange) {
|
|
34109
|
+
return;
|
|
34110
|
+
}
|
|
34039
34111
|
editor.setActiveTextRange(void 0);
|
|
34040
34112
|
return;
|
|
34041
34113
|
}
|
|
34042
34114
|
clearTableCellSelection();
|
|
34043
34115
|
editor.setActiveTextRange(range);
|
|
34044
|
-
}, [
|
|
34116
|
+
}, [
|
|
34117
|
+
clearTableCellSelection,
|
|
34118
|
+
editor,
|
|
34119
|
+
resolveActiveRangeFromDomSelection,
|
|
34120
|
+
resolveParagraphHostElement,
|
|
34121
|
+
setSelectionFromDocxBoundaries
|
|
34122
|
+
]);
|
|
34045
34123
|
const flushActiveRangeFromSelection = React.useCallback(() => {
|
|
34046
34124
|
if (deferredCollapsedSelectionSyncTimeoutRef.current !== null) {
|
|
34047
34125
|
window.clearTimeout(deferredCollapsedSelectionSyncTimeoutRef.current);
|
|
@@ -34055,6 +34133,73 @@ function DocxEditorViewer({
|
|
|
34055
34133
|
setActiveRangeFromSelection();
|
|
34056
34134
|
});
|
|
34057
34135
|
}, [setActiveRangeFromSelection]);
|
|
34136
|
+
React.useLayoutEffect(() => {
|
|
34137
|
+
if (isReadOnly) {
|
|
34138
|
+
return;
|
|
34139
|
+
}
|
|
34140
|
+
const session = editor.selectionSessionKind;
|
|
34141
|
+
if (pointerSelectionDragRef.current.moved || session === "composition") {
|
|
34142
|
+
return;
|
|
34143
|
+
}
|
|
34144
|
+
const rootElement = viewerRootRef.current;
|
|
34145
|
+
if (!rootElement) {
|
|
34146
|
+
return;
|
|
34147
|
+
}
|
|
34148
|
+
const activeElement = document.activeElement;
|
|
34149
|
+
if (!(activeElement instanceof HTMLElement) || !activeElement.isContentEditable || !rootElement.contains(activeElement)) {
|
|
34150
|
+
return;
|
|
34151
|
+
}
|
|
34152
|
+
const focusedHost = activeElement.closest(
|
|
34153
|
+
"[data-docx-paragraph-host='true']"
|
|
34154
|
+
);
|
|
34155
|
+
if (!focusedHost) {
|
|
34156
|
+
return;
|
|
34157
|
+
}
|
|
34158
|
+
const selection = window.getSelection();
|
|
34159
|
+
if (!selection) {
|
|
34160
|
+
return;
|
|
34161
|
+
}
|
|
34162
|
+
const liveRange = selection.rangeCount > 0 ? selection.getRangeAt(0) : void 0;
|
|
34163
|
+
const anchorNode = selection.anchorNode;
|
|
34164
|
+
const selectionInsideHost = Boolean(
|
|
34165
|
+
liveRange && focusedHost.contains(liveRange.startContainer) && focusedHost.contains(liveRange.endContainer)
|
|
34166
|
+
);
|
|
34167
|
+
const anchorIsElement = Boolean(
|
|
34168
|
+
anchorNode && anchorNode.nodeType !== Node.TEXT_NODE
|
|
34169
|
+
);
|
|
34170
|
+
const selectionWasDestroyed = !liveRange || !selectionInsideHost || selection.isCollapsed && anchorIsElement;
|
|
34171
|
+
if (!selectionWasDestroyed) {
|
|
34172
|
+
return;
|
|
34173
|
+
}
|
|
34174
|
+
const focusedNodeIndexAttr = focusedHost.getAttribute(
|
|
34175
|
+
"data-docx-paragraph-node-index"
|
|
34176
|
+
);
|
|
34177
|
+
const focusedNodeIndex = focusedNodeIndexAttr != null ? Number.parseInt(focusedNodeIndexAttr, 10) : Number.NaN;
|
|
34178
|
+
const pendingCaret = pendingEditableCaretRef.current;
|
|
34179
|
+
if (pendingCaret && Number.isFinite(focusedNodeIndex) && pendingCaret.nodeIndex === focusedNodeIndex) {
|
|
34180
|
+
const textLength = editableTextFromElement(focusedHost).length;
|
|
34181
|
+
const safeStart = Math.max(0, Math.min(pendingCaret.start, textLength));
|
|
34182
|
+
const safeEnd = Math.max(
|
|
34183
|
+
safeStart,
|
|
34184
|
+
Math.min(pendingCaret.end, textLength)
|
|
34185
|
+
);
|
|
34186
|
+
setSelectionWithinElementByTextOffsets(focusedHost, safeStart, safeEnd);
|
|
34187
|
+
return;
|
|
34188
|
+
}
|
|
34189
|
+
if (session === "keyboard") {
|
|
34190
|
+
return;
|
|
34191
|
+
}
|
|
34192
|
+
const range = editor.activeTextRange;
|
|
34193
|
+
if (!range) {
|
|
34194
|
+
return;
|
|
34195
|
+
}
|
|
34196
|
+
const normalized = normalizeTextRange(range);
|
|
34197
|
+
const targetHost = resolveParagraphHostElement(normalized.start.location);
|
|
34198
|
+
if (!targetHost || targetHost !== focusedHost) {
|
|
34199
|
+
return;
|
|
34200
|
+
}
|
|
34201
|
+
setSelectionFromDocxBoundaries(normalized.start, normalized.end);
|
|
34202
|
+
});
|
|
34058
34203
|
const selectionIsExpandedWithinElement = React.useCallback(
|
|
34059
34204
|
(element) => {
|
|
34060
34205
|
const selection = window.getSelection();
|
|
@@ -34508,6 +34653,28 @@ function DocxEditorViewer({
|
|
|
34508
34653
|
const collapsedCaretInsideEditableHost = Boolean(
|
|
34509
34654
|
selectionRange.collapsed && activeElement instanceof HTMLElement && activeElement.isContentEditable && rootElement.contains(activeElement) && activeElement.contains(selectionRange.startContainer)
|
|
34510
34655
|
);
|
|
34656
|
+
const selectionWithinSingleEditableHost = Boolean(
|
|
34657
|
+
activeElement instanceof HTMLElement && activeElement.isContentEditable && rootElement.contains(activeElement) && activeElement.contains(selectionRange.startContainer) && activeElement.contains(selectionRange.endContainer) && selectionRange.startContainer.nodeType === Node.TEXT_NODE && selectionRange.endContainer.nodeType === Node.TEXT_NODE
|
|
34658
|
+
);
|
|
34659
|
+
if (selectionWithinSingleEditableHost && activeElement instanceof HTMLElement) {
|
|
34660
|
+
const host = activeElement.closest(
|
|
34661
|
+
"[data-docx-paragraph-host='true']"
|
|
34662
|
+
);
|
|
34663
|
+
const nodeIndexAttr = host?.getAttribute(
|
|
34664
|
+
"data-docx-paragraph-node-index"
|
|
34665
|
+
);
|
|
34666
|
+
const offsets = host ? selectionOffsetsWithinElement(host) : void 0;
|
|
34667
|
+
if (host && nodeIndexAttr != null && offsets) {
|
|
34668
|
+
const nodeIndex = Number.parseInt(nodeIndexAttr, 10);
|
|
34669
|
+
if (Number.isFinite(nodeIndex)) {
|
|
34670
|
+
pendingEditableCaretRef.current = {
|
|
34671
|
+
nodeIndex,
|
|
34672
|
+
start: offsets.start,
|
|
34673
|
+
end: offsets.end
|
|
34674
|
+
};
|
|
34675
|
+
}
|
|
34676
|
+
}
|
|
34677
|
+
}
|
|
34511
34678
|
if (collapsedCaretInsideEditableHost) {
|
|
34512
34679
|
scheduleDeferredCollapsedSelectionSync();
|
|
34513
34680
|
return;
|
|
@@ -34519,6 +34686,27 @@ function DocxEditorViewer({
|
|
|
34519
34686
|
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
34520
34687
|
};
|
|
34521
34688
|
}, [flushActiveRangeFromSelection, scheduleDeferredCollapsedSelectionSync]);
|
|
34689
|
+
React.useEffect(() => {
|
|
34690
|
+
const onPointerDown = () => {
|
|
34691
|
+
pointerSelectionDragRef.current = { down: true, moved: false };
|
|
34692
|
+
};
|
|
34693
|
+
const onPointerMove = (event) => {
|
|
34694
|
+
if (pointerSelectionDragRef.current.down && event.buttons !== 0) {
|
|
34695
|
+
pointerSelectionDragRef.current.moved = true;
|
|
34696
|
+
}
|
|
34697
|
+
};
|
|
34698
|
+
const onPointerUp = () => {
|
|
34699
|
+
pointerSelectionDragRef.current = { down: false, moved: false };
|
|
34700
|
+
};
|
|
34701
|
+
window.addEventListener("pointerdown", onPointerDown, true);
|
|
34702
|
+
window.addEventListener("pointermove", onPointerMove, true);
|
|
34703
|
+
window.addEventListener("pointerup", onPointerUp, true);
|
|
34704
|
+
return () => {
|
|
34705
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
34706
|
+
window.removeEventListener("pointermove", onPointerMove, true);
|
|
34707
|
+
window.removeEventListener("pointerup", onPointerUp, true);
|
|
34708
|
+
};
|
|
34709
|
+
}, []);
|
|
34522
34710
|
const beginCrossNodeSelectionDrag = React.useCallback(
|
|
34523
34711
|
(startBoundary, pointerId, startX, startY) => {
|
|
34524
34712
|
tableSelectionDragRef.current = {
|
|
@@ -41946,6 +42134,18 @@ function DocxEditorViewer({
|
|
|
41946
42134
|
...leadingCoverLayoutSpacer ? {
|
|
41947
42135
|
minHeight: `${estimateParagraphLineHeightPx(node, nodeDocGridLinePitchPx) + EMPTY_PARAGRAPH_EXTRA_HEIGHT_PX + LEADING_COVER_SPACER_EXTRA_HEIGHT_PX}px`
|
|
41948
42136
|
} : void 0,
|
|
42137
|
+
// Carry the paragraph's run font on the editable host so text typed into
|
|
42138
|
+
// it (which is a bare, not-yet-committed text node, not a styled run
|
|
42139
|
+
// span) renders in the same font the committed run will use — i.e. the
|
|
42140
|
+
// font shown in the toolbar — instead of inheriting a generic default.
|
|
42141
|
+
// Rendered runs set their own font on their span, so this only affects
|
|
42142
|
+
// freshly typed/empty content. When the paragraph has no explicit run
|
|
42143
|
+
// font we leave it unset so the document default still applies.
|
|
42144
|
+
...(() => {
|
|
42145
|
+
const runStyle = firstRunStyle(node);
|
|
42146
|
+
const hostFontFamily = cssFontFamily(runStyle?.fontFamily);
|
|
42147
|
+
return hostFontFamily ? { fontFamily: hostFontFamily } : {};
|
|
42148
|
+
})(),
|
|
41949
42149
|
outline: "none"
|
|
41950
42150
|
};
|
|
41951
42151
|
let fallbackParagraphRuns;
|
|
@@ -42171,6 +42371,16 @@ function DocxEditorViewer({
|
|
|
42171
42371
|
if (!editable) {
|
|
42172
42372
|
return;
|
|
42173
42373
|
}
|
|
42374
|
+
const mouseUpOffsets = selectionOffsetsWithinElement(
|
|
42375
|
+
event.currentTarget
|
|
42376
|
+
);
|
|
42377
|
+
if (mouseUpOffsets) {
|
|
42378
|
+
pendingEditableCaretRef.current = {
|
|
42379
|
+
nodeIndex,
|
|
42380
|
+
start: mouseUpOffsets.start,
|
|
42381
|
+
end: mouseUpOffsets.end
|
|
42382
|
+
};
|
|
42383
|
+
}
|
|
42174
42384
|
if (selectionIsExpandedWithinElement(event.currentTarget)) {
|
|
42175
42385
|
flushActiveRangeFromSelection();
|
|
42176
42386
|
cancelPendingPointerSelectionReconcile();
|
|
@@ -42215,6 +42425,14 @@ function DocxEditorViewer({
|
|
|
42215
42425
|
nodeIndex,
|
|
42216
42426
|
event.currentTarget.innerHTML
|
|
42217
42427
|
);
|
|
42428
|
+
const typedOffsets = selectionOffsetsWithinElement(
|
|
42429
|
+
event.currentTarget
|
|
42430
|
+
);
|
|
42431
|
+
pendingEditableCaretRef.current = typedOffsets ? {
|
|
42432
|
+
nodeIndex,
|
|
42433
|
+
start: typedOffsets.start,
|
|
42434
|
+
end: typedOffsets.end
|
|
42435
|
+
} : null;
|
|
42218
42436
|
},
|
|
42219
42437
|
onCompositionStart: () => {
|
|
42220
42438
|
if (!editable) {
|