@extend-ai/react-docx 0.7.0-alpha.4 → 0.7.0-alpha.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.js CHANGED
@@ -1,16 +1,23 @@
1
1
  import {
2
2
  createMinimalDocxPackage,
3
3
  getPart,
4
- initWasm,
5
- mapsToWasmPackage,
6
4
  packageToArrayBuffer,
7
5
  parseDocx,
6
+ withPart
7
+ } from "./chunk-QOXSE6WY.js";
8
+ import {
9
+ buildDocModel,
10
+ buildDocModelFromBytes,
11
+ cloneDocModel,
12
+ normalizeDocModel
13
+ } from "./chunk-P3B3Q7Y6.js";
14
+ import {
15
+ initWasm,
16
+ mapsToWasmPackage,
8
17
  setWasmSource,
9
- wasmBuildDocModelFromPackage,
10
18
  wasmModelToDocumentXml,
11
- wasmSerializeDocx,
12
- withPart
13
- } from "./chunk-XLGR633U.js";
19
+ wasmSerializeDocx
20
+ } from "./chunk-2SXGXGWO.js";
14
21
 
15
22
  // src/index.tsx
16
23
  import * as React2 from "react";
@@ -237,413 +244,144 @@ function layoutDocument(model, options = {}) {
237
244
  return pages;
238
245
  }
239
246
 
240
- // ../doc-model/src/normalize.ts
241
- function normalizeUint8Array(value) {
242
- if (value instanceof Uint8Array) {
243
- return value;
244
- }
245
- if (Array.isArray(value)) {
246
- return Uint8Array.from(value);
247
- }
248
- return void 0;
247
+ // src/docx-import.ts
248
+ var nextImportWorkerRequestId = 1;
249
+ function createAbortError() {
250
+ if (typeof DOMException !== "undefined") {
251
+ return new DOMException("DOCX import was aborted", "AbortError");
252
+ }
253
+ const error = new Error("DOCX import was aborted");
254
+ error.name = "AbortError";
255
+ return error;
256
+ }
257
+ function errorFromWorkerResponse(response) {
258
+ const error = new Error(response.error.message);
259
+ error.name = response.error.name ?? "Error";
260
+ if (response.error.stack) {
261
+ error.stack = response.error.stack;
262
+ }
263
+ return error;
264
+ }
265
+ function canUseDocxImportWorker(options) {
266
+ return options.useWorker !== false && typeof Worker !== "undefined";
267
+ }
268
+ function createDocxImportWorker() {
269
+ return new Worker(new URL("./docx-import-worker.js", import.meta.url), {
270
+ type: "module",
271
+ name: "react-docx-import"
272
+ });
249
273
  }
250
- function normalizeParagraphChild(child) {
251
- if (child.type !== "image") {
252
- return child;
253
- }
254
- const image = child;
255
- const data = normalizeUint8Array(image.data);
256
- if (data === image.data) {
257
- return child;
274
+ async function importDocxOnMainThread(buffer, signal) {
275
+ if (signal?.aborted) {
276
+ throw createAbortError();
258
277
  }
259
- return {
260
- ...image,
261
- data
262
- };
263
- }
264
- function normalizeTableCellContent(node) {
265
- if (node.type === "table") {
266
- return normalizeDocNode(node);
278
+ const startedAt = performanceNow();
279
+ const [{ parseDocx: parseDocx2 }, { buildDocModel: buildDocModel2 }] = await Promise.all([
280
+ import("./src-PJYTN6DB.js"),
281
+ import("./src-NDPFDRVM.js")
282
+ ]);
283
+ const pkg = await parseDocx2(buffer);
284
+ const parsedAt = performanceNow();
285
+ if (signal?.aborted) {
286
+ throw createAbortError();
267
287
  }
268
- return {
269
- ...node,
270
- children: node.children.map(normalizeParagraphChild)
271
- };
272
- }
273
- function normalizeDocNode(node) {
274
- if (node.type === "paragraph") {
275
- return {
276
- ...node,
277
- children: node.children.map(normalizeParagraphChild)
278
- };
288
+ const model = await buildDocModel2(pkg);
289
+ const finishedAt = performanceNow();
290
+ if (signal?.aborted) {
291
+ throw createAbortError();
279
292
  }
280
293
  return {
281
- ...node,
282
- rows: node.rows.map((row) => ({
283
- ...row,
284
- cells: row.cells.map((cell) => ({
285
- ...cell,
286
- nodes: cell.nodes.map(normalizeTableCellContent)
287
- }))
288
- }))
289
- };
290
- }
291
- function normalizeDocModel(model) {
292
- return {
293
- ...model,
294
- nodes: model.nodes.map(normalizeDocNode),
295
- metadata: {
296
- ...model.metadata,
297
- headerSections: model.metadata.headerSections.map((section) => ({
298
- ...section,
299
- nodes: section.nodes.map(normalizeDocNode)
300
- })),
301
- footerSections: model.metadata.footerSections.map((section) => ({
302
- ...section,
303
- nodes: section.nodes.map(normalizeDocNode)
304
- })),
305
- sections: model.metadata.sections?.map((section) => ({
306
- ...section,
307
- headerSections: section.headerSections.map((header) => ({
308
- ...header,
309
- nodes: header.nodes.map(normalizeDocNode)
310
- })),
311
- footerSections: section.footerSections.map((footer) => ({
312
- ...footer,
313
- nodes: footer.nodes.map(normalizeDocNode)
314
- }))
315
- })),
316
- footnotes: model.metadata.footnotes?.map((note) => ({
317
- ...note,
318
- nodes: note.nodes?.map(normalizeDocNode)
319
- })),
320
- endnotes: model.metadata.endnotes?.map((note) => ({
321
- ...note,
322
- nodes: note.nodes?.map(normalizeDocNode)
323
- }))
294
+ package: pkg,
295
+ model,
296
+ source: "main-thread",
297
+ timings: {
298
+ totalMs: finishedAt - startedAt,
299
+ parseMs: parsedAt - startedAt,
300
+ buildModelMs: finishedAt - parsedAt
324
301
  }
325
302
  };
326
303
  }
327
-
328
- // ../doc-model/src/clone.ts
329
- function isParagraphCellContent(node) {
330
- return node.type === "paragraph";
331
- }
332
- function isTableCellContentTable(node) {
333
- return node.type === "table";
304
+ function performanceNow() {
305
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
334
306
  }
335
- function cloneTableCellContent(nodes) {
336
- return nodes.map((node) => {
337
- if (isParagraphCellContent(node)) {
338
- return cloneParagraph(node);
339
- }
340
- if (isTableCellContentTable(node)) {
341
- return cloneTable(node);
342
- }
343
- return node;
344
- });
345
- }
346
- function cloneParagraphNumbering(numbering) {
347
- return numbering ? { ...numbering } : void 0;
348
- }
349
- function cloneParagraphSpacing(spacing) {
350
- return spacing ? { ...spacing } : void 0;
351
- }
352
- function cloneParagraphIndent(indent) {
353
- return indent ? { ...indent } : void 0;
354
- }
355
- function cloneParagraphBorderStyle(border) {
356
- return border ? { ...border } : void 0;
357
- }
358
- function cloneParagraphBorderSet(borders) {
359
- if (!borders) {
360
- return void 0;
307
+ async function importDocxBuffer(buffer, options = {}) {
308
+ if (options.signal?.aborted) {
309
+ throw createAbortError();
361
310
  }
362
- return {
363
- top: cloneParagraphBorderStyle(borders.top),
364
- right: cloneParagraphBorderStyle(borders.right),
365
- bottom: cloneParagraphBorderStyle(borders.bottom),
366
- left: cloneParagraphBorderStyle(borders.left),
367
- between: cloneParagraphBorderStyle(borders.between),
368
- bar: cloneParagraphBorderStyle(borders.bar)
369
- };
370
- }
371
- function cloneParagraphStyle(style) {
372
- if (!style) {
373
- return void 0;
311
+ if (!canUseDocxImportWorker(options)) {
312
+ return importDocxOnMainThread(buffer, options.signal);
374
313
  }
375
- return {
376
- ...style,
377
- numbering: cloneParagraphNumbering(style.numbering),
378
- spacing: cloneParagraphSpacing(style.spacing),
379
- indent: cloneParagraphIndent(style.indent),
380
- borders: cloneParagraphBorderSet(style.borders),
381
- dropCap: style.dropCap ? {
382
- ...style.dropCap
383
- } : void 0
384
- };
385
- }
386
- function cloneParagraph(paragraph) {
387
- return {
388
- type: "paragraph",
389
- style: cloneParagraphStyle(paragraph.style),
390
- paragraphMarkDeleted: paragraph.paragraphMarkDeleted,
391
- sourceXml: paragraph.sourceXml,
392
- children: paragraph.children.map((child) => {
393
- if (child.type === "text") {
394
- return {
395
- type: "text",
396
- text: child.text,
397
- style: child.style ? { ...child.style } : void 0,
398
- link: child.link
399
- };
314
+ let worker;
315
+ try {
316
+ worker = createDocxImportWorker();
317
+ } catch {
318
+ return importDocxOnMainThread(buffer, options.signal);
319
+ }
320
+ const requestId = nextImportWorkerRequestId;
321
+ nextImportWorkerRequestId += 1;
322
+ return new Promise((resolve, reject) => {
323
+ let settled = false;
324
+ const cleanup = () => {
325
+ worker.removeEventListener("message", handleMessage);
326
+ worker.removeEventListener("error", handleError);
327
+ worker.removeEventListener("messageerror", handleMessageError);
328
+ options.signal?.removeEventListener("abort", handleAbort);
329
+ worker.terminate();
330
+ };
331
+ const settle = (resolver) => {
332
+ if (settled) {
333
+ return;
400
334
  }
401
- if (child.type === "form-field") {
402
- return {
403
- type: "form-field",
404
- fieldType: child.fieldType,
405
- sourceKind: child.sourceKind,
406
- id: child.id,
407
- tag: child.tag,
408
- title: child.title,
409
- placeholder: child.placeholder,
410
- checked: child.checked,
411
- value: child.value,
412
- options: child.options?.map((option) => ({
413
- displayText: option.displayText,
414
- value: option.value
415
- })),
416
- widget: child.widget ? {
417
- name: child.widget.name,
418
- enabled: child.widget.enabled,
419
- calcOnExit: child.widget.calcOnExit,
420
- text: child.widget.text ? {
421
- inputType: child.widget.text.inputType,
422
- defaultText: child.widget.text.defaultText,
423
- maxLength: child.widget.text.maxLength,
424
- textFormat: child.widget.text.textFormat
425
- } : void 0,
426
- checkbox: child.widget.checkbox ? {
427
- defaultChecked: child.widget.checkbox.defaultChecked,
428
- sizeMode: child.widget.checkbox.sizeMode,
429
- sizePt: child.widget.checkbox.sizePt
430
- } : void 0,
431
- dropdown: child.widget.dropdown ? {
432
- defaultValue: child.widget.dropdown.defaultValue
433
- } : void 0
434
- } : void 0,
435
- checkedSymbol: child.checkedSymbol,
436
- uncheckedSymbol: child.uncheckedSymbol,
437
- style: child.style ? { ...child.style } : void 0,
438
- link: child.link,
439
- sourceXml: child.sourceXml
440
- };
335
+ settled = true;
336
+ cleanup();
337
+ resolver();
338
+ };
339
+ const handleAbort = () => {
340
+ settle(() => reject(createAbortError()));
341
+ };
342
+ const handleError = (event) => {
343
+ const message = event.message || "DOCX import worker failed";
344
+ settle(() => reject(new Error(message)));
345
+ };
346
+ const handleMessageError = () => {
347
+ settle(() => reject(new Error("DOCX import worker returned an unreadable response")));
348
+ };
349
+ const handleMessage = (event) => {
350
+ const response = event.data;
351
+ if (!response || response.id !== requestId) {
352
+ return;
441
353
  }
442
- return {
443
- type: "image",
444
- src: child.src,
445
- alt: child.alt,
446
- widthPx: child.widthPx,
447
- heightPx: child.heightPx,
448
- partName: child.partName,
449
- contentType: child.contentType,
450
- data: child.data ? new Uint8Array(child.data) : void 0,
451
- sourceXml: child.sourceXml,
452
- crop: child.crop ? { ...child.crop } : void 0,
453
- cssFilter: child.cssFilter,
454
- cssOpacity: child.cssOpacity,
455
- floating: child.floating ? { ...child.floating } : void 0,
456
- syntheticTextBox: child.syntheticTextBox,
457
- textBoxText: child.textBoxText
354
+ if (response.type === "error") {
355
+ settle(() => reject(errorFromWorkerResponse(response)));
356
+ return;
357
+ }
358
+ settle(
359
+ () => resolve({
360
+ package: response.package,
361
+ model: response.model,
362
+ source: "worker",
363
+ timings: response.timings
364
+ })
365
+ );
366
+ };
367
+ worker.addEventListener("message", handleMessage);
368
+ worker.addEventListener("error", handleError);
369
+ worker.addEventListener("messageerror", handleMessageError);
370
+ options.signal?.addEventListener("abort", handleAbort, { once: true });
371
+ try {
372
+ const request = {
373
+ id: requestId,
374
+ type: "import-docx",
375
+ buffer
458
376
  };
459
- })
460
- };
461
- }
462
- function cloneTableBoxSpacing(spacing) {
463
- if (!spacing) {
464
- return void 0;
465
- }
466
- return {
467
- topTwips: spacing.topTwips,
468
- rightTwips: spacing.rightTwips,
469
- bottomTwips: spacing.bottomTwips,
470
- leftTwips: spacing.leftTwips
471
- };
472
- }
473
- function cloneTableBorderStyle(border) {
474
- if (!border) {
475
- return void 0;
476
- }
477
- return {
478
- type: border.type,
479
- color: border.color,
480
- sizeEighthPt: border.sizeEighthPt
481
- };
482
- }
483
- function cloneTableBorderSet(borders) {
484
- if (!borders) {
485
- return void 0;
486
- }
487
- return {
488
- top: cloneTableBorderStyle(borders.top),
489
- right: cloneTableBorderStyle(borders.right),
490
- bottom: cloneTableBorderStyle(borders.bottom),
491
- left: cloneTableBorderStyle(borders.left),
492
- insideH: cloneTableBorderStyle(borders.insideH),
493
- insideV: cloneTableBorderStyle(borders.insideV),
494
- tl2br: cloneTableBorderStyle(borders.tl2br),
495
- tr2bl: cloneTableBorderStyle(borders.tr2bl)
496
- };
497
- }
498
- function cloneTableFloatingStyle(floating) {
499
- if (!floating) {
500
- return void 0;
501
- }
502
- return {
503
- xTwips: floating.xTwips,
504
- yTwips: floating.yTwips,
505
- leftFromTextTwips: floating.leftFromTextTwips,
506
- rightFromTextTwips: floating.rightFromTextTwips,
507
- topFromTextTwips: floating.topFromTextTwips,
508
- bottomFromTextTwips: floating.bottomFromTextTwips,
509
- horizontalAnchor: floating.horizontalAnchor,
510
- verticalAnchor: floating.verticalAnchor,
511
- horizontalAlign: floating.horizontalAlign,
512
- verticalAlign: floating.verticalAlign
513
- };
514
- }
515
- function cloneTable(table) {
516
- return {
517
- type: "table",
518
- sourceXml: table.sourceXml,
519
- style: table.style ? {
520
- widthTwips: table.style.widthTwips,
521
- indentTwips: table.style.indentTwips,
522
- layout: table.style.layout,
523
- cellSpacingTwips: table.style.cellSpacingTwips,
524
- floating: cloneTableFloatingStyle(table.style.floating),
525
- cellMarginTwips: cloneTableBoxSpacing(table.style.cellMarginTwips),
526
- columnWidthsTwips: table.style.columnWidthsTwips ? [...table.style.columnWidthsTwips] : void 0,
527
- borders: cloneTableBorderSet(table.style.borders)
528
- } : void 0,
529
- rows: table.rows.map((row) => ({
530
- type: "table-row",
531
- style: row.style ? { ...row.style } : void 0,
532
- cells: row.cells.map((cell) => ({
533
- type: "table-cell",
534
- style: cell.style ? {
535
- ...cell.style,
536
- marginTwips: cloneTableBoxSpacing(cell.style.marginTwips),
537
- borders: cloneTableBorderSet(cell.style.borders)
538
- } : void 0,
539
- nodes: cloneTableCellContent(cell.nodes)
540
- }))
541
- }))
542
- };
543
- }
544
- function cloneDocNode(node) {
545
- return node.type === "paragraph" ? cloneParagraph(node) : cloneTable(node);
546
- }
547
- function cloneNumberingDefinitions(numberingDefinitions) {
548
- if (!numberingDefinitions) {
549
- return void 0;
550
- }
551
- return {
552
- abstracts: numberingDefinitions.abstracts.map((abstractDefinition) => ({
553
- abstractNumId: abstractDefinition.abstractNumId,
554
- levels: abstractDefinition.levels.map((level) => ({
555
- ...level,
556
- runStyle: level.runStyle ? { ...level.runStyle } : void 0,
557
- pictureBullet: level.pictureBullet ? { ...level.pictureBullet } : void 0
558
- }))
559
- })),
560
- instances: numberingDefinitions.instances.map((instanceDefinition) => ({
561
- numId: instanceDefinition.numId,
562
- abstractNumId: instanceDefinition.abstractNumId,
563
- levelStartOverrides: instanceDefinition.levelStartOverrides ? { ...instanceDefinition.levelStartOverrides } : void 0,
564
- levelOverrides: instanceDefinition.levelOverrides ? instanceDefinition.levelOverrides.map((level) => ({
565
- ...level,
566
- runStyle: level.runStyle ? { ...level.runStyle } : void 0,
567
- pictureBullet: level.pictureBullet ? { ...level.pictureBullet } : void 0
568
- })) : void 0
569
- }))
570
- };
571
- }
572
- function cloneDocModel(model) {
573
- return {
574
- nodes: model.nodes.map(cloneDocNode),
575
- metadata: {
576
- sourceParts: model.metadata.sourceParts,
577
- warnings: [...model.metadata.warnings],
578
- documentPageCount: model.metadata.documentPageCount,
579
- documentOpenTag: model.metadata.documentOpenTag,
580
- documentBackgroundColor: model.metadata.documentBackgroundColor,
581
- sectionPropertiesXml: model.metadata.sectionPropertiesXml,
582
- sections: model.metadata.sections?.map((section) => ({
583
- startNodeIndex: section.startNodeIndex,
584
- sectionPropertiesXml: section.sectionPropertiesXml,
585
- headerSections: (section.headerSections ?? []).map((headerSection) => ({
586
- partName: headerSection.partName,
587
- referenceType: headerSection.referenceType,
588
- nodes: headerSection.nodes.map(cloneDocNode)
589
- })),
590
- footerSections: (section.footerSections ?? []).map((footerSection) => ({
591
- partName: footerSection.partName,
592
- referenceType: footerSection.referenceType,
593
- nodes: footerSection.nodes.map(cloneDocNode)
594
- }))
595
- })),
596
- headerSections: (model.metadata.headerSections ?? []).map((section) => ({
597
- partName: section.partName,
598
- referenceType: section.referenceType,
599
- nodes: section.nodes.map(cloneDocNode)
600
- })),
601
- footerSections: (model.metadata.footerSections ?? []).map((section) => ({
602
- partName: section.partName,
603
- referenceType: section.referenceType,
604
- nodes: section.nodes.map(cloneDocNode)
605
- })),
606
- paragraphStyles: (model.metadata.paragraphStyles ?? []).map((style) => ({
607
- ...style,
608
- runStyle: style.runStyle ? { ...style.runStyle } : void 0,
609
- numbering: cloneParagraphNumbering(style.numbering),
610
- spacing: cloneParagraphSpacing(style.spacing),
611
- indent: cloneParagraphIndent(style.indent),
612
- borders: cloneParagraphBorderSet(style.borders)
613
- })),
614
- defaultParagraphStyleId: model.metadata.defaultParagraphStyleId,
615
- numberingDefinitions: cloneNumberingDefinitions(
616
- model.metadata.numberingDefinitions
617
- ),
618
- compatibility: model.metadata.compatibility ? { ...model.metadata.compatibility } : void 0,
619
- footnotes: model.metadata.footnotes?.map((note) => ({
620
- ...note,
621
- nodes: note.nodes?.map(cloneDocNode)
622
- })),
623
- endnotes: model.metadata.endnotes?.map((note) => ({
624
- ...note,
625
- nodes: note.nodes?.map(cloneDocNode)
626
- }))
377
+ const transfer = options.transferBuffer ? [buffer] : [];
378
+ worker.postMessage(request, transfer);
379
+ } catch (error) {
380
+ settle(
381
+ () => reject(error instanceof Error ? error : new Error("Failed to start DOCX import worker"))
382
+ );
627
383
  }
628
- };
629
- }
630
-
631
- // ../doc-model/src/index.ts
632
- async function buildDocModel(pkg) {
633
- const wasmPackage = mapsToWasmPackage({
634
- parts: pkg.parts,
635
- binaryAssets: pkg.binaryAssets
636
384
  });
637
- const model = await wasmBuildDocModelFromPackage(wasmPackage);
638
- return normalizeDocModel(model);
639
- }
640
- async function buildDocModelFromBytes(bytes) {
641
- const { parseDocx: parseDocx2 } = await import("./src-IT7QNDVM.js");
642
- const payload = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
643
- const buffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);
644
- const pkg = await parseDocx2(buffer);
645
- const model = await buildDocModel(pkg);
646
- return { package: pkg, model };
647
385
  }
648
386
 
649
387
  // src/section-layout.ts
@@ -1600,7 +1338,7 @@ function splitParagraphChildrenAtTextOffsets(paragraph, text, startOffset, endOf
1600
1338
  afterChildren
1601
1339
  };
1602
1340
  }
1603
- function cloneParagraph2(paragraph) {
1341
+ function cloneParagraph(paragraph) {
1604
1342
  return {
1605
1343
  type: "paragraph",
1606
1344
  style: paragraph.style ? { ...paragraph.style } : void 0,
@@ -1632,7 +1370,7 @@ function duplicateParagraph(model, index) {
1632
1370
  if (!node) {
1633
1371
  return next;
1634
1372
  }
1635
- next.nodes.splice(index + 1, 0, cloneParagraph2(node));
1373
+ next.nodes.splice(index + 1, 0, cloneParagraph(node));
1636
1374
  return next;
1637
1375
  }
1638
1376
  function updateParagraphText(model, index, text, options) {
@@ -1844,7 +1582,7 @@ function copyParagraphs(model, startIndex, endIndex = startIndex) {
1844
1582
  for (let index = start; index <= end; index += 1) {
1845
1583
  const node = model.nodes[index];
1846
1584
  if (node?.type === "paragraph") {
1847
- paragraphs.push(cloneParagraph2(node));
1585
+ paragraphs.push(cloneParagraph(node));
1848
1586
  }
1849
1587
  }
1850
1588
  return paragraphs;
@@ -1852,7 +1590,7 @@ function copyParagraphs(model, startIndex, endIndex = startIndex) {
1852
1590
  function pasteParagraphs(model, index, paragraphs) {
1853
1591
  const next = cloneDocModel(model);
1854
1592
  const safeIndex = Math.max(0, Math.min(index, next.nodes.length));
1855
- const copies = paragraphs.map(cloneParagraph2);
1593
+ const copies = paragraphs.map(cloneParagraph);
1856
1594
  next.nodes.splice(safeIndex, 0, ...copies);
1857
1595
  return next;
1858
1596
  }
@@ -2009,7 +1747,7 @@ async function serializeDocModel(model, basePackage) {
2009
1747
  model,
2010
1748
  basePackage ? mapsToWasmPackage(basePackage) : void 0
2011
1749
  );
2012
- const { parseDocx: parseDocx2 } = await import("./src-IT7QNDVM.js");
1750
+ const { parseDocx: parseDocx2 } = await import("./src-PJYTN6DB.js");
2013
1751
  return parseDocx2(bytes);
2014
1752
  }
2015
1753
  async function serializeDocx(model, basePackage) {
@@ -2369,6 +2107,13 @@ function reconcilePageCountCandidateToTargetCountByScalingHeight(options) {
2369
2107
  previousScale = scale;
2370
2108
  previousPageCount = candidate.pageCount;
2371
2109
  }
2110
+ if (!needMorePages && selectedCandidate.pageCount !== safeTargetPageCount) {
2111
+ return {
2112
+ pageCount: initialPageCount,
2113
+ pages: initialPages,
2114
+ scale: 1
2115
+ };
2116
+ }
2372
2117
  return selectedCandidate;
2373
2118
  }
2374
2119
 
@@ -3644,6 +3389,20 @@ var SerialIdleTaskQueue = class {
3644
3389
  this.schedulePump();
3645
3390
  });
3646
3391
  }
3392
+ /** Drops queued work for a single key, resolving its waiters. */
3393
+ cancel(key) {
3394
+ const remaining = [];
3395
+ this.pending.forEach((entry) => {
3396
+ if (entry.key === key) {
3397
+ entry.resolvers.forEach((resolveEntry) => {
3398
+ resolveEntry();
3399
+ });
3400
+ return;
3401
+ }
3402
+ remaining.push(entry);
3403
+ });
3404
+ this.pending.splice(0, this.pending.length, ...remaining);
3405
+ }
3647
3406
  /** Drops all queued tasks, resolving their waiters without running them. */
3648
3407
  clear() {
3649
3408
  const dropped = this.pending.splice(0, this.pending.length);
@@ -3828,6 +3587,29 @@ var MEASURED_BODY_FOOTER_OVERLAP_STABILITY_THRESHOLD = 1;
3828
3587
  var WORD_TABLE_CELL_PARAGRAPH_AUTO_LINE_TWIPS = 240;
3829
3588
  var WORD_TABLE_CELL_PARAGRAPH_BEFORE_TWIPS = 0;
3830
3589
  var WORD_TABLE_CELL_PARAGRAPH_AFTER_TWIPS = 0;
3590
+ var DOCX_IMPORT_PERFORMANCE_PREFIX = "react-docx.import";
3591
+ function markDocxImportPerformance(name) {
3592
+ if (typeof performance === "undefined" || typeof performance.mark !== "function") {
3593
+ return;
3594
+ }
3595
+ try {
3596
+ performance.mark(name);
3597
+ } catch {
3598
+ }
3599
+ }
3600
+ function measureDocxImportPerformance(name, startMark, endMark) {
3601
+ if (typeof performance === "undefined" || typeof performance.measure !== "function") {
3602
+ return;
3603
+ }
3604
+ try {
3605
+ performance.measure(name, startMark, endMark);
3606
+ } catch {
3607
+ }
3608
+ }
3609
+ function createDocxImportPerformanceTraceName(fileName) {
3610
+ const normalizedName = fileName.replace(/[^a-z0-9._-]+/gi, "_").slice(0, 80);
3611
+ return `${DOCX_IMPORT_PERFORMANCE_PREFIX}.${Date.now()}.${normalizedName}`;
3612
+ }
3831
3613
  var TABLE_ROW_SLICE_VISUAL_BLEED_PX = 1;
3832
3614
  var TABLE_CELL_SLICE_FULLY_VISIBLE_BOTTOM_BUFFER_PX = 4;
3833
3615
  var DEFAULT_SPLIT_PARAGRAPH_LINE_TWIPS = 259;
@@ -3915,6 +3697,7 @@ var tableEstimatedRowHeightsByNode = /* @__PURE__ */ new WeakMap();
3915
3697
  var paragraphExplicitIndentBySourceXml = /* @__PURE__ */ new Map();
3916
3698
  var paragraphDropCapBySourceXml = /* @__PURE__ */ new Map();
3917
3699
  var paragraphTrackedMarkupBySourceXml = /* @__PURE__ */ new Map();
3700
+ var paragraphCommentMarkupBySourceXml = /* @__PURE__ */ new Map();
3918
3701
  var paragraphMeasureCanvasContext;
3919
3702
  var textWidthByFontAndValue = /* @__PURE__ */ new Map();
3920
3703
  var estimatedTextAdvanceWidthByFontAndValue = /* @__PURE__ */ new Map();
@@ -4209,6 +3992,10 @@ function resolveEffectiveZoomScale(element) {
4209
3992
  }
4210
3993
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
4211
3994
  }
3995
+ function normalizePageVirtualizationZoomScale(value) {
3996
+ const scale = Number(value);
3997
+ return Number.isFinite(scale) && scale > 0 ? scale : void 0;
3998
+ }
4212
3999
  var DOC_SURFACE_STYLE_BY_THEME = {
4213
4000
  light: {
4214
4001
  backgroundColor: "#ffffff",
@@ -7207,7 +6994,7 @@ function splitParagraphAtExplicitColumnBreaks(paragraph) {
7207
6994
  }
7208
6995
  appendCurrentSegment();
7209
6996
  return paragraphChildren.map((children, segmentIndex) => {
7210
- const nextStyle = cloneParagraphStyle2(paragraph.style);
6997
+ const nextStyle = cloneParagraphStyle(paragraph.style);
7211
6998
  if (segmentIndex > 0 && nextStyle?.numbering) {
7212
6999
  nextStyle.numbering = void 0;
7213
7000
  }
@@ -8916,9 +8703,7 @@ function estimateTabLeaderWrappedLineCountForParagraph(paragraph, maxLineWidthPx
8916
8703
  leadingSegments,
8917
8704
  paragraphBaseFontPx
8918
8705
  );
8919
- const tabStopPositionsPx = (paragraph.style?.tabStops ?? []).map((tabStop) => twipsToPixels(tabStop.positionTwips)).filter(
8920
- (positionPx) => Number.isFinite(positionPx) && positionPx > 0
8921
- ).sort((left, right) => left - right);
8706
+ const tabStopPositionsPx = resolveParagraphFirstLineLeftTabStopsPx(paragraph);
8922
8707
  const explicitLeadingTabStopPx = tableOfContentsLeadingLeftTabStopPx(paragraph);
8923
8708
  const leadingReservationWidthPx = leadingSegments.length === 0 ? 0 : Number.isFinite(explicitLeadingTabStopPx) && explicitLeadingTabStopPx > 0 ? Math.max(
8924
8709
  leadingTextWidthPx,
@@ -12784,10 +12569,7 @@ function tableOfContentsLeadingLeftTabStopPx(paragraph) {
12784
12569
  if (!isTableOfContentsParagraph(paragraph)) {
12785
12570
  return void 0;
12786
12571
  }
12787
- const leftTabStopPositionsPx = (paragraph.style?.tabStops ?? []).filter((tabStop) => tabStop.alignment === "left").map((tabStop) => twipsToPixels(tabStop.positionTwips)).filter(
12788
- (positionPx) => Number.isFinite(positionPx) && positionPx > 0
12789
- ).sort((left, right) => left - right);
12790
- return leftTabStopPositionsPx[0];
12572
+ return resolveParagraphFirstLineLeftTabStopsPx(paragraph)[0];
12791
12573
  }
12792
12574
  function paragraphContainsTabCharacter(paragraph) {
12793
12575
  return paragraph.children.some((child) => {
@@ -13837,6 +13619,81 @@ function resolveParagraphTrackedMarkup(paragraph) {
13837
13619
  setCacheEntry(paragraphTrackedMarkupBySourceXml, sourceXml, resolved);
13838
13620
  return resolved;
13839
13621
  }
13622
+ function resolveParagraphCommentMarkup(paragraph) {
13623
+ const sourceXml = paragraph.sourceXml ?? "";
13624
+ if (!sourceXml || !/commentRange|commentReference/i.test(sourceXml)) {
13625
+ return void 0;
13626
+ }
13627
+ const cached = paragraphCommentMarkupBySourceXml.get(sourceXml);
13628
+ if (cached !== void 0) {
13629
+ return cached ?? void 0;
13630
+ }
13631
+ const rangeStartById = /* @__PURE__ */ new Map();
13632
+ const rangeEndById = /* @__PURE__ */ new Map();
13633
+ for (const match of sourceXml.matchAll(
13634
+ /<w:commentRangeStart\b[^>]*w:id="(-?\d+)"[^>]*\/?>/gi
13635
+ )) {
13636
+ const commentId = Number.parseInt(match[1] ?? "", 10);
13637
+ if (Number.isFinite(commentId) && match.index !== void 0) {
13638
+ rangeStartById.set(commentId, match.index + match[0].length);
13639
+ }
13640
+ }
13641
+ for (const match of sourceXml.matchAll(
13642
+ /<w:commentRangeEnd\b[^>]*w:id="(-?\d+)"[^>]*\/?>/gi
13643
+ )) {
13644
+ const commentId = Number.parseInt(match[1] ?? "", 10);
13645
+ if (Number.isFinite(commentId) && match.index !== void 0) {
13646
+ rangeEndById.set(commentId, match.index);
13647
+ }
13648
+ }
13649
+ const ranges = [];
13650
+ const rangeIds = /* @__PURE__ */ new Set([
13651
+ ...rangeStartById.keys(),
13652
+ ...rangeEndById.keys()
13653
+ ]);
13654
+ rangeIds.forEach((commentId) => {
13655
+ const start = rangeStartById.get(commentId) ?? 0;
13656
+ const end = rangeEndById.get(commentId) ?? sourceXml.length;
13657
+ if (end > start) {
13658
+ ranges.push({ commentId, start, end });
13659
+ }
13660
+ });
13661
+ if (ranges.length === 0) {
13662
+ setCacheEntry(paragraphCommentMarkupBySourceXml, sourceXml, null);
13663
+ return void 0;
13664
+ }
13665
+ const commentIdsByVisibleChildIndex = [];
13666
+ let visibleChildIndex = 0;
13667
+ const runPattern = /<w:r\b[\s\S]*?<\/w:r>/gi;
13668
+ for (const runMatch of sourceXml.matchAll(runPattern)) {
13669
+ const runXml = runMatch[0] ?? "";
13670
+ if (!runXml) {
13671
+ continue;
13672
+ }
13673
+ const runStart = runMatch.index ?? 0;
13674
+ const contentRunXml = stripTextBoxContentFromRunXml(runXml);
13675
+ const visibleTokens = parseTrackedRunTokens(contentRunXml, false);
13676
+ const hasImage = /<w:(?:drawing|pict)\b/i.test(runXml);
13677
+ const visibleChildCount = visibleTokens.filter((token) => token.text.length > 0 || token.isNote).length + (hasImage ? 1 : 0);
13678
+ if (visibleChildCount === 0) {
13679
+ continue;
13680
+ }
13681
+ const activeCommentIds = ranges.filter((range) => runStart >= range.start && runStart < range.end).map((range) => range.commentId);
13682
+ if (activeCommentIds.length > 0) {
13683
+ for (let index = 0; index < visibleChildCount; index += 1) {
13684
+ commentIdsByVisibleChildIndex[visibleChildIndex + index] = activeCommentIds;
13685
+ }
13686
+ }
13687
+ visibleChildIndex += visibleChildCount;
13688
+ }
13689
+ if (commentIdsByVisibleChildIndex.length === 0) {
13690
+ setCacheEntry(paragraphCommentMarkupBySourceXml, sourceXml, null);
13691
+ return void 0;
13692
+ }
13693
+ const resolved = { commentIdsByVisibleChildIndex };
13694
+ setCacheEntry(paragraphCommentMarkupBySourceXml, sourceXml, resolved);
13695
+ return resolved;
13696
+ }
13840
13697
  function instructionTextToPageFieldKind(rawInstruction) {
13841
13698
  const normalized = decodeXmlText(rawInstruction).replace(/\s+/g, " ").trim().toUpperCase();
13842
13699
  if (!normalized || normalized.includes("PAGEREF")) {
@@ -13883,11 +13740,16 @@ function paragraphPageFieldSequence(paragraph) {
13883
13740
  }
13884
13741
  return fields;
13885
13742
  }
13743
+ var pageFieldValueSequenceBySourceXml = /* @__PURE__ */ new Map();
13886
13744
  function paragraphPageFieldValueSequence(paragraph) {
13887
13745
  const xml = paragraph.sourceXml ?? "";
13888
13746
  if (!xml) {
13889
13747
  return [];
13890
13748
  }
13749
+ const cached = pageFieldValueSequenceBySourceXml.get(xml);
13750
+ if (cached) {
13751
+ return cached;
13752
+ }
13891
13753
  const values = [];
13892
13754
  const fieldStack = [];
13893
13755
  const tokenPattern = /<w:fldSimple\b[^>]*\bw:instr="([^"]+)"[^>]*>[\s\S]*?<\/w:fldSimple>|<w:r\b[\s\S]*?<\/w:r>/gi;
@@ -13967,13 +13829,19 @@ function paragraphPageFieldValueSequence(paragraph) {
13967
13829
  fieldStack.pop();
13968
13830
  }
13969
13831
  }
13832
+ setCacheEntry(pageFieldValueSequenceBySourceXml, xml, values);
13970
13833
  return values;
13971
13834
  }
13835
+ var styleRefFieldValueSequenceBySourceXml = /* @__PURE__ */ new Map();
13972
13836
  function paragraphStyleRefFieldValueSequence(paragraph) {
13973
13837
  const xml = paragraph.sourceXml ?? "";
13974
13838
  if (!xml) {
13975
13839
  return [];
13976
13840
  }
13841
+ const cached = styleRefFieldValueSequenceBySourceXml.get(xml);
13842
+ if (cached) {
13843
+ return cached;
13844
+ }
13977
13845
  const values = [];
13978
13846
  const fieldStack = [];
13979
13847
  const tokenPattern = /<w:fldSimple\b[^>]*\bw:instr="([^"]+)"[^>]*>[\s\S]*?<\/w:fldSimple>|<w:r\b[\s\S]*?<\/w:r>/gi;
@@ -14053,6 +13921,7 @@ function paragraphStyleRefFieldValueSequence(paragraph) {
14053
13921
  fieldStack.pop();
14054
13922
  }
14055
13923
  }
13924
+ setCacheEntry(styleRefFieldValueSequenceBySourceXml, xml, values);
14056
13925
  return values;
14057
13926
  }
14058
13927
  function normalizeStyleRefTarget(value) {
@@ -14187,6 +14056,7 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14187
14056
  const showTrackedChanges = options?.showTrackedChanges === true;
14188
14057
  const showTrackedInlineMarkup = showTrackedChanges && options?.trackedMarkupMode !== "gutter";
14189
14058
  const trackedMarkup = showTrackedInlineMarkup ? resolveParagraphTrackedMarkup(paragraph) : void 0;
14059
+ const commentMarkup = options?.showCommentHighlights === true ? resolveParagraphCommentMarkup(paragraph) : void 0;
14190
14060
  const tocParagraphLevel = tableOfContentsLevel(paragraph);
14191
14061
  const tocLinkColor = tocParagraphLevel ? options?.tocLinkColorByLevel?.[tocParagraphLevel] : void 0;
14192
14062
  const floatingAnchorOriginCorrectionXPx = Number.isFinite(
@@ -14228,8 +14098,19 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14228
14098
  });
14229
14099
  };
14230
14100
  const currentTrackedInlineChange = () => trackedMarkup?.inlineChangeByVisibleChildIndex[trackedVisibleChildCursor];
14101
+ const currentCommentHighlightStyle = () => {
14102
+ const commentIds = commentMarkup?.commentIdsByVisibleChildIndex[trackedVisibleChildCursor];
14103
+ if (!commentIds || commentIds.length === 0) {
14104
+ return void 0;
14105
+ }
14106
+ const accent = commentAccentColor(documentTheme);
14107
+ return {
14108
+ backgroundColor: documentTheme === "dark" ? "rgba(251, 191, 36, 0.24)" : "rgba(251, 191, 36, 0.3)",
14109
+ borderBottom: `2px solid ${accent}`
14110
+ };
14111
+ };
14231
14112
  const consumeTrackedVisibleChild = (child) => {
14232
- if (!trackedMarkup) {
14113
+ if (!trackedMarkup && !commentMarkup) {
14233
14114
  return;
14234
14115
  }
14235
14116
  if (child.type === "form-field") {
@@ -14398,20 +14279,26 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14398
14279
  const resolveFieldText = (value, preferredZone) => resolvePageFieldText(resolveStyleRefFieldText(value), preferredZone);
14399
14280
  const trackedLinkStyle = (style, trackedInlineChange) => {
14400
14281
  if (!isTableOfContentsParagraph(paragraph)) {
14401
- return trackedInlineStyle(
14402
- linkStyleToCss(style, documentTheme),
14403
- trackedInlineChange
14404
- );
14282
+ return {
14283
+ ...trackedInlineStyle(
14284
+ linkStyleToCss(style, documentTheme),
14285
+ trackedInlineChange
14286
+ ),
14287
+ ...currentCommentHighlightStyle()
14288
+ };
14405
14289
  }
14406
14290
  const base = runStyleToCss(style, documentTheme);
14407
- return trackedInlineStyle(
14408
- {
14409
- ...base,
14410
- color: tocLinkColor ? themedRunColor(tocLinkColor, documentTheme) : "inherit",
14411
- textDecoration: "none"
14412
- },
14413
- trackedInlineChange
14414
- );
14291
+ return {
14292
+ ...trackedInlineStyle(
14293
+ {
14294
+ ...base,
14295
+ color: tocLinkColor ? themedRunColor(tocLinkColor, documentTheme) : "inherit",
14296
+ textDecoration: "none"
14297
+ },
14298
+ trackedInlineChange
14299
+ ),
14300
+ ...currentCommentHighlightStyle()
14301
+ };
14415
14302
  };
14416
14303
  const usesExternalHorizontalAnchorOrigin = (image) => {
14417
14304
  const horizontalRelativeTo = image.floating?.horizontalRelativeTo?.trim().toLowerCase();
@@ -14458,10 +14345,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14458
14345
  trackTextAdvance(text, child.style);
14459
14346
  return;
14460
14347
  }
14461
- const trackedStyle = trackedInlineStyle(
14462
- runStyleToCss(child.style, documentTheme),
14463
- trackedInlineChange
14464
- );
14348
+ const trackedStyle = {
14349
+ ...trackedInlineStyle(
14350
+ runStyleToCss(child.style, documentTheme),
14351
+ trackedInlineChange
14352
+ ),
14353
+ ...currentCommentHighlightStyle()
14354
+ };
14465
14355
  if (text === " " && !useTabLeaderLayout && !useAnchoredTabLayout) {
14466
14356
  target.push(
14467
14357
  /* @__PURE__ */ jsx("span", { style: tabTextStyle(child.style, trackedStyle), children: "\xA0" }, key)
@@ -14717,10 +14607,13 @@ function renderParagraphRuns(paragraph, keyPrefix, documentTheme = "light", numb
14717
14607
  }
14718
14608
  return;
14719
14609
  }
14720
- const textStyle = trackedInlineStyle(
14721
- runStyleToCss(child.style, documentTheme),
14722
- trackedInlineChange
14723
- );
14610
+ const textStyle = {
14611
+ ...trackedInlineStyle(
14612
+ runStyleToCss(child.style, documentTheme),
14613
+ trackedInlineChange
14614
+ ),
14615
+ ...currentCommentHighlightStyle()
14616
+ };
14724
14617
  const noteLabel = noteMarkerLabel(
14725
14618
  child.noteReference,
14726
14619
  safeNoteMarkerIndexes.footnote,
@@ -15685,23 +15578,23 @@ function textWithListType(text, listType) {
15685
15578
  const normalized = stripListPrefix(text);
15686
15579
  return listType === "unordered" ? `\u2022 ${normalized}` : `1. ${normalized}`;
15687
15580
  }
15688
- function cloneParagraphBorderStyle2(border) {
15581
+ function cloneParagraphBorderStyle(border) {
15689
15582
  return border ? { ...border } : void 0;
15690
15583
  }
15691
- function cloneParagraphBorderSet2(borders) {
15584
+ function cloneParagraphBorderSet(borders) {
15692
15585
  if (!borders) {
15693
15586
  return void 0;
15694
15587
  }
15695
15588
  return {
15696
- top: cloneParagraphBorderStyle2(borders.top),
15697
- right: cloneParagraphBorderStyle2(borders.right),
15698
- bottom: cloneParagraphBorderStyle2(borders.bottom),
15699
- left: cloneParagraphBorderStyle2(borders.left),
15700
- between: cloneParagraphBorderStyle2(borders.between),
15701
- bar: cloneParagraphBorderStyle2(borders.bar)
15589
+ top: cloneParagraphBorderStyle(borders.top),
15590
+ right: cloneParagraphBorderStyle(borders.right),
15591
+ bottom: cloneParagraphBorderStyle(borders.bottom),
15592
+ left: cloneParagraphBorderStyle(borders.left),
15593
+ between: cloneParagraphBorderStyle(borders.between),
15594
+ bar: cloneParagraphBorderStyle(borders.bar)
15702
15595
  };
15703
15596
  }
15704
- function cloneParagraphStyle2(style) {
15597
+ function cloneParagraphStyle(style) {
15705
15598
  if (!style) {
15706
15599
  return void 0;
15707
15600
  }
@@ -15711,12 +15604,12 @@ function cloneParagraphStyle2(style) {
15711
15604
  spacing: style.spacing ? { ...style.spacing } : void 0,
15712
15605
  indent: style.indent ? { ...style.indent } : void 0,
15713
15606
  tabStops: style.tabStops ? style.tabStops.map((tabStop) => ({ ...tabStop })) : void 0,
15714
- borders: cloneParagraphBorderSet2(style.borders),
15607
+ borders: cloneParagraphBorderSet(style.borders),
15715
15608
  dropCap: style.dropCap ? { ...style.dropCap } : void 0
15716
15609
  };
15717
15610
  }
15718
15611
  function splitParagraphStyleWithDefaultSpacing(style, sourceXml) {
15719
- const clonedStyle = cloneParagraphStyle2(style);
15612
+ const clonedStyle = cloneParagraphStyle(style);
15720
15613
  if (sourceXml || clonedStyle?.styleId) {
15721
15614
  return clonedStyle;
15722
15615
  }
@@ -15735,7 +15628,7 @@ function splitParagraphStyleWithDefaultSpacing(style, sourceXml) {
15735
15628
  }
15736
15629
  };
15737
15630
  }
15738
- function cloneTableBoxSpacing2(spacing) {
15631
+ function cloneTableBoxSpacing(spacing) {
15739
15632
  if (!spacing) {
15740
15633
  return void 0;
15741
15634
  }
@@ -15746,7 +15639,7 @@ function cloneTableBoxSpacing2(spacing) {
15746
15639
  leftTwips: spacing.leftTwips
15747
15640
  };
15748
15641
  }
15749
- function cloneTableBorderStyle2(border) {
15642
+ function cloneTableBorderStyle(border) {
15750
15643
  if (!border) {
15751
15644
  return void 0;
15752
15645
  }
@@ -15756,19 +15649,19 @@ function cloneTableBorderStyle2(border) {
15756
15649
  sizeEighthPt: border.sizeEighthPt
15757
15650
  };
15758
15651
  }
15759
- function cloneTableBorderSet2(borders) {
15652
+ function cloneTableBorderSet(borders) {
15760
15653
  if (!borders) {
15761
15654
  return void 0;
15762
15655
  }
15763
15656
  return {
15764
- top: cloneTableBorderStyle2(borders.top),
15765
- right: cloneTableBorderStyle2(borders.right),
15766
- bottom: cloneTableBorderStyle2(borders.bottom),
15767
- left: cloneTableBorderStyle2(borders.left),
15768
- insideH: cloneTableBorderStyle2(borders.insideH),
15769
- insideV: cloneTableBorderStyle2(borders.insideV),
15770
- tl2br: cloneTableBorderStyle2(borders.tl2br),
15771
- tr2bl: cloneTableBorderStyle2(borders.tr2bl)
15657
+ top: cloneTableBorderStyle(borders.top),
15658
+ right: cloneTableBorderStyle(borders.right),
15659
+ bottom: cloneTableBorderStyle(borders.bottom),
15660
+ left: cloneTableBorderStyle(borders.left),
15661
+ insideH: cloneTableBorderStyle(borders.insideH),
15662
+ insideV: cloneTableBorderStyle(borders.insideV),
15663
+ tl2br: cloneTableBorderStyle(borders.tl2br),
15664
+ tr2bl: cloneTableBorderStyle(borders.tr2bl)
15772
15665
  };
15773
15666
  }
15774
15667
  function cloneTableCellStyle(style) {
@@ -15777,8 +15670,8 @@ function cloneTableCellStyle(style) {
15777
15670
  }
15778
15671
  return {
15779
15672
  ...style,
15780
- marginTwips: cloneTableBoxSpacing2(style.marginTwips),
15781
- borders: cloneTableBorderSet2(style.borders)
15673
+ marginTwips: cloneTableBoxSpacing(style.marginTwips),
15674
+ borders: cloneTableBorderSet(style.borders)
15782
15675
  };
15783
15676
  }
15784
15677
  function cloneTableRowStyle(style) {
@@ -15793,7 +15686,7 @@ function createEmptyParagraphFromTemplate(template) {
15793
15686
  const nextTextStyle = cloneTextStyle2(firstRunStyle(template));
15794
15687
  return {
15795
15688
  type: "paragraph",
15796
- style: cloneParagraphStyle2(template?.style),
15689
+ style: cloneParagraphStyle(template?.style),
15797
15690
  children: [
15798
15691
  {
15799
15692
  type: "text",
@@ -15862,7 +15755,7 @@ function shiftListIndent(indent, levelDelta) {
15862
15755
  };
15863
15756
  }
15864
15757
  function ensurePrefixListIndent(paragraph) {
15865
- const clonedStyle = cloneParagraphStyle2(paragraph.style) ?? {};
15758
+ const clonedStyle = cloneParagraphStyle(paragraph.style) ?? {};
15866
15759
  const existingIndent = clonedStyle.indent;
15867
15760
  const hasMeaningfulLeftIndent = Number.isFinite(existingIndent?.leftTwips) && Math.abs(existingIndent?.leftTwips ?? 0) > 0;
15868
15761
  const hasMeaningfulFirstLine = Number.isFinite(existingIndent?.firstLineTwips) && Math.abs(existingIndent?.firstLineTwips ?? 0) > 0;
@@ -15882,7 +15775,7 @@ function ensurePrefixListIndent(paragraph) {
15882
15775
  return true;
15883
15776
  }
15884
15777
  function clearAutoPrefixListIndent(paragraph) {
15885
- const clonedStyle = cloneParagraphStyle2(paragraph.style);
15778
+ const clonedStyle = cloneParagraphStyle(paragraph.style);
15886
15779
  const existingIndent = clonedStyle?.indent;
15887
15780
  if (!clonedStyle || !existingIndent) {
15888
15781
  return false;
@@ -16009,11 +15902,22 @@ function parseEmbeddedTableRuntimeKey(tableRuntimeKey) {
16009
15902
  descendants
16010
15903
  };
16011
15904
  }
15905
+ var columnWidthsByTable = /* @__PURE__ */ new WeakMap();
16012
15906
  function columnWidthsFromTableDefinition(table, columnCount) {
15907
+ const cachedByCount = columnWidthsByTable.get(table);
15908
+ if (cachedByCount?.has(columnCount)) {
15909
+ return cachedByCount.get(columnCount);
15910
+ }
15911
+ const resolved = computeColumnWidthsFromTableDefinition(table, columnCount);
15912
+ const cache = cachedByCount ?? /* @__PURE__ */ new Map();
15913
+ cache.set(columnCount, resolved);
15914
+ columnWidthsByTable.set(table, cache);
15915
+ return resolved;
15916
+ }
15917
+ function computeColumnWidthsFromTableDefinition(table, columnCount) {
16013
15918
  const gridWidths = table.style?.columnWidthsTwips;
16014
15919
  const rowDerivedWidths = deriveColumnWidthsFromTableRows(table, columnCount);
16015
15920
  if (gridWidths && gridWidths.length === columnCount) {
16016
- console.log("[colw]", columnCount, gridWidths.length, !!rowDerivedWidths, gridConflictsWithRowWidths(table, gridWidths));
16017
15921
  if (rowDerivedWidths && rowDerivedWidths.length > 0 && gridConflictsWithRowWidths(table, gridWidths)) {
16018
15922
  return rowDerivedWidths;
16019
15923
  }
@@ -16500,7 +16404,7 @@ function applyParagraphBorderPresetForRangeEntry(borders, preset, remove, index,
16500
16404
  if (total <= 1) {
16501
16405
  return applyParagraphBorderPreset(borders, preset, remove);
16502
16406
  }
16503
- const nextBorders = cloneParagraphBorderSet2(borders) ?? {};
16407
+ const nextBorders = cloneParagraphBorderSet(borders) ?? {};
16504
16408
  const visibleBorder = toolbarParagraphBorderStyle(
16505
16409
  resolvePreferredParagraphBorder(nextBorders)
16506
16410
  );
@@ -16581,7 +16485,7 @@ function tableBorderPresetState(borders, selectedCellBorders) {
16581
16485
  };
16582
16486
  }
16583
16487
  function applyParagraphBorderPreset(borders, preset, remove = false) {
16584
- const nextBorders = cloneParagraphBorderSet2(borders) ?? {};
16488
+ const nextBorders = cloneParagraphBorderSet(borders) ?? {};
16585
16489
  const visibleBorder = toolbarParagraphBorderStyle(
16586
16490
  resolvePreferredParagraphBorder(nextBorders)
16587
16491
  );
@@ -16637,7 +16541,7 @@ function applyParagraphBorderPreset(borders, preset, remove = false) {
16637
16541
  return nextBorders;
16638
16542
  }
16639
16543
  function applyTableBorderPreset(borders, preset, remove = false) {
16640
- const nextBorders = cloneTableBorderSet2(borders) ?? {};
16544
+ const nextBorders = cloneTableBorderSet(borders) ?? {};
16641
16545
  const visibleBorder = toolbarTableBorderStyle(
16642
16546
  resolvePreferredTableBorder(nextBorders)
16643
16547
  );
@@ -17554,6 +17458,127 @@ function collectTrackedChangesFromModel(model) {
17554
17458
  });
17555
17459
  return trackedChanges;
17556
17460
  }
17461
+ function decodeCommentRangeText(rangeXml) {
17462
+ const texts = [];
17463
+ for (const match of rangeXml.matchAll(
17464
+ /<w:t\b[^>]*>([\s\S]*?)<\/w:t>/gi
17465
+ )) {
17466
+ texts.push(decodeXmlText(match[1] ?? ""));
17467
+ }
17468
+ const combined = texts.join("").replace(/\s+/g, " ").trim();
17469
+ if (!combined) {
17470
+ return void 0;
17471
+ }
17472
+ return combined.length > 120 ? `${combined.slice(0, 119)}\u2026` : combined;
17473
+ }
17474
+ function resolveCommentAnchorText(sourceXml, commentId) {
17475
+ const startMatch = sourceXml.match(
17476
+ new RegExp(`<w:commentRangeStart\\b[^>]*w:id="${commentId}"[^>]*/?>`, "i")
17477
+ );
17478
+ const endMatch = sourceXml.match(
17479
+ new RegExp(`<w:commentRangeEnd\\b[^>]*w:id="${commentId}"[^>]*/?>`, "i")
17480
+ );
17481
+ const startIndex = startMatch?.index !== void 0 ? startMatch.index + startMatch[0].length : (
17482
+ // Range opened in an earlier paragraph: take from the paragraph start.
17483
+ endMatch?.index !== void 0 ? 0 : void 0
17484
+ );
17485
+ if (startIndex === void 0) {
17486
+ return void 0;
17487
+ }
17488
+ const endIndex = endMatch?.index !== void 0 ? endMatch.index : sourceXml.length;
17489
+ if (endIndex <= startIndex) {
17490
+ return void 0;
17491
+ }
17492
+ return decodeCommentRangeText(sourceXml.slice(startIndex, endIndex));
17493
+ }
17494
+ function collectCommentsFromModel(model) {
17495
+ const definitions = model.metadata.comments ?? [];
17496
+ if (definitions.length === 0) {
17497
+ return [];
17498
+ }
17499
+ const definitionById = new Map(
17500
+ definitions.map((definition) => [definition.id, definition])
17501
+ );
17502
+ const comments = [];
17503
+ const appendParagraphComments = (paragraph, nodeIndex, location) => {
17504
+ const sourceXml = paragraph.sourceXml ?? "";
17505
+ if (!sourceXml || !/commentReference/i.test(sourceXml)) {
17506
+ return;
17507
+ }
17508
+ for (const match of sourceXml.matchAll(
17509
+ /<w:commentReference\b[^>]*w:id="(-?\d+)"/gi
17510
+ )) {
17511
+ const commentId = Number.parseInt(match[1] ?? "", 10);
17512
+ const definition = Number.isFinite(commentId) ? definitionById.get(commentId) : void 0;
17513
+ if (!definition) {
17514
+ continue;
17515
+ }
17516
+ comments.push({
17517
+ id: `${paragraphLocationKey(location)}:comment:${commentId}`,
17518
+ commentId,
17519
+ author: definition.author,
17520
+ initials: definition.initials,
17521
+ date: definition.date,
17522
+ text: definition.text,
17523
+ parentId: definition.parentId,
17524
+ resolved: definition.resolved,
17525
+ anchorText: resolveCommentAnchorText(sourceXml, commentId),
17526
+ nodeIndex,
17527
+ location: location.kind === "paragraph" ? { kind: "paragraph", nodeIndex: location.nodeIndex } : {
17528
+ kind: "table-cell",
17529
+ tableIndex: location.tableIndex,
17530
+ rowIndex: location.rowIndex,
17531
+ cellIndex: location.cellIndex,
17532
+ paragraphIndex: location.paragraphIndex
17533
+ }
17534
+ });
17535
+ }
17536
+ };
17537
+ model.nodes.forEach((node, nodeIndex) => {
17538
+ if (node.type === "paragraph") {
17539
+ appendParagraphComments(node, nodeIndex, {
17540
+ kind: "paragraph",
17541
+ nodeIndex
17542
+ });
17543
+ return;
17544
+ }
17545
+ node.rows.forEach((row, rowIndex) => {
17546
+ row.cells.forEach((cell, cellIndex) => {
17547
+ const directParagraphs = tableCellParagraphs(cell.nodes);
17548
+ directParagraphs.forEach((paragraph, paragraphIndex) => {
17549
+ appendParagraphComments(paragraph, nodeIndex, {
17550
+ kind: "table-cell",
17551
+ tableIndex: nodeIndex,
17552
+ rowIndex,
17553
+ cellIndex,
17554
+ paragraphIndex
17555
+ });
17556
+ });
17557
+ const nestedParagraphs = tableCellParagraphsRecursively(
17558
+ cell.nodes
17559
+ ).filter((paragraph) => !directParagraphs.includes(paragraph));
17560
+ nestedParagraphs.forEach((paragraph, nestedParagraphIndex) => {
17561
+ appendParagraphComments(paragraph, nodeIndex, {
17562
+ kind: "table-cell",
17563
+ tableIndex: nodeIndex,
17564
+ rowIndex,
17565
+ cellIndex,
17566
+ paragraphIndex: -(nestedParagraphIndex + 1)
17567
+ });
17568
+ });
17569
+ });
17570
+ });
17571
+ });
17572
+ return comments;
17573
+ }
17574
+ function commentAccentColor(documentTheme) {
17575
+ return documentTheme === "dark" ? "#fbbf24" : "#d97706";
17576
+ }
17577
+ function estimateCommentCardHeight(comment) {
17578
+ const snippet = comment.text || "Comment";
17579
+ const lines = Math.max(1, Math.ceil(snippet.length / 30));
17580
+ return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
17581
+ }
17557
17582
  function trackedChangeKindLabel(kind) {
17558
17583
  switch (kind) {
17559
17584
  case "insertion":
@@ -17602,15 +17627,15 @@ function trackedChangeAccentColor(kind, documentTheme) {
17602
17627
  return palette.format;
17603
17628
  }
17604
17629
  }
17605
- function trackedChangeSortTuple(change) {
17606
- if (change.location.kind === "paragraph") {
17607
- return [change.location.nodeIndex, 0, 0, 0];
17630
+ function gutterAnnotationSortTuple(location) {
17631
+ if (location.kind === "paragraph") {
17632
+ return [location.nodeIndex, 0, 0, 0];
17608
17633
  }
17609
17634
  return [
17610
- change.location.tableIndex,
17611
- change.location.rowIndex,
17612
- change.location.cellIndex,
17613
- change.location.paragraphIndex
17635
+ location.tableIndex,
17636
+ location.rowIndex,
17637
+ location.cellIndex,
17638
+ location.paragraphIndex
17614
17639
  ];
17615
17640
  }
17616
17641
  function trackedChangeBelongsToPageSegments(location, pageSegments) {
@@ -17629,10 +17654,10 @@ function trackedChangeBelongsToPageSegments(location, pageSegments) {
17629
17654
  return location.rowIndex >= segment.tableRowRange.startRowIndex && location.rowIndex < segment.tableRowRange.endRowIndex;
17630
17655
  });
17631
17656
  }
17632
- function resolveTrackedChangePageIndex(change, pageNodeSegmentsByPage) {
17657
+ function resolveGutterAnnotationPageIndex(location, pageNodeSegmentsByPage) {
17633
17658
  for (let pageIndex = 0; pageIndex < pageNodeSegmentsByPage.length; pageIndex += 1) {
17634
17659
  if (trackedChangeBelongsToPageSegments(
17635
- change.location,
17660
+ location,
17636
17661
  pageNodeSegmentsByPage[pageIndex] ?? []
17637
17662
  )) {
17638
17663
  return pageIndex;
@@ -17687,30 +17712,30 @@ function estimateTrackedChangeCardHeight(change) {
17687
17712
  const lines = Math.max(1, Math.ceil(snippet.length / 30));
17688
17713
  return Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, 34 + lines * 14);
17689
17714
  }
17690
- function layoutTrackedChangesForPage(changes, anchorByChangeId, cardHeightsByChangeId, pageWidthPx, pageHeightPx) {
17691
- if (changes.length === 0) {
17715
+ function layoutTrackedChangesForPage(annotations, anchorByChangeId, cardHeightsByChangeId, pageWidthPx, pageHeightPx) {
17716
+ if (annotations.length === 0) {
17692
17717
  return [];
17693
17718
  }
17694
17719
  const fallbackStride = Math.max(
17695
17720
  18,
17696
- pageHeightPx / Math.max(1, changes.length + 1)
17721
+ pageHeightPx / Math.max(1, annotations.length + 1)
17697
17722
  );
17698
- const withAnchors = changes.map((change, index) => {
17723
+ const withAnchors = annotations.map((annotation, index) => {
17699
17724
  const defaultAnchor = Math.min(
17700
17725
  Math.max(10, Math.round((index + 1) * fallbackStride)),
17701
17726
  Math.max(10, pageHeightPx - 10)
17702
17727
  );
17703
- const anchorPoint = anchorByChangeId.get(change.id);
17728
+ const anchorPoint = anchorByChangeId.get(annotation.id);
17704
17729
  const anchorY = anchorPoint?.y ?? defaultAnchor;
17705
17730
  const anchorX = anchorPoint?.x ?? Math.max(10, pageWidthPx - 10);
17706
- const measuredHeightPx = cardHeightsByChangeId?.get(change.id);
17707
- const estimatedHeightPx = estimateTrackedChangeCardHeight(change);
17731
+ const measuredHeightPx = cardHeightsByChangeId?.get(annotation.id);
17732
+ const estimatedHeightPx = annotation.trackedChange ? estimateTrackedChangeCardHeight(annotation.trackedChange) : annotation.comment ? estimateCommentCardHeight(annotation.comment) : TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX;
17708
17733
  const heightPx = Number.isFinite(measuredHeightPx) && measuredHeightPx > 0 ? Math.max(
17709
17734
  TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX,
17710
17735
  Math.round(measuredHeightPx)
17711
17736
  ) : estimatedHeightPx;
17712
17737
  return {
17713
- change,
17738
+ annotation,
17714
17739
  anchorX: clampNumber(
17715
17740
  Math.round(anchorX),
17716
17741
  10,
@@ -18741,10 +18766,14 @@ function useDocxEditor(options = {}) {
18741
18766
  const [isImporting, setIsImporting] = React.useState(false);
18742
18767
  const [documentTheme, setDocumentThemeState] = React.useState(options.initialDocumentTheme ?? "light");
18743
18768
  const [showTrackedChanges, setShowTrackedChangesState] = React.useState(options.initialShowTrackedChanges ?? false);
18769
+ const [showComments, setShowCommentsState] = React.useState(
18770
+ options.initialShowComments ?? false
18771
+ );
18744
18772
  const [paginationInfo, setPaginationInfo] = React.useState({
18745
18773
  currentPage: 1,
18746
18774
  totalPages: 1
18747
18775
  });
18776
+ const activeImportAbortControllerRef = React.useRef(void 0);
18748
18777
  const [history, setHistory] = React.useState({
18749
18778
  past: [],
18750
18779
  future: []
@@ -19057,6 +19086,9 @@ function useDocxEditor(options = {}) {
19057
19086
  () => collectTrackedChangesFromModel(model),
19058
19087
  [model]
19059
19088
  );
19089
+ const comments = React.useMemo(() => collectCommentsFromModel(model), [
19090
+ model
19091
+ ]);
19060
19092
  const hasUnorderedList = selectedListType === "unordered";
19061
19093
  const hasOrderedList = selectedListType === "ordered";
19062
19094
  const canUndo = history.past.length > 0;
@@ -19077,6 +19109,15 @@ function useDocxEditor(options = {}) {
19077
19109
  const toggleShowTrackedChanges = React.useCallback(() => {
19078
19110
  setShowTrackedChangesState((current) => !current);
19079
19111
  }, []);
19112
+ const setShowComments = React.useCallback(
19113
+ (nextShowComments) => {
19114
+ setShowCommentsState(nextShowComments);
19115
+ },
19116
+ []
19117
+ );
19118
+ const toggleShowComments = React.useCallback(() => {
19119
+ setShowCommentsState((current) => !current);
19120
+ }, []);
19080
19121
  const registerPendingExportModelTransformer = React.useCallback(
19081
19122
  (transformer) => {
19082
19123
  pendingExportModelTransformerRef.current = transformer;
@@ -19140,6 +19181,7 @@ function useDocxEditor(options = {}) {
19140
19181
  );
19141
19182
  React.useEffect(() => {
19142
19183
  return () => {
19184
+ activeImportAbortControllerRef.current?.abort();
19143
19185
  unloadEmbeddedFonts();
19144
19186
  };
19145
19187
  }, [unloadEmbeddedFonts]);
@@ -19275,6 +19317,8 @@ function useDocxEditor(options = {}) {
19275
19317
  );
19276
19318
  const importDocxFile = React.useCallback(
19277
19319
  async (file) => {
19320
+ activeImportAbortControllerRef.current?.abort();
19321
+ activeImportAbortControllerRef.current = void 0;
19278
19322
  if (!/\.docx?$/i.test(file.name)) {
19279
19323
  replaceDocumentWithImportError(
19280
19324
  file.name,
@@ -19285,11 +19329,50 @@ function useDocxEditor(options = {}) {
19285
19329
  setIsImporting(true);
19286
19330
  setImportError(void 0);
19287
19331
  setStatus(`Loading ${file.name}...`);
19332
+ const importAbortController = new AbortController();
19333
+ activeImportAbortControllerRef.current = importAbortController;
19334
+ const traceName = createDocxImportPerformanceTraceName(file.name);
19335
+ const startMark = `${traceName}:start`;
19336
+ const bufferStartMark = `${traceName}:arrayBuffer:start`;
19337
+ const bufferEndMark = `${traceName}:arrayBuffer:end`;
19338
+ const workerStartMark = `${traceName}:worker:start`;
19339
+ const workerEndMark = `${traceName}:worker:end`;
19340
+ const fontsStartMark = `${traceName}:fonts:start`;
19341
+ const fontsEndMark = `${traceName}:fonts:end`;
19342
+ const stateStartMark = `${traceName}:state:start`;
19343
+ const stateEndMark = `${traceName}:state:end`;
19344
+ markDocxImportPerformance(startMark);
19288
19345
  try {
19346
+ markDocxImportPerformance(bufferStartMark);
19289
19347
  const buffer = await file.arrayBuffer();
19290
- const pkg = await parseDocx(buffer);
19348
+ markDocxImportPerformance(bufferEndMark);
19349
+ measureDocxImportPerformance(
19350
+ `${traceName}:arrayBuffer`,
19351
+ bufferStartMark,
19352
+ bufferEndMark
19353
+ );
19354
+ markDocxImportPerformance(workerStartMark);
19355
+ const importResult = await importDocxBuffer(buffer, {
19356
+ signal: importAbortController.signal,
19357
+ transferBuffer: true
19358
+ });
19359
+ markDocxImportPerformance(workerEndMark);
19360
+ measureDocxImportPerformance(
19361
+ `${traceName}:${importResult.source}`,
19362
+ workerStartMark,
19363
+ workerEndMark
19364
+ );
19365
+ const pkg = importResult.package;
19366
+ const nextModel = importResult.model;
19367
+ markDocxImportPerformance(fontsStartMark);
19291
19368
  await loadEmbeddedFontsFromPackage(pkg);
19292
- const nextModel = await buildDocModel(pkg);
19369
+ markDocxImportPerformance(fontsEndMark);
19370
+ measureDocxImportPerformance(
19371
+ `${traceName}:fonts`,
19372
+ fontsStartMark,
19373
+ fontsEndMark
19374
+ );
19375
+ markDocxImportPerformance(stateStartMark);
19293
19376
  setModel(nextModel);
19294
19377
  setDocumentLoadNonce((current) => current + 1);
19295
19378
  setHistory({ past: [], future: [] });
@@ -19302,16 +19385,31 @@ function useDocxEditor(options = {}) {
19302
19385
  setSelectedFormFieldLocation(void 0);
19303
19386
  setImportError(void 0);
19304
19387
  setStatus(`Loaded ${file.name}`);
19388
+ markDocxImportPerformance(stateEndMark);
19389
+ measureDocxImportPerformance(
19390
+ `${traceName}:state-dispatch`,
19391
+ stateStartMark,
19392
+ stateEndMark
19393
+ );
19394
+ measureDocxImportPerformance(`${traceName}:total`, startMark, stateEndMark);
19305
19395
  } catch (error) {
19396
+ if (error instanceof Error && error.name === "AbortError" && activeImportAbortControllerRef.current !== importAbortController) {
19397
+ return;
19398
+ }
19306
19399
  const nextError = error instanceof Error ? error : new Error("Unknown error");
19307
19400
  replaceDocumentWithImportError(file.name, nextError);
19308
19401
  } finally {
19309
- setIsImporting(false);
19402
+ if (activeImportAbortControllerRef.current === importAbortController) {
19403
+ activeImportAbortControllerRef.current = void 0;
19404
+ setIsImporting(false);
19405
+ }
19310
19406
  }
19311
19407
  },
19312
19408
  [loadEmbeddedFontsFromPackage, replaceDocumentWithImportError]
19313
19409
  );
19314
19410
  const newDocument = React.useCallback(() => {
19411
+ activeImportAbortControllerRef.current?.abort();
19412
+ activeImportAbortControllerRef.current = void 0;
19315
19413
  unloadEmbeddedFonts();
19316
19414
  setModel(cloneDocModel(starterTemplateRef.current));
19317
19415
  setDocumentLoadNonce((current) => current + 1);
@@ -19924,7 +20022,7 @@ function useDocxEditor(options = {}) {
19924
20022
  return;
19925
20023
  }
19926
20024
  paragraph.style = {
19927
- ...cloneParagraphStyle2(paragraph.style) ?? {},
20025
+ ...cloneParagraphStyle(paragraph.style) ?? {},
19928
20026
  numbering: void 0
19929
20027
  };
19930
20028
  paragraph.sourceXml = void 0;
@@ -19980,7 +20078,7 @@ function useDocxEditor(options = {}) {
19980
20078
  normalizedRange.end.offset
19981
20079
  );
19982
20080
  collapsedOffset = safeStart + replacementText.length;
19983
- const endParagraphStyleForMerge = cloneParagraphStyle2(
20081
+ const endParagraphStyleForMerge = cloneParagraphStyle(
19984
20082
  endParagraph.style
19985
20083
  );
19986
20084
  const insertedStyle = cloneTextStyle2(
@@ -20067,7 +20165,7 @@ function useDocxEditor(options = {}) {
20067
20165
  normalizedRange.start.location
20068
20166
  );
20069
20167
  if (mergedLookup.paragraph) {
20070
- mergedLookup.paragraph.style = endParagraphStyleForMerge ? cloneParagraphStyle2(endParagraphStyleForMerge) : void 0;
20168
+ mergedLookup.paragraph.style = endParagraphStyleForMerge ? cloneParagraphStyle(endParagraphStyleForMerge) : void 0;
20071
20169
  mergedLookup.paragraph.sourceXml = void 0;
20072
20170
  if (mergedLookup.tableNode) {
20073
20171
  mergedLookup.tableNode.sourceXml = void 0;
@@ -20384,7 +20482,7 @@ function useDocxEditor(options = {}) {
20384
20482
  const removePreset2 = preset !== "none" && presetState2[preset];
20385
20483
  if (preset === "diagonal-down" || preset === "diagonal-up") {
20386
20484
  const clonedCellStyle = cloneTableCellStyle(targetCell.style) ?? {};
20387
- const nextCellBorders = cloneTableBorderSet2(clonedCellStyle.borders) ?? {};
20485
+ const nextCellBorders = cloneTableBorderSet(clonedCellStyle.borders) ?? {};
20388
20486
  const visibleBorder = removePreset2 ? nilTableBorderStyle() : toolbarTableBorderStyle(
20389
20487
  resolvePreferredTableBorder(nextCellBorders) ?? resolvePreferredTableBorder(tableNode2.style?.borders)
20390
20488
  );
@@ -20414,7 +20512,7 @@ function useDocxEditor(options = {}) {
20414
20512
  borders: nextBorders2
20415
20513
  };
20416
20514
  if (preset === "none" && targetCell.style?.borders) {
20417
- const nextCellBorders = cloneTableBorderSet2(targetCell.style.borders) ?? {};
20515
+ const nextCellBorders = cloneTableBorderSet(targetCell.style.borders) ?? {};
20418
20516
  const nilBorder = nilTableBorderStyle();
20419
20517
  nextCellBorders.tl2br = { ...nilBorder };
20420
20518
  nextCellBorders.tr2bl = { ...nilBorder };
@@ -20465,7 +20563,7 @@ function useDocxEditor(options = {}) {
20465
20563
  if (!paragraph2) {
20466
20564
  continue;
20467
20565
  }
20468
- const clonedStyle2 = cloneParagraphStyle2(paragraph2.style) ?? {};
20566
+ const clonedStyle2 = cloneParagraphStyle(paragraph2.style) ?? {};
20469
20567
  const nextBorders2 = applyParagraphBorderPresetForRangeEntry(
20470
20568
  clonedStyle2.borders,
20471
20569
  preset,
@@ -20497,7 +20595,7 @@ function useDocxEditor(options = {}) {
20497
20595
  if (!paragraph) {
20498
20596
  return current;
20499
20597
  }
20500
- const clonedStyle = cloneParagraphStyle2(paragraph.style) ?? {};
20598
+ const clonedStyle = cloneParagraphStyle(paragraph.style) ?? {};
20501
20599
  const presetState = paragraphBorderPresetState(clonedStyle.borders);
20502
20600
  const removePreset = preset !== "none" && presetState[preset];
20503
20601
  const nextBorders = applyParagraphBorderPreset(
@@ -20656,7 +20754,7 @@ function useDocxEditor(options = {}) {
20656
20754
  const currentText = paragraphText(paragraph);
20657
20755
  if (shouldRemove) {
20658
20756
  if (paragraphHasNumbering(paragraph)) {
20659
- const clonedStyle = cloneParagraphStyle2(paragraph.style);
20757
+ const clonedStyle = cloneParagraphStyle(paragraph.style);
20660
20758
  if (clonedStyle?.numbering) {
20661
20759
  clonedStyle.numbering = void 0;
20662
20760
  paragraph.style = clonedStyle;
@@ -20802,7 +20900,7 @@ function useDocxEditor(options = {}) {
20802
20900
  return current;
20803
20901
  }
20804
20902
  paragraphNode.style = {
20805
- ...cloneParagraphStyle2(paragraphNode.style) ?? {},
20903
+ ...cloneParagraphStyle(paragraphNode.style) ?? {},
20806
20904
  numbering: {
20807
20905
  ...numbering,
20808
20906
  ilvl: nextLevel
@@ -20918,7 +21016,7 @@ function useDocxEditor(options = {}) {
20918
21016
  paragraphNode.sourceXml = void 0;
20919
21017
  next.nodes.splice(insertionIndex, 0, {
20920
21018
  type: "paragraph",
20921
- style: cloneParagraphStyle2(paragraphNode.style),
21019
+ style: cloneParagraphStyle(paragraphNode.style),
20922
21020
  children: [
20923
21021
  {
20924
21022
  type: "text",
@@ -21009,12 +21107,12 @@ function useDocxEditor(options = {}) {
21009
21107
  afterInsertedStyle: inheritedRunStyle
21010
21108
  }
21011
21109
  );
21012
- paragraphNode.style = cloneParagraphStyle2(splitParagraphStyle);
21110
+ paragraphNode.style = cloneParagraphStyle(splitParagraphStyle);
21013
21111
  paragraphNode.children = splitChildren.beforeChildren;
21014
21112
  paragraphNode.sourceXml = void 0;
21015
21113
  next.nodes.splice(insertionIndex, 0, {
21016
21114
  type: "paragraph",
21017
- style: cloneParagraphStyle2(splitParagraphStyle),
21115
+ style: cloneParagraphStyle(splitParagraphStyle),
21018
21116
  children: splitChildren.afterChildren
21019
21117
  });
21020
21118
  splitResult = {
@@ -21348,7 +21446,7 @@ function useDocxEditor(options = {}) {
21348
21446
  if (!currentDropCap) {
21349
21447
  return current;
21350
21448
  }
21351
- paragraph.style = cloneParagraphStyle2(paragraph.style) ?? {};
21449
+ paragraph.style = cloneParagraphStyle(paragraph.style) ?? {};
21352
21450
  paragraph.style.dropCap = {
21353
21451
  ...currentDropCap,
21354
21452
  ...patch
@@ -21424,7 +21522,7 @@ function useDocxEditor(options = {}) {
21424
21522
  link: preservedLink
21425
21523
  }
21426
21524
  ];
21427
- paragraph.style = cloneParagraphStyle2(paragraph.style) ?? {};
21525
+ paragraph.style = cloneParagraphStyle(paragraph.style) ?? {};
21428
21526
  paragraph.style.dropCap = {
21429
21527
  ...currentDropCap
21430
21528
  };
@@ -21578,7 +21676,7 @@ function useDocxEditor(options = {}) {
21578
21676
  const firstParagraph = paragraphs[0];
21579
21677
  const nextParagraph = {
21580
21678
  type: "paragraph",
21581
- style: cloneParagraphStyle2(firstParagraph?.style),
21679
+ style: cloneParagraphStyle(firstParagraph?.style),
21582
21680
  children: [
21583
21681
  {
21584
21682
  type: "text",
@@ -22237,6 +22335,8 @@ function useDocxEditor(options = {}) {
22237
22335
  documentTheme,
22238
22336
  trackedChanges,
22239
22337
  showTrackedChanges,
22338
+ comments,
22339
+ showComments,
22240
22340
  currentPage: paginationInfo.currentPage,
22241
22341
  totalPages: paginationInfo.totalPages,
22242
22342
  selection,
@@ -22264,8 +22364,10 @@ function useDocxEditor(options = {}) {
22264
22364
  setStatus,
22265
22365
  setDocumentTheme,
22266
22366
  setShowTrackedChanges,
22367
+ setShowComments,
22267
22368
  syncPaginationInfo,
22268
22369
  toggleShowTrackedChanges,
22370
+ toggleShowComments,
22269
22371
  importDocxFile,
22270
22372
  newDocument,
22271
22373
  exportDocx,
@@ -22552,6 +22654,7 @@ function useDocxPageThumbnails(editor, options = {}) {
22552
22654
  if (!targetCanvas) {
22553
22655
  return;
22554
22656
  }
22657
+ const requiresAttachedTarget = canvas === void 0;
22555
22658
  const pageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22556
22659
  if (!pageElement || !pageElement.isConnected) {
22557
22660
  updatePageThumbnailState(pageIndex, "unavailable");
@@ -22565,6 +22668,9 @@ function useDocxPageThumbnails(editor, options = {}) {
22565
22668
  }
22566
22669
  updatePageThumbnailState(pageIndex, "rendering");
22567
22670
  await ensureThumbnailRasterQueue().enqueue(targetCanvas, async () => {
22671
+ if (requiresAttachedTarget && attachedCanvasByPageRef.current.get(pageIndex) !== targetCanvas) {
22672
+ return;
22673
+ }
22568
22674
  const livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22569
22675
  if (!livePageElement || !livePageElement.isConnected) {
22570
22676
  updatePageThumbnailState(pageIndex, "unavailable");
@@ -22711,6 +22817,10 @@ function useDocxPageThumbnails(editor, options = {}) {
22711
22817
  void renderPageThumbnailToCanvasRef.current(pageIndex, canvas);
22712
22818
  return;
22713
22819
  }
22820
+ const previousCanvas = attachedCanvasByPageRef.current.get(pageIndex);
22821
+ if (previousCanvas) {
22822
+ thumbnailRasterQueueRef.current?.cancel(previousCanvas);
22823
+ }
22714
22824
  attachedCanvasByPageRef.current.delete(pageIndex);
22715
22825
  };
22716
22826
  canvasRefCallbacksRef.current.set(pageIndex, nextCanvasRef);
@@ -22978,6 +23088,42 @@ function useDocxTrackChanges(editor) {
22978
23088
  ]
22979
23089
  );
22980
23090
  }
23091
+ function useDocxComments(editor) {
23092
+ const commentsByLocation = React.useMemo(() => {
23093
+ const grouped = /* @__PURE__ */ new Map();
23094
+ editor.comments.forEach((comment) => {
23095
+ const key = paragraphLocationKey(comment.location);
23096
+ const bucket = grouped.get(key) ?? [];
23097
+ bucket.push(comment);
23098
+ grouped.set(key, bucket);
23099
+ });
23100
+ return grouped;
23101
+ }, [editor.comments]);
23102
+ const getCommentsForLocation = React.useCallback(
23103
+ (location) => {
23104
+ return commentsByLocation.get(paragraphLocationKey(location)) ?? [];
23105
+ },
23106
+ [commentsByLocation]
23107
+ );
23108
+ return React.useMemo(
23109
+ () => ({
23110
+ comments: editor.comments,
23111
+ showComments: editor.showComments,
23112
+ setShowComments: editor.setShowComments,
23113
+ toggleShowComments: editor.toggleShowComments,
23114
+ commentsByLocation,
23115
+ getCommentsForLocation
23116
+ }),
23117
+ [
23118
+ editor.comments,
23119
+ editor.showComments,
23120
+ editor.setShowComments,
23121
+ editor.toggleShowComments,
23122
+ commentsByLocation,
23123
+ getCommentsForLocation
23124
+ ]
23125
+ );
23126
+ }
22981
23127
  function useDocxPageLayout(editor) {
22982
23128
  const primarySectionPropertiesXml = editor.model.metadata.sections?.[0]?.sectionPropertiesXml ?? editor.model.metadata.sectionPropertiesXml;
22983
23129
  const layout = React.useMemo(() => {
@@ -23850,6 +23996,8 @@ function DocxEditorViewer({
23850
23996
  headingStyles,
23851
23997
  showTrackedChanges,
23852
23998
  renderTrackedChangeCard,
23999
+ showComments,
24000
+ renderCommentCard,
23853
24001
  renderTableContextMenu,
23854
24002
  renderContextMenu,
23855
24003
  onFormFieldDoubleClick,
@@ -23858,7 +24006,9 @@ function DocxEditorViewer({
23858
24006
  const pageSurfaceRegistryOwner = docxViewerPageSurfaceRegistryOwner(editor);
23859
24007
  const trackedChangesEnabled = showTrackedChanges ?? editor.showTrackedChanges;
23860
24008
  const hasTrackedChanges = editor.trackedChanges.length > 0;
23861
- const showTrackedChangeGutter = trackedChangesEnabled;
24009
+ const commentsEnabled = showComments ?? editor.showComments;
24010
+ const hasComments = editor.comments.length > 0;
24011
+ const showTrackedChangeGutter = trackedChangesEnabled || commentsEnabled;
23862
24012
  const isReadOnly = mode === "read-only" || trackedChangesEnabled;
23863
24013
  const isNightReaderMode = isReadOnly && editor.documentTheme === "dark";
23864
24014
  const documentContentTheme = isNightReaderMode ? "light" : editor.documentTheme;
@@ -23877,11 +24027,13 @@ function DocxEditorViewer({
23877
24027
  const paragraphRunRenderOptions = React.useMemo(
23878
24028
  () => ({
23879
24029
  showTrackedChanges: trackedChangesEnabled,
24030
+ showCommentHighlights: commentsEnabled,
23880
24031
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
23881
24032
  tocLinkColorByLevel,
23882
24033
  imageFilterSuffix: documentContentFilter
23883
24034
  }),
23884
24035
  [
24036
+ commentsEnabled,
23885
24037
  documentContentFilter,
23886
24038
  editor.model.metadata.numberingDefinitions,
23887
24039
  tocLinkColorByLevel,
@@ -23924,7 +24076,6 @@ function DocxEditorViewer({
23924
24076
  /* @__PURE__ */ new Map()
23925
24077
  );
23926
24078
  const pageElementsRef = React.useRef(/* @__PURE__ */ new Map());
23927
- const pagePlaceholderRefCallbacksRef = React.useRef(/* @__PURE__ */ new Map());
23928
24079
  const pageSurfaceRefCallbacksRef = React.useRef(/* @__PURE__ */ new Map());
23929
24080
  const trackedChangeCardElementsRef = React.useRef(/* @__PURE__ */ new Map());
23930
24081
  const initialPaginationStableSignatureRef = React.useRef(
@@ -23992,26 +24143,6 @@ function DocxEditorViewer({
23992
24143
  measuredPageContentHeightByIndex,
23993
24144
  setMeasuredPageContentHeightByIndex
23994
24145
  ] = React.useState([]);
23995
- const pagePlaceholderRefForIndex = React.useCallback(
23996
- (pageIndex) => {
23997
- const normalizedPageIndex = Math.max(0, Math.round(pageIndex));
23998
- const cached = pagePlaceholderRefCallbacksRef.current.get(normalizedPageIndex);
23999
- if (cached) {
24000
- return cached;
24001
- }
24002
- const nextRef = (element) => {
24003
- if (element) {
24004
- pageElementsRef.current.set(normalizedPageIndex, element);
24005
- } else {
24006
- pageElementsRef.current.delete(normalizedPageIndex);
24007
- }
24008
- registerDocxViewerPageSurface(editor, normalizedPageIndex, void 0);
24009
- };
24010
- pagePlaceholderRefCallbacksRef.current.set(normalizedPageIndex, nextRef);
24011
- return nextRef;
24012
- },
24013
- [pageSurfaceRegistryOwner]
24014
- );
24015
24146
  const pageSurfaceRefForIndex = React.useCallback(
24016
24147
  (pageIndex) => {
24017
24148
  const normalizedPageIndex = Math.max(0, Math.round(pageIndex));
@@ -24033,7 +24164,6 @@ function DocxEditorViewer({
24033
24164
  [pageSurfaceRegistryOwner]
24034
24165
  );
24035
24166
  React.useEffect(() => {
24036
- pagePlaceholderRefCallbacksRef.current.clear();
24037
24167
  pageSurfaceRefCallbacksRef.current.clear();
24038
24168
  }, [pageSurfaceRegistryOwner]);
24039
24169
  const [
@@ -25274,6 +25404,17 @@ function DocxEditorViewer({
25274
25404
  const pageVirtualizationOverscan = hasLargeTableLayoutSurface && !Number.isFinite(pageVirtualization?.overscan) ? LARGE_TABLE_PAGE_VIRTUALIZATION_OVERSCAN : rawPageVirtualizationOverscan;
25275
25405
  const webdriverActive = typeof navigator !== "undefined" && navigator.webdriver === true;
25276
25406
  const internalPageVirtualizationRequested = pageVirtualization?.enabled !== false && !hasExternalVisiblePageRange && !hideDocumentUntilPaginationSettled && isInitialPaginationSettled && !deferInternalPageVirtualization && !webdriverActive && pageCount > 1;
25407
+ const explicitPageVirtualizationScrollElement = pageVirtualization?.scrollElement ?? null;
25408
+ const explicitPageVirtualizationZoomScale = normalizePageVirtualizationZoomScale(pageVirtualization?.zoomScale);
25409
+ const resolveViewerMeasurementZoomScale = React.useCallback(
25410
+ (rootElement, fallback = 1) => {
25411
+ if (explicitPageVirtualizationZoomScale !== void 0) {
25412
+ return explicitPageVirtualizationZoomScale;
25413
+ }
25414
+ return rootElement ? resolveEffectiveZoomScale(rootElement) : fallback;
25415
+ },
25416
+ [explicitPageVirtualizationZoomScale]
25417
+ );
25277
25418
  React.useEffect(() => {
25278
25419
  setDeferInternalPageVirtualization(!hasLargeTableLayoutSurface);
25279
25420
  }, [editor.documentLoadNonce, hasLargeTableLayoutSurface]);
@@ -25304,9 +25445,34 @@ function DocxEditorViewer({
25304
25445
  return;
25305
25446
  }
25306
25447
  setInternalVirtualScrollElement(
25307
- nearestScrollableAncestor(viewerRootRef.current)
25448
+ explicitPageVirtualizationScrollElement instanceof HTMLElement ? explicitPageVirtualizationScrollElement : nearestScrollableAncestor(viewerRootRef.current)
25308
25449
  );
25309
- }, [editor.documentLoadNonce, pageCount, trackedChangesEnabled]);
25450
+ }, [
25451
+ editor.documentLoadNonce,
25452
+ explicitPageVirtualizationScrollElement,
25453
+ pageCount,
25454
+ trackedChangesEnabled
25455
+ ]);
25456
+ const [zoomProbeNonce, setZoomProbeNonce] = React.useState(0);
25457
+ React.useEffect(() => {
25458
+ if (typeof window === "undefined") {
25459
+ return;
25460
+ }
25461
+ const rootElement = viewerRootRef.current;
25462
+ if (!rootElement) {
25463
+ return;
25464
+ }
25465
+ const bumpZoomProbe = () => {
25466
+ setZoomProbeNonce((nonce) => nonce + 1);
25467
+ };
25468
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(bumpZoomProbe) : void 0;
25469
+ resizeObserver?.observe(rootElement);
25470
+ window.addEventListener("resize", bumpZoomProbe);
25471
+ return () => {
25472
+ resizeObserver?.disconnect();
25473
+ window.removeEventListener("resize", bumpZoomProbe);
25474
+ };
25475
+ }, [editor.documentLoadNonce]);
25310
25476
  React.useLayoutEffect(() => {
25311
25477
  if (typeof window === "undefined") {
25312
25478
  return;
@@ -25315,11 +25481,22 @@ function DocxEditorViewer({
25315
25481
  if (!rootElement) {
25316
25482
  return;
25317
25483
  }
25318
- const nextScale = Math.round(resolveEffectiveZoomScale(rootElement) * 100) / 100;
25484
+ const nextScale = Math.round(
25485
+ resolveViewerMeasurementZoomScale(
25486
+ rootElement,
25487
+ virtualizerMeasurementScale
25488
+ ) * 100
25489
+ ) / 100;
25319
25490
  setVirtualizerMeasurementScale(
25320
25491
  (current) => Math.abs(current - nextScale) < 5e-3 ? current : nextScale
25321
25492
  );
25322
- });
25493
+ }, [
25494
+ editor.documentLoadNonce,
25495
+ pageCount,
25496
+ resolveViewerMeasurementZoomScale,
25497
+ virtualizerMeasurementScale,
25498
+ zoomProbeNonce
25499
+ ]);
25323
25500
  const internalPageVirtualizationEnabled = internalPageVirtualizationRequested && internalVirtualScrollElement !== null;
25324
25501
  const internalPageVirtualizationPending = typeof window !== "undefined" && internalPageVirtualizationRequested && internalVirtualScrollElement === null;
25325
25502
  const internalVirtualScrollUsesWindow = typeof document !== "undefined" && internalVirtualScrollElement !== null && (internalVirtualScrollElement === document.scrollingElement || internalVirtualScrollElement === document.documentElement || internalVirtualScrollElement === document.body);
@@ -25362,6 +25539,30 @@ function DocxEditorViewer({
25362
25539
  internalWindowPageVirtualizer
25363
25540
  ]);
25364
25541
  const internalVirtualItems = internalPageVirtualizer.getVirtualItems();
25542
+ const internalMostVisiblePageIndex = React.useMemo(() => {
25543
+ if (!internalPageVirtualizationEnabled || internalVirtualItems.length === 0) {
25544
+ return void 0;
25545
+ }
25546
+ const virtualizerMetrics = internalPageVirtualizer;
25547
+ const viewportStart = Number.isFinite(virtualizerMetrics.scrollOffset) ? virtualizerMetrics.scrollOffset : internalVirtualItems[0]?.start ?? 0;
25548
+ const viewportSize = virtualizerMetrics.scrollRect?.height;
25549
+ const viewportEnd = viewportStart + (Number.isFinite(viewportSize) && viewportSize > 0 ? viewportSize : internalVirtualItems[0]?.size ?? 0);
25550
+ let bestPageIndex;
25551
+ let bestVisibleSize = -1;
25552
+ internalVirtualItems.forEach((item) => {
25553
+ const visibleSize = Math.min(item.end, viewportEnd) - Math.max(item.start, viewportStart);
25554
+ if (visibleSize > bestVisibleSize) {
25555
+ bestVisibleSize = visibleSize;
25556
+ bestPageIndex = item.index;
25557
+ }
25558
+ });
25559
+ return bestPageIndex === void 0 ? void 0 : clampNumber(bestPageIndex, 0, pageCount - 1);
25560
+ }, [
25561
+ internalPageVirtualizationEnabled,
25562
+ internalPageVirtualizer,
25563
+ internalVirtualItems,
25564
+ pageCount
25565
+ ]);
25365
25566
  const internalVisiblePageRange = React.useMemo(() => {
25366
25567
  if (!internalPageVirtualizationEnabled) {
25367
25568
  return void 0;
@@ -25652,6 +25853,40 @@ function DocxEditorViewer({
25652
25853
  }
25653
25854
  return indexes;
25654
25855
  }, [pageCount, visiblePageEndIndex, visiblePageStartIndex]);
25856
+ const pageStackVirtualSpacers = React.useMemo(() => {
25857
+ const pageWrapperWidthPxForIndex = (pageIndex) => {
25858
+ const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
25859
+ return showTrackedChangeGutter ? pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_WIDTH_PX : pageLayout.pageWidthPx;
25860
+ };
25861
+ const summarizeSkippedPages = (startPageIndex, endPageIndex) => {
25862
+ if (pageCount <= 0 || endPageIndex < startPageIndex || startPageIndex >= pageCount || endPageIndex < 0) {
25863
+ return { heightPx: 0, widthPx: 0 };
25864
+ }
25865
+ const start = clampNumber(startPageIndex, 0, pageCount - 1);
25866
+ const end = clampNumber(endPageIndex, start, pageCount - 1);
25867
+ let heightPx = 0;
25868
+ let widthPx = 0;
25869
+ for (let pageIndex = start; pageIndex <= end; pageIndex += 1) {
25870
+ const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
25871
+ heightPx += Math.max(1, Math.round(pageLayout.pageHeightPx));
25872
+ widthPx = Math.max(widthPx, pageWrapperWidthPxForIndex(pageIndex));
25873
+ }
25874
+ const skippedPageCount = end - start + 1;
25875
+ heightPx += Math.max(0, skippedPageCount - 1) * DOC_PAGE_BREAK_GAP;
25876
+ return { heightPx, widthPx };
25877
+ };
25878
+ return {
25879
+ before: summarizeSkippedPages(0, visiblePageStartIndex - 1),
25880
+ after: summarizeSkippedPages(visiblePageEndIndex + 1, pageCount - 1)
25881
+ };
25882
+ }, [
25883
+ documentLayout,
25884
+ pageCount,
25885
+ pageSectionInfoByIndex,
25886
+ showTrackedChangeGutter,
25887
+ visiblePageEndIndex,
25888
+ visiblePageStartIndex
25889
+ ]);
25655
25890
  React.useLayoutEffect(() => {
25656
25891
  if (typeof window === "undefined") {
25657
25892
  return;
@@ -25663,7 +25898,7 @@ function DocxEditorViewer({
25663
25898
  const next = new Map(current);
25664
25899
  let changed = false;
25665
25900
  const rootElement = viewerRootRef.current;
25666
- const zoomScale = rootElement ? resolveEffectiveZoomScale(rootElement) : 1;
25901
+ const zoomScale = resolveViewerMeasurementZoomScale(rootElement, 1);
25667
25902
  paragraphElementsRef.current.forEach((element, nodeIndex) => {
25668
25903
  if (!element.isConnected || element.dataset.docxParagraphPartialLineRange === "true" || element.closest('[data-docx-header-footer-region="footer"]') || element.closest('[data-docx-header-footer-region="header"]')) {
25669
25904
  return;
@@ -25692,6 +25927,7 @@ function DocxEditorViewer({
25692
25927
  }, [
25693
25928
  editor.documentLoadNonce,
25694
25929
  pageNodeSegmentIdentityKeysByPage,
25930
+ resolveViewerMeasurementZoomScale,
25695
25931
  visiblePageEndIndex,
25696
25932
  visiblePageStartIndex
25697
25933
  ]);
@@ -25811,7 +26047,7 @@ function DocxEditorViewer({
25811
26047
  }, [onPageCountChange, stableReportedPageCount]);
25812
26048
  React.useEffect(() => {
25813
26049
  const nextCurrentPage = clampNumber(
25814
- visiblePageStartIndex + 1,
26050
+ (internalMostVisiblePageIndex ?? visiblePageStartIndex) + 1,
25815
26051
  1,
25816
26052
  Math.max(1, stableReportedPageCount)
25817
26053
  );
@@ -25821,6 +26057,7 @@ function DocxEditorViewer({
25821
26057
  });
25822
26058
  }, [
25823
26059
  editor.syncPaginationInfo,
26060
+ internalMostVisiblePageIndex,
25824
26061
  stableReportedPageCount,
25825
26062
  visiblePageStartIndex
25826
26063
  ]);
@@ -25828,20 +26065,38 @@ function DocxEditorViewer({
25828
26065
  const pageBuckets = pageNodeSegmentsByPage.map(
25829
26066
  () => []
25830
26067
  );
25831
- editor.trackedChanges.forEach((change) => {
25832
- const pageIndex = resolveTrackedChangePageIndex(
25833
- change,
26068
+ const placeAnnotation = (annotation) => {
26069
+ const pageIndex = resolveGutterAnnotationPageIndex(
26070
+ annotation.location,
25834
26071
  pageNodeSegmentsByPage
25835
26072
  );
25836
26073
  if (pageIndex < 0 || pageIndex >= pageBuckets.length) {
25837
26074
  return;
25838
26075
  }
25839
- pageBuckets[pageIndex].push(change);
25840
- });
25841
- pageBuckets.forEach((pageChanges) => {
25842
- pageChanges.sort((left, right) => {
25843
- const leftKey = trackedChangeSortTuple(left);
25844
- const rightKey = trackedChangeSortTuple(right);
26076
+ pageBuckets[pageIndex].push(annotation);
26077
+ };
26078
+ if (trackedChangesEnabled) {
26079
+ editor.trackedChanges.forEach((change) => {
26080
+ placeAnnotation({
26081
+ id: change.id,
26082
+ location: change.location,
26083
+ trackedChange: change
26084
+ });
26085
+ });
26086
+ }
26087
+ if (commentsEnabled) {
26088
+ editor.comments.forEach((comment) => {
26089
+ placeAnnotation({
26090
+ id: comment.id,
26091
+ location: comment.location,
26092
+ comment
26093
+ });
26094
+ });
26095
+ }
26096
+ pageBuckets.forEach((pageAnnotations) => {
26097
+ pageAnnotations.sort((left, right) => {
26098
+ const leftKey = gutterAnnotationSortTuple(left.location);
26099
+ const rightKey = gutterAnnotationSortTuple(right.location);
25845
26100
  for (let index = 0; index < leftKey.length; index += 1) {
25846
26101
  if (leftKey[index] === rightKey[index]) {
25847
26102
  continue;
@@ -25852,7 +26107,13 @@ function DocxEditorViewer({
25852
26107
  });
25853
26108
  });
25854
26109
  return pageBuckets;
25855
- }, [editor.trackedChanges, pageNodeSegmentsByPage]);
26110
+ }, [
26111
+ commentsEnabled,
26112
+ editor.comments,
26113
+ editor.trackedChanges,
26114
+ pageNodeSegmentsByPage,
26115
+ trackedChangesEnabled
26116
+ ]);
25856
26117
  const [trackedChangeAnchorByPage, setTrackedChangeAnchorByPage] = React.useState([]);
25857
26118
  const [headerBodyClearanceByPage, setHeaderBodyClearanceByPage] = React.useState({});
25858
26119
  React.useEffect(() => {
@@ -25866,18 +26127,18 @@ function DocxEditorViewer({
25866
26127
  );
25867
26128
  return;
25868
26129
  }
25869
- const nextAnchorMaps = trackedChangesByPage.map((changes, pageIndex) => {
26130
+ const nextAnchorMaps = trackedChangesByPage.map((annotations, pageIndex) => {
25870
26131
  const pageElement = pageElementsRef.current.get(pageIndex);
25871
26132
  const anchorsByChangeId = /* @__PURE__ */ new Map();
25872
- if (!pageElement || changes.length === 0) {
26133
+ if (!pageElement || annotations.length === 0) {
25873
26134
  return anchorsByChangeId;
25874
26135
  }
25875
26136
  const pageHeightPx = Math.max(1, pageElement.offsetHeight);
25876
26137
  const pageWidthPx = Math.max(1, pageElement.offsetWidth);
25877
- changes.forEach((change) => {
26138
+ annotations.forEach((annotation) => {
25878
26139
  const anchorElement = findTrackedChangeAnchorElementInPage(
25879
26140
  pageElement,
25880
- change.location
26141
+ annotation.location
25881
26142
  );
25882
26143
  if (!anchorElement) {
25883
26144
  return;
@@ -25901,7 +26162,7 @@ function DocxEditorViewer({
25901
26162
  10,
25902
26163
  Math.max(10, pageWidthPx - 10)
25903
26164
  );
25904
- anchorsByChangeId.set(change.id, { x: anchorX, y: anchorY });
26165
+ anchorsByChangeId.set(annotation.id, { x: anchorX, y: anchorY });
25905
26166
  });
25906
26167
  return anchorsByChangeId;
25907
26168
  });
@@ -25919,28 +26180,30 @@ function DocxEditorViewer({
25919
26180
  );
25920
26181
  return;
25921
26182
  }
25922
- const nextHeightsByPage = trackedChangesByPage.map((changes, pageIndex) => {
25923
- const pageHeights = /* @__PURE__ */ new Map();
25924
- changes.forEach((change) => {
25925
- const cardElement = trackedChangeCardElementsRef.current.get(
25926
- `${pageIndex}:${change.id}`
25927
- );
25928
- if (!cardElement) {
25929
- return;
25930
- }
25931
- const measuredHeight = Math.round(
25932
- cardElement.getBoundingClientRect().height
25933
- );
25934
- if (!Number.isFinite(measuredHeight) || measuredHeight <= 0) {
25935
- return;
25936
- }
25937
- pageHeights.set(
25938
- change.id,
25939
- Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, measuredHeight)
25940
- );
25941
- });
25942
- return pageHeights;
25943
- });
26183
+ const nextHeightsByPage = trackedChangesByPage.map(
26184
+ (annotations, pageIndex) => {
26185
+ const pageHeights = /* @__PURE__ */ new Map();
26186
+ annotations.forEach((annotation) => {
26187
+ const cardElement = trackedChangeCardElementsRef.current.get(
26188
+ `${pageIndex}:${annotation.id}`
26189
+ );
26190
+ if (!cardElement) {
26191
+ return;
26192
+ }
26193
+ const measuredHeight = Math.round(
26194
+ cardElement.getBoundingClientRect().height
26195
+ );
26196
+ if (!Number.isFinite(measuredHeight) || measuredHeight <= 0) {
26197
+ return;
26198
+ }
26199
+ pageHeights.set(
26200
+ annotation.id,
26201
+ Math.max(TRACKED_CHANGE_GUTTER_CARD_MIN_HEIGHT_PX, measuredHeight)
26202
+ );
26203
+ });
26204
+ return pageHeights;
26205
+ }
26206
+ );
25944
26207
  setTrackedChangeCardHeightsByPage((current) => {
25945
26208
  if (current.length === nextHeightsByPage.length) {
25946
26209
  let equal = true;
@@ -26186,7 +26449,7 @@ function DocxEditorViewer({
26186
26449
  );
26187
26450
  return;
26188
26451
  }
26189
- const zoomScale = resolveEffectiveZoomScale(rootElement);
26452
+ const zoomScale = resolveViewerMeasurementZoomScale(rootElement, 1);
26190
26453
  const next = {};
26191
26454
  for (let pageIndex = 0; pageIndex < pageCount; pageIndex += 1) {
26192
26455
  if (!isPageVisible(pageIndex)) {
@@ -26273,6 +26536,7 @@ function DocxEditorViewer({
26273
26536
  pageCount,
26274
26537
  pageHeaderAndFooterNodes,
26275
26538
  pageSectionInfoByIndex,
26539
+ resolveViewerMeasurementZoomScale,
26276
26540
  visiblePageEndIndex,
26277
26541
  visiblePageStartIndex
26278
26542
  ]);
@@ -26302,7 +26566,7 @@ function DocxEditorViewer({
26302
26566
  if (Date.now() < paginationMeasurementSuspendUntilRef.current) {
26303
26567
  return;
26304
26568
  }
26305
- const zoomScale = resolveEffectiveZoomScale(rootElement);
26569
+ const zoomScale = resolveViewerMeasurementZoomScale(rootElement, 1);
26306
26570
  const nextMeasuredPageIdentityKeys = pageNodeSegmentIdentityKeysByPage;
26307
26571
  const nextMeasuredPageDiagnostics = pageNodeSegmentsByPage.map(
26308
26572
  (_, pageIndex) => {
@@ -26439,9 +26703,14 @@ function DocxEditorViewer({
26439
26703
  },
26440
26704
  []
26441
26705
  );
26706
+ const storedDocumentPageCountForLatch = editor.model.metadata.documentPageCount;
26707
+ const latchTargetPageCount = Number.isFinite(storedDocumentPageCountForLatch) ? Math.max(
26708
+ collectDocxHardPageBreakStartNodeIndexes(editor.model).size + 1,
26709
+ Math.round(storedDocumentPageCountForLatch)
26710
+ ) : void 0;
26442
26711
  const nextMeasuredBodyFooterOverlapLatchState = resolveMeasuredBodyFooterOverlapLatchState({
26443
26712
  pageCount,
26444
- targetPageCount: editor.model.metadata.documentPageCount,
26713
+ targetPageCount: latchTargetPageCount,
26445
26714
  overlappingPageIndexes,
26446
26715
  previousSignature: measuredBodyFooterOverlapCandidateRef.current.signature,
26447
26716
  previousConsecutivePasses: measuredBodyFooterOverlapCandidateRef.current.consecutivePasses,
@@ -26512,6 +26781,7 @@ function DocxEditorViewer({
26512
26781
  pageNodeSegmentIdentityKeysByPage,
26513
26782
  pageSectionInfoByIndex,
26514
26783
  pageHeaderAndFooterNodes,
26784
+ resolveViewerMeasurementZoomScale,
26515
26785
  visiblePageEndIndex,
26516
26786
  visiblePageStartIndex
26517
26787
  ]);
@@ -30946,7 +31216,10 @@ function DocxEditorViewer({
30946
31216
  return;
30947
31217
  }
30948
31218
  const rootElement = viewerRootRef.current;
30949
- const zoomScale = rootElement ? resolveEffectiveZoomScale(rootElement) : virtualizerMeasurementScale;
31219
+ const zoomScale = resolveViewerMeasurementZoomScale(
31220
+ rootElement,
31221
+ virtualizerMeasurementScale
31222
+ );
30950
31223
  const nextMeasuredHeights = {};
30951
31224
  editor.model.nodes.forEach((node, nodeIndex) => {
30952
31225
  if (node.type !== "table") {
@@ -31088,6 +31361,7 @@ function DocxEditorViewer({
31088
31361
  pageContentWidthPxByNodeIndex,
31089
31362
  paginationMeasurementEnabled,
31090
31363
  paginationMeasurementEpoch,
31364
+ resolveViewerMeasurementZoomScale,
31091
31365
  tableMeasuredRowHeights,
31092
31366
  tableColumnWidths,
31093
31367
  tableRowHeights,
@@ -33270,7 +33544,8 @@ function DocxEditorViewer({
33270
33544
  const hasFixedPositionWrappedImage = paragraph.children.some(
33271
33545
  (child) => child.type === "image" && isFixedPositionWrappedFloatingImage(child)
33272
33546
  );
33273
- if ((trackedChangesEnabled || useSpecialTabLayout) && !hasFixedPositionWrappedImage) {
33547
+ const paragraphHasCommentAnchors = commentsEnabled && /commentRange|commentReference/i.test(paragraph.sourceXml ?? "");
33548
+ if ((trackedChangesEnabled || useSpecialTabLayout || paragraphHasCommentAnchors) && !hasFixedPositionWrappedImage) {
33274
33549
  return renderParagraphRuns(
33275
33550
  paragraph,
33276
33551
  keyPrefix,
@@ -33283,6 +33558,7 @@ function DocxEditorViewer({
33283
33558
  void 0,
33284
33559
  {
33285
33560
  showTrackedChanges: trackedChangesEnabled,
33561
+ showCommentHighlights: commentsEnabled,
33286
33562
  numberingDefinitions: editor.model.metadata.numberingDefinitions,
33287
33563
  tocLinkColorByLevel,
33288
33564
  paragraphOriginLeftPx: bodyParagraphOriginLeftPx,
@@ -39626,44 +39902,25 @@ ${currentText.slice(end)}`;
39626
39902
  }
39627
39903
  }
39628
39904
  ) : null,
39629
- pageNodeSegmentsByPage.map((pageNodeSegments, pageIndex) => {
39905
+ pageStackVirtualSpacers.before.heightPx > 0 ? /* @__PURE__ */ jsx(
39906
+ "div",
39907
+ {
39908
+ "aria-hidden": "true",
39909
+ "data-docx-page-window-spacer": "before",
39910
+ style: {
39911
+ height: pageStackVirtualSpacers.before.heightPx,
39912
+ width: pageStackVirtualSpacers.before.widthPx,
39913
+ margin: "0 auto",
39914
+ pointerEvents: "none",
39915
+ visibility: hideDocumentUntilPaginationSettled ? "hidden" : void 0
39916
+ }
39917
+ }
39918
+ ) : null,
39919
+ visiblePageIndexes.map((pageIndex) => {
39920
+ const pageNodeSegments = pageNodeSegmentsByPage[pageIndex] ?? [];
39630
39921
  const pageInfo = pageSectionInfoByIndex[pageIndex];
39631
39922
  const pageLayout = pageInfo?.layout ?? documentLayout;
39632
- const pageVisible = isPageVisible(pageIndex);
39633
39923
  const pageWrapperWidthPx = showTrackedChangeGutter ? pageLayout.pageWidthPx + TRACKED_CHANGE_GUTTER_WIDTH_PX : pageLayout.pageWidthPx;
39634
- if (!pageVisible) {
39635
- const placeholderBackgroundColor = pageBackgroundColor ?? editor.model.metadata.documentBackgroundColor ?? pageSurfaceBaseStyle.backgroundColor;
39636
- return /* @__PURE__ */ jsx(
39637
- "div",
39638
- {
39639
- "data-docx-page-wrapper": "true",
39640
- "data-docx-page-index": pageIndex,
39641
- "data-index": pageIndex,
39642
- style: {
39643
- width: pageWrapperWidthPx,
39644
- margin: "0 auto",
39645
- visibility: hideDocumentUntilPaginationSettled ? "hidden" : void 0
39646
- },
39647
- children: /* @__PURE__ */ jsx(
39648
- "div",
39649
- {
39650
- "data-docx-page-placeholder": "true",
39651
- ref: pagePlaceholderRefForIndex(pageIndex),
39652
- style: {
39653
- ...pageSurfaceBaseStyle,
39654
- ...pageMarginPaddingStyle(pageLayout.marginsPx),
39655
- height: pageLayout.pageHeightPx,
39656
- minHeight: pageLayout.pageHeightPx,
39657
- width: pageLayout.pageWidthPx,
39658
- backgroundColor: placeholderBackgroundColor,
39659
- pointerEvents: "none"
39660
- }
39661
- }
39662
- )
39663
- },
39664
- `page-${pageIndex}`
39665
- );
39666
- }
39667
39924
  const pageContentWidthPx = Math.max(
39668
39925
  120,
39669
39926
  pageLayout.pageWidthPx - pageLayout.marginsPx.left - pageLayout.marginsPx.right
@@ -39835,6 +40092,10 @@ ${currentText.slice(end)}`;
39835
40092
  width: pageWrapperWidthPx,
39836
40093
  minHeight: pageLayout.pageHeightPx,
39837
40094
  margin: "0 auto",
40095
+ // Isolate per-page layout/style recalculation so scrolling and
40096
+ // edits on one page don't force whole-document layout passes.
40097
+ // (No paint containment: floats and gutter cards may overhang.)
40098
+ contain: "layout style",
39838
40099
  visibility: hideDocumentUntilPaginationSettled ? "hidden" : void 0
39839
40100
  },
39840
40101
  children: [
@@ -40085,9 +40346,6 @@ ${currentText.slice(end)}`;
40085
40346
  segments: [segment]
40086
40347
  });
40087
40348
  });
40088
- if (typeof window !== "undefined" && window.__docxDebugGroups) {
40089
- console.log("[groups]", pageIndex, JSON.stringify(sectionGroups.map((g) => ({ s: g.sectionIndex, n: g.segments.map((x) => x.nodeIndex) }))));
40090
- }
40091
40349
  return sectionGroups.map((group, groupIndex) => {
40092
40350
  const sectionColumns = sectionColumnsBySectionIndex[group.sectionIndex];
40093
40351
  const isLastGroupOnPage = groupIndex === sectionGroups.length - 1;
@@ -40912,10 +41170,10 @@ ${currentText.slice(end)}`;
40912
41170
  overflow: "visible"
40913
41171
  },
40914
41172
  children: pageTrackedChanges.map((entry) => {
40915
- const accentColor = trackedChangeAccentColor(
40916
- entry.change.kind,
41173
+ const accentColor = entry.annotation.trackedChange ? trackedChangeAccentColor(
41174
+ entry.annotation.trackedChange.kind,
40917
41175
  editor.documentTheme
40918
- );
41176
+ ) : commentAccentColor(editor.documentTheme);
40919
41177
  const cardCenterY = clampNumber(
40920
41178
  Math.round(entry.top + entry.heightPx / 2),
40921
41179
  8,
@@ -40976,12 +41234,12 @@ ${currentText.slice(end)}`;
40976
41234
  )
40977
41235
  ]
40978
41236
  },
40979
- `tracked-connector-${pageIndex}-${entry.change.id}`
41237
+ `tracked-connector-${pageIndex}-${entry.annotation.id}`
40980
41238
  );
40981
41239
  })
40982
41240
  }
40983
41241
  ),
40984
- !hasTrackedChanges && pageIndex === 0 ? /* @__PURE__ */ jsx(
41242
+ (!trackedChangesEnabled || !hasTrackedChanges) && (!commentsEnabled || !hasComments) && pageIndex === 0 ? /* @__PURE__ */ jsx(
40985
41243
  "p",
40986
41244
  {
40987
41245
  style: {
@@ -40994,19 +41252,21 @@ ${currentText.slice(end)}`;
40994
41252
  lineHeight: 1.35,
40995
41253
  color: "#94a3b8"
40996
41254
  },
40997
- children: "No edits found"
41255
+ children: trackedChangesEnabled && commentsEnabled ? "No edits or comments found" : commentsEnabled ? "No comments found" : "No edits found"
40998
41256
  }
40999
41257
  ) : null,
41000
41258
  pageTrackedChanges.map((entry) => {
41001
- const accentColor = trackedChangeAccentColor(
41002
- entry.change.kind,
41259
+ const trackedChange = entry.annotation.trackedChange;
41260
+ const comment = entry.annotation.comment;
41261
+ const accentColor = trackedChange ? trackedChangeAccentColor(
41262
+ trackedChange.kind,
41003
41263
  editor.documentTheme
41004
- );
41264
+ ) : commentAccentColor(editor.documentTheme);
41005
41265
  const formattedDate = formatTrackedChangeDate(
41006
- entry.change.date
41266
+ trackedChange?.date ?? comment?.date
41007
41267
  );
41008
- const kindLabel = trackedChangeKindLabel(entry.change.kind);
41009
- const snippet = normalizeTrackedChangeSnippet(entry.change.text) ?? (entry.change.kind === "format-change" || entry.change.kind === "paragraph-format-change" ? "Formatting" : "Change");
41268
+ const kindLabel = trackedChange ? trackedChangeKindLabel(trackedChange.kind) : comment?.resolved ? "Comment \xB7 Resolved" : comment?.parentId !== void 0 ? "Reply" : "Comment";
41269
+ const snippet = trackedChange ? normalizeTrackedChangeSnippet(trackedChange.text) ?? (trackedChange.kind === "format-change" || trackedChange.kind === "paragraph-format-change" ? "Formatting" : "Change") : comment?.text || "Comment";
41010
41270
  const cardWidthPx = Math.max(
41011
41271
  140,
41012
41272
  TRACKED_CHANGE_GUTTER_WIDTH_PX - TRACKED_CHANGE_GUTTER_CARD_LEFT_PX - TRACKED_CHANGE_GUTTER_CARD_RIGHT_PX
@@ -41058,7 +41318,7 @@ ${currentText.slice(end)}`;
41058
41318
  fontWeight: 700,
41059
41319
  lineHeight: 1.25
41060
41320
  },
41061
- children: entry.change.author?.trim() || "Unknown author"
41321
+ children: (trackedChange?.author ?? comment?.author)?.trim() || "Unknown author"
41062
41322
  }
41063
41323
  ),
41064
41324
  formattedDate ? /* @__PURE__ */ jsx(
@@ -41077,6 +41337,23 @@ ${currentText.slice(end)}`;
41077
41337
  ]
41078
41338
  }
41079
41339
  ),
41340
+ comment?.anchorText ? /* @__PURE__ */ jsxs(
41341
+ "p",
41342
+ {
41343
+ style: {
41344
+ margin: "2px 0 0",
41345
+ fontSize: 11,
41346
+ lineHeight: 1.3,
41347
+ fontStyle: "italic",
41348
+ color: editor.documentTheme === "dark" ? "#94a3b8" : "#6b7280"
41349
+ },
41350
+ children: [
41351
+ "\u201C",
41352
+ comment.anchorText,
41353
+ "\u201D"
41354
+ ]
41355
+ }
41356
+ ) : null,
41080
41357
  /* @__PURE__ */ jsxs(
41081
41358
  "p",
41082
41359
  {
@@ -41098,8 +41375,8 @@ ${currentText.slice(end)}`;
41098
41375
  ]
41099
41376
  }
41100
41377
  );
41101
- const renderedCard = renderTrackedChangeCard ? renderTrackedChangeCard({
41102
- change: entry.change,
41378
+ const renderedCard = trackedChange ? renderTrackedChangeCard ? renderTrackedChangeCard({
41379
+ change: trackedChange,
41103
41380
  kindLabel,
41104
41381
  snippet,
41105
41382
  formattedDate,
@@ -41107,12 +41384,21 @@ ${currentText.slice(end)}`;
41107
41384
  documentTheme: editor.documentTheme,
41108
41385
  pageIndex,
41109
41386
  style: cardStyle
41387
+ }) : defaultCard : comment && renderCommentCard ? renderCommentCard({
41388
+ comment,
41389
+ snippet,
41390
+ formattedDate,
41391
+ accentColor,
41392
+ documentTheme: editor.documentTheme,
41393
+ pageIndex,
41394
+ style: cardStyle
41110
41395
  }) : defaultCard;
41111
41396
  return /* @__PURE__ */ jsx(
41112
41397
  "div",
41113
41398
  {
41399
+ "data-docx-gutter-annotation": trackedChange ? "tracked-change" : "comment",
41114
41400
  ref: (element) => {
41115
- const elementKey = `${pageIndex}:${entry.change.id}`;
41401
+ const elementKey = `${pageIndex}:${entry.annotation.id}`;
41116
41402
  if (element) {
41117
41403
  trackedChangeCardElementsRef.current.set(
41118
41404
  elementKey,
@@ -41127,7 +41413,7 @@ ${currentText.slice(end)}`;
41127
41413
  style: cardContainerStyle,
41128
41414
  children: renderedCard
41129
41415
  },
41130
- `tracked-card-${pageIndex}-${entry.change.id}`
41416
+ `tracked-card-${pageIndex}-${entry.annotation.id}`
41131
41417
  );
41132
41418
  })
41133
41419
  ]
@@ -41138,6 +41424,20 @@ ${currentText.slice(end)}`;
41138
41424
  `page-${pageIndex}`
41139
41425
  );
41140
41426
  }),
41427
+ pageStackVirtualSpacers.after.heightPx > 0 ? /* @__PURE__ */ jsx(
41428
+ "div",
41429
+ {
41430
+ "aria-hidden": "true",
41431
+ "data-docx-page-window-spacer": "after",
41432
+ style: {
41433
+ height: pageStackVirtualSpacers.after.heightPx,
41434
+ width: pageStackVirtualSpacers.after.widthPx,
41435
+ margin: "0 auto",
41436
+ pointerEvents: "none",
41437
+ visibility: hideDocumentUntilPaginationSettled ? "hidden" : void 0
41438
+ }
41439
+ }
41440
+ ) : null,
41141
41441
  !isReadOnly ? (() => {
41142
41442
  const hasCustomContextMenuState = Boolean(contextMenuState);
41143
41443
  const hasTableContextMenuState = Boolean(tableContextMenuState);
@@ -43032,16 +43332,20 @@ function useDocxModel(file) {
43032
43332
  }
43033
43333
  const docxFile = file;
43034
43334
  let isCurrent = true;
43335
+ const abortController = new AbortController();
43035
43336
  async function load() {
43036
43337
  setState({ isLoading: true });
43037
43338
  try {
43038
- const pkg = await parseDocx(docxFile);
43339
+ const { model } = await importDocxBuffer(docxFile, {
43340
+ signal: abortController.signal,
43341
+ transferBuffer: false
43342
+ });
43039
43343
  if (!isCurrent) {
43040
43344
  return;
43041
43345
  }
43042
43346
  setState({
43043
43347
  isLoading: false,
43044
- model: await buildDocModel(pkg)
43348
+ model
43045
43349
  });
43046
43350
  } catch (error) {
43047
43351
  if (!isCurrent) {
@@ -43056,6 +43360,7 @@ function useDocxModel(file) {
43056
43360
  void load();
43057
43361
  return () => {
43058
43362
  isCurrent = false;
43363
+ abortController.abort();
43059
43364
  };
43060
43365
  }, [file]);
43061
43366
  return state;
@@ -43395,6 +43700,7 @@ export {
43395
43700
  updateTableCellParagraphTextRecursive,
43396
43701
  updateTableCellText,
43397
43702
  useDocxBorders,
43703
+ useDocxComments,
43398
43704
  useDocxDocumentTheme,
43399
43705
  useDocxEditor,
43400
43706
  useDocxFormFields,