@extend-ai/react-docx 0.7.0-alpha.7 → 0.7.0-alpha.8

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
@@ -3160,6 +3160,14 @@ var THUMBNAIL_EXCLUDED_CLONE_SELECTOR = [
3160
3160
  var THUMBNAIL_IMAGE_DOWNSCALE_MIN_DATA_URI_LENGTH = 32768;
3161
3161
  var THUMBNAIL_IMAGE_DOWNSCALE_MAX_DIMENSION_PX = 512;
3162
3162
  var THUMBNAIL_IMAGE_JPEG_QUALITY = 0.78;
3163
+ var THUMBNAIL_DIRECT_DEFAULT_FONT_FAMILY = "Calibri, Arial, sans-serif";
3164
+ var THUMBNAIL_DIRECT_DEFAULT_TEXT_COLOR = "#111827";
3165
+ var THUMBNAIL_DIRECT_TABLE_BORDER_COLOR = "#d1d5db";
3166
+ var THUMBNAIL_DIRECT_IMAGE_BACKGROUND = "#f3f4f6";
3167
+ var THUMBNAIL_DIRECT_MAX_ELEMENTS = 320;
3168
+ var THUMBNAIL_DIRECT_MAX_TEXT_CHARS = 640;
3169
+ var THUMBNAIL_DIRECT_MAX_LINES = 14;
3170
+ var THUMBNAIL_DIRECT_MAX_LAYOUT_LINES = 80;
3163
3171
  function thumbnailSvgDataUri(svg) {
3164
3172
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
3165
3173
  }
@@ -3223,6 +3231,346 @@ function getDownscaledThumbnailImageDataUri(src) {
3223
3231
  downscaledThumbnailImageCache.set(src, pending);
3224
3232
  return pending;
3225
3233
  }
3234
+ function directThumbnailPositivePx(value, fallback = 1) {
3235
+ return Number.isFinite(value) && value > 0 ? Math.max(1, Number(value)) : fallback;
3236
+ }
3237
+ function setCanvasFillStyle(context, color, fallback) {
3238
+ try {
3239
+ context.fillStyle = color || fallback;
3240
+ } catch {
3241
+ context.fillStyle = fallback;
3242
+ }
3243
+ }
3244
+ function setCanvasStrokeStyle(context, color, fallback) {
3245
+ try {
3246
+ context.strokeStyle = color || fallback;
3247
+ } catch {
3248
+ context.strokeStyle = fallback;
3249
+ }
3250
+ }
3251
+ function directThumbnailFont(run, fallbackFontSizePx) {
3252
+ const fontSizePx = Math.max(
3253
+ 6,
3254
+ Math.min(
3255
+ 36,
3256
+ Math.round(
3257
+ directThumbnailPositivePx(run?.fontSizePx, fallbackFontSizePx)
3258
+ )
3259
+ )
3260
+ );
3261
+ const fontStyle = run?.italic ? "italic " : "";
3262
+ const fontWeight = run?.bold ? "700 " : "";
3263
+ return `${fontStyle}${fontWeight}${fontSizePx}px ${run?.fontFamily || THUMBNAIL_DIRECT_DEFAULT_FONT_FAMILY}`;
3264
+ }
3265
+ var THUMBNAIL_DIRECT_TOKEN_REGEX = /(\r\n|\n|\t|[^\S\r\n\t]+|[^\s\r\n\t]+)/g;
3266
+ var THUMBNAIL_DIRECT_LEADING_WHITESPACE_REGEX = /^\s/;
3267
+ var THUMBNAIL_DIRECT_TEXT_MEASURE_CACHE_MAX_ENTRIES = 4096;
3268
+ var directThumbnailTextMeasureCache = /* @__PURE__ */ new Map();
3269
+ function measureDirectThumbnailToken(context, font, text) {
3270
+ if (!text) {
3271
+ return 0;
3272
+ }
3273
+ const cacheKey = `${font}\0${text}`;
3274
+ const cached = directThumbnailTextMeasureCache.get(cacheKey);
3275
+ if (cached !== void 0) {
3276
+ return cached;
3277
+ }
3278
+ const width = context.measureText(text).width;
3279
+ if (directThumbnailTextMeasureCache.size >= THUMBNAIL_DIRECT_TEXT_MEASURE_CACHE_MAX_ENTRIES) {
3280
+ const oldestKey = directThumbnailTextMeasureCache.keys().next().value;
3281
+ if (oldestKey !== void 0) {
3282
+ directThumbnailTextMeasureCache.delete(oldestKey);
3283
+ }
3284
+ }
3285
+ directThumbnailTextMeasureCache.set(cacheKey, width);
3286
+ return width;
3287
+ }
3288
+ function appendDirectThumbnailTextLine(lines, currentSegments, currentWidthPx) {
3289
+ const line = {
3290
+ segments: currentSegments,
3291
+ widthPx: currentWidthPx
3292
+ };
3293
+ lines.push(line);
3294
+ return line;
3295
+ }
3296
+ function layoutDirectThumbnailTextRuns(params) {
3297
+ const { context, runs, fallbackFontSizePx } = params;
3298
+ const widthPx = Math.max(1, params.widthPx);
3299
+ const maxLineCount = Math.max(
3300
+ 1,
3301
+ Math.min(THUMBNAIL_DIRECT_MAX_LAYOUT_LINES, params.maxLineCount)
3302
+ );
3303
+ const lines = [];
3304
+ let currentSegments = [];
3305
+ let currentWidthPx = 0;
3306
+ let remainingChars = THUMBNAIL_DIRECT_MAX_TEXT_CHARS;
3307
+ const flushLine = () => {
3308
+ appendDirectThumbnailTextLine(lines, currentSegments, currentWidthPx);
3309
+ currentSegments = [];
3310
+ currentWidthPx = 0;
3311
+ };
3312
+ for (const run of runs) {
3313
+ if (lines.length >= maxLineCount || remainingChars <= 0) {
3314
+ break;
3315
+ }
3316
+ const text = run.text.slice(0, remainingChars);
3317
+ remainingChars -= text.length;
3318
+ const runFont = directThumbnailFont(run, fallbackFontSizePx);
3319
+ context.font = runFont;
3320
+ const tokens = text.match(THUMBNAIL_DIRECT_TOKEN_REGEX) ?? [];
3321
+ for (const token of tokens) {
3322
+ if (lines.length >= maxLineCount) {
3323
+ break;
3324
+ }
3325
+ if (token === "\n" || token === "\r\n") {
3326
+ flushLine();
3327
+ continue;
3328
+ }
3329
+ const drawableToken = token === " " ? " " : token;
3330
+ const tokenWidthPx = measureDirectThumbnailToken(
3331
+ context,
3332
+ runFont,
3333
+ drawableToken
3334
+ );
3335
+ const tokenIsWhitespace = THUMBNAIL_DIRECT_LEADING_WHITESPACE_REGEX.test(drawableToken);
3336
+ if (currentSegments.length > 0 && currentWidthPx + tokenWidthPx > widthPx && !tokenIsWhitespace) {
3337
+ flushLine();
3338
+ }
3339
+ if (currentSegments.length === 0 && tokenIsWhitespace) {
3340
+ continue;
3341
+ }
3342
+ currentSegments.push({
3343
+ run,
3344
+ text: drawableToken,
3345
+ widthPx: tokenWidthPx,
3346
+ font: runFont
3347
+ });
3348
+ currentWidthPx += tokenWidthPx;
3349
+ }
3350
+ }
3351
+ if (currentSegments.length > 0 || lines.length === 0) {
3352
+ flushLine();
3353
+ }
3354
+ return lines;
3355
+ }
3356
+ function directThumbnailAlignedX(params) {
3357
+ const { xPx, widthPx, lineWidthPx, align } = params;
3358
+ if (align === "center") {
3359
+ return xPx + Math.max(0, (widthPx - lineWidthPx) / 2);
3360
+ }
3361
+ if (align === "right") {
3362
+ return xPx + Math.max(0, widthPx - lineWidthPx);
3363
+ }
3364
+ return xPx;
3365
+ }
3366
+ function drawDirectThumbnailTextRuns(params) {
3367
+ const {
3368
+ context,
3369
+ runs,
3370
+ xPx,
3371
+ yPx,
3372
+ widthPx,
3373
+ heightPx,
3374
+ align,
3375
+ startLineIndex
3376
+ } = params;
3377
+ const safeWidthPx = Math.max(1, widthPx);
3378
+ const safeHeightPx = Math.max(1, heightPx);
3379
+ const fallbackFontSizePx = Math.max(
3380
+ 7,
3381
+ Math.min(
3382
+ 20,
3383
+ Math.round(
3384
+ runs.find((run) => Number.isFinite(run.fontSizePx))?.fontSizePx ?? 12
3385
+ )
3386
+ )
3387
+ );
3388
+ const lineHeightPx = Math.max(
3389
+ fallbackFontSizePx + 1,
3390
+ Math.round(params.lineHeightPx ?? fallbackFontSizePx * 1.25)
3391
+ );
3392
+ const skippedLineCount = Math.max(
3393
+ 0,
3394
+ Math.min(THUMBNAIL_DIRECT_MAX_LAYOUT_LINES - 1, Math.trunc(startLineIndex ?? 0))
3395
+ );
3396
+ const visibleLineCount = Math.max(
3397
+ 1,
3398
+ Math.min(
3399
+ THUMBNAIL_DIRECT_MAX_LINES,
3400
+ Math.ceil(safeHeightPx / Math.max(1, lineHeightPx)) + 1
3401
+ )
3402
+ );
3403
+ const lines = layoutDirectThumbnailTextRuns({
3404
+ context,
3405
+ runs,
3406
+ widthPx: safeWidthPx,
3407
+ fallbackFontSizePx,
3408
+ maxLineCount: skippedLineCount + visibleLineCount
3409
+ }).slice(skippedLineCount, skippedLineCount + visibleLineCount);
3410
+ context.save();
3411
+ context.beginPath();
3412
+ context.rect(xPx, yPx, safeWidthPx, safeHeightPx);
3413
+ context.clip();
3414
+ context.textBaseline = "alphabetic";
3415
+ let lastAppliedFont;
3416
+ lines.forEach((line, lineIndex) => {
3417
+ const lineTopPx = yPx + lineIndex * lineHeightPx;
3418
+ if (lineTopPx > yPx + safeHeightPx) {
3419
+ return;
3420
+ }
3421
+ let cursorXPx = directThumbnailAlignedX({
3422
+ xPx,
3423
+ widthPx: safeWidthPx,
3424
+ lineWidthPx: line.widthPx,
3425
+ align
3426
+ });
3427
+ const baselineYPx = lineTopPx + Math.max(1, Math.round(lineHeightPx * 0.78));
3428
+ line.segments.forEach((segment) => {
3429
+ const segmentWidthPx = segment.widthPx;
3430
+ if (segment.run.backgroundColor) {
3431
+ setCanvasFillStyle(context, segment.run.backgroundColor, "transparent");
3432
+ context.fillRect(cursorXPx, lineTopPx + 1, segmentWidthPx, lineHeightPx);
3433
+ }
3434
+ if (segment.font !== lastAppliedFont) {
3435
+ context.font = segment.font;
3436
+ lastAppliedFont = segment.font;
3437
+ }
3438
+ setCanvasFillStyle(
3439
+ context,
3440
+ segment.run.color,
3441
+ THUMBNAIL_DIRECT_DEFAULT_TEXT_COLOR
3442
+ );
3443
+ context.fillText(segment.text, cursorXPx, baselineYPx);
3444
+ cursorXPx += segmentWidthPx;
3445
+ });
3446
+ });
3447
+ context.restore();
3448
+ }
3449
+ function drawDirectThumbnailParagraph(context, paragraph) {
3450
+ const xPx = Math.round(paragraph.xPx);
3451
+ const yPx = Math.round(paragraph.yPx);
3452
+ const widthPx = Math.max(1, Math.round(paragraph.widthPx));
3453
+ const heightPx = Math.max(1, Math.round(paragraph.heightPx));
3454
+ if (paragraph.backgroundColor) {
3455
+ setCanvasFillStyle(context, paragraph.backgroundColor, "transparent");
3456
+ context.fillRect(xPx, yPx, widthPx, heightPx);
3457
+ }
3458
+ drawDirectThumbnailTextRuns({
3459
+ context,
3460
+ runs: paragraph.runs,
3461
+ xPx: xPx + 1,
3462
+ yPx,
3463
+ widthPx: Math.max(1, widthPx - 2),
3464
+ heightPx,
3465
+ align: paragraph.align,
3466
+ lineHeightPx: paragraph.lineHeightPx,
3467
+ startLineIndex: paragraph.startLineIndex
3468
+ });
3469
+ }
3470
+ function drawDirectThumbnailImagePlaceholder(context, image, hairlineSourcePx) {
3471
+ const xPx = Math.round(image.xPx);
3472
+ const yPx = Math.round(image.yPx);
3473
+ const widthPx = Math.max(1, Math.round(image.widthPx));
3474
+ const heightPx = Math.max(1, Math.round(image.heightPx));
3475
+ setCanvasFillStyle(
3476
+ context,
3477
+ image.backgroundColor,
3478
+ THUMBNAIL_DIRECT_IMAGE_BACKGROUND
3479
+ );
3480
+ context.fillRect(xPx, yPx, widthPx, heightPx);
3481
+ setCanvasStrokeStyle(
3482
+ context,
3483
+ image.borderColor,
3484
+ THUMBNAIL_DIRECT_TABLE_BORDER_COLOR
3485
+ );
3486
+ context.lineWidth = hairlineSourcePx;
3487
+ context.strokeRect(xPx, yPx, widthPx, heightPx);
3488
+ }
3489
+ function drawDirectThumbnailTable(context, table, hairlineSourcePx) {
3490
+ const tableXPx = Math.round(table.xPx);
3491
+ const tableYPx = Math.round(table.yPx);
3492
+ const tableWidthPx = Math.max(1, Math.round(table.widthPx));
3493
+ const tableHeightPx = Math.max(1, Math.round(table.heightPx));
3494
+ context.save();
3495
+ context.beginPath();
3496
+ context.rect(tableXPx, tableYPx, tableWidthPx, tableHeightPx);
3497
+ context.clip();
3498
+ setCanvasStrokeStyle(
3499
+ context,
3500
+ table.borderColor,
3501
+ THUMBNAIL_DIRECT_TABLE_BORDER_COLOR
3502
+ );
3503
+ context.lineWidth = hairlineSourcePx;
3504
+ table.cells.forEach((cell) => {
3505
+ const xPx = tableXPx + Math.round(cell.xPx);
3506
+ const yPx = tableYPx + Math.round(cell.yPx);
3507
+ const widthPx = Math.max(1, Math.round(cell.widthPx));
3508
+ const heightPx = Math.max(1, Math.round(cell.heightPx));
3509
+ if (cell.backgroundColor) {
3510
+ setCanvasFillStyle(context, cell.backgroundColor, "transparent");
3511
+ context.fillRect(xPx, yPx, widthPx, heightPx);
3512
+ }
3513
+ context.strokeRect(xPx, yPx, widthPx, heightPx);
3514
+ if (cell.runs?.length) {
3515
+ drawDirectThumbnailTextRuns({
3516
+ context,
3517
+ runs: cell.runs,
3518
+ xPx: xPx + 3,
3519
+ yPx: yPx + 2,
3520
+ widthPx: Math.max(1, widthPx - 6),
3521
+ heightPx: Math.max(1, heightPx - 4),
3522
+ lineHeightPx: 13
3523
+ });
3524
+ }
3525
+ });
3526
+ context.restore();
3527
+ }
3528
+ function renderDocxThumbnailSnapshotSurface(params) {
3529
+ if (typeof document === "undefined") {
3530
+ throw new Error("DOCX thumbnails require a browser environment.");
3531
+ }
3532
+ const sourceWidthPx = directThumbnailPositivePx(params.snapshot.sourceWidthPx);
3533
+ const sourceHeightPx = directThumbnailPositivePx(params.snapshot.sourceHeightPx);
3534
+ const pixelWidthPx = Math.max(1, Math.round(params.pixelWidthPx));
3535
+ const pixelHeightPx = Math.max(1, Math.round(params.pixelHeightPx));
3536
+ const surface = document.createElement("canvas");
3537
+ surface.width = pixelWidthPx;
3538
+ surface.height = pixelHeightPx;
3539
+ const context = surface.getContext("2d");
3540
+ if (!context) {
3541
+ throw new Error("2D canvas context is unavailable for DOCX thumbnails.");
3542
+ }
3543
+ const scaleX = pixelWidthPx / sourceWidthPx;
3544
+ const scaleY = pixelHeightPx / sourceHeightPx;
3545
+ const hairlineSourcePx = Math.max(0.75, 1 / Math.max(scaleX, scaleY));
3546
+ context.setTransform(scaleX, 0, 0, scaleY, 0, 0);
3547
+ context.imageSmoothingEnabled = true;
3548
+ context.imageSmoothingQuality = "high";
3549
+ setCanvasFillStyle(
3550
+ context,
3551
+ params.snapshot.pageBackgroundColor,
3552
+ "#ffffff"
3553
+ );
3554
+ context.fillRect(0, 0, sourceWidthPx, sourceHeightPx);
3555
+ params.snapshot.elements.slice(0, THUMBNAIL_DIRECT_MAX_ELEMENTS).forEach((element) => {
3556
+ switch (element.kind) {
3557
+ case "paragraph":
3558
+ drawDirectThumbnailParagraph(context, element);
3559
+ break;
3560
+ case "image-placeholder":
3561
+ drawDirectThumbnailImagePlaceholder(
3562
+ context,
3563
+ element,
3564
+ hairlineSourcePx
3565
+ );
3566
+ break;
3567
+ case "table":
3568
+ drawDirectThumbnailTable(context, element, hairlineSourcePx);
3569
+ break;
3570
+ }
3571
+ });
3572
+ return surface;
3573
+ }
3226
3574
  async function buildDocxThumbnailSvgMarkup(params) {
3227
3575
  const { pageElement, sourceWidthPx, sourceHeightPx, widthPx, heightPx } = params;
3228
3576
  const clone = pageElement.cloneNode(true);
@@ -3284,16 +3632,33 @@ async function rasterizeDocxThumbnailSurface(params) {
3284
3632
  return surface;
3285
3633
  }
3286
3634
  function blitDocxThumbnailSurface(surface, canvas, resolution) {
3287
- canvas.width = Math.max(1, Math.round(resolution.pixelWidthPx));
3288
- canvas.height = Math.max(1, Math.round(resolution.pixelHeightPx));
3289
- canvas.style.width = `${Math.max(1, Math.round(resolution.widthPx))}px`;
3290
- canvas.style.height = `${Math.max(1, Math.round(resolution.heightPx))}px`;
3635
+ const pixelWidth = Math.max(1, Math.round(resolution.pixelWidthPx));
3636
+ const pixelHeight = Math.max(1, Math.round(resolution.pixelHeightPx));
3637
+ const cssWidth = `${Math.max(1, Math.round(resolution.widthPx))}px`;
3638
+ const cssHeight = `${Math.max(1, Math.round(resolution.heightPx))}px`;
3639
+ let bufferResized = false;
3640
+ if (canvas.width !== pixelWidth) {
3641
+ canvas.width = pixelWidth;
3642
+ bufferResized = true;
3643
+ }
3644
+ if (canvas.height !== pixelHeight) {
3645
+ canvas.height = pixelHeight;
3646
+ bufferResized = true;
3647
+ }
3648
+ if (canvas.style.width !== cssWidth) {
3649
+ canvas.style.width = cssWidth;
3650
+ }
3651
+ if (canvas.style.height !== cssHeight) {
3652
+ canvas.style.height = cssHeight;
3653
+ }
3291
3654
  const context = canvas.getContext("2d");
3292
3655
  if (!context) {
3293
3656
  throw new Error("2D canvas context is unavailable for DOCX thumbnails.");
3294
3657
  }
3295
3658
  context.setTransform(1, 0, 0, 1, 0, 0);
3296
- context.clearRect(0, 0, canvas.width, canvas.height);
3659
+ if (!bufferResized) {
3660
+ context.clearRect(0, 0, canvas.width, canvas.height);
3661
+ }
3297
3662
  context.drawImage(surface, 0, 0, canvas.width, canvas.height);
3298
3663
  }
3299
3664
  var DocxThumbnailSurfaceCache = class {
@@ -3368,6 +3733,7 @@ var SerialIdleTaskQueue = class {
3368
3733
  now;
3369
3734
  pumpScheduled = false;
3370
3735
  running = false;
3736
+ nextSequence = 0;
3371
3737
  constructor(options) {
3372
3738
  this.scheduleTask = options?.scheduleTask ?? defaultScheduleTask;
3373
3739
  this.scheduleDelayed = options?.scheduleDelayed ?? defaultScheduleDelayed;
@@ -3377,14 +3743,23 @@ var SerialIdleTaskQueue = class {
3377
3743
  get pendingCount() {
3378
3744
  return this.pending.length;
3379
3745
  }
3380
- enqueue(key, run) {
3746
+ enqueue(key, run, options) {
3747
+ const priority = Number.isFinite(options?.priority) ? Number(options?.priority) : 0;
3381
3748
  return new Promise((resolve) => {
3382
3749
  const existing = this.pending.find((entry) => entry.key === key);
3383
3750
  if (existing) {
3384
3751
  existing.run = run;
3385
3752
  existing.resolvers.push(resolve);
3753
+ existing.priority = Math.min(existing.priority, priority);
3386
3754
  } else {
3387
- this.pending.push({ key, run, resolvers: [resolve] });
3755
+ this.pending.push({
3756
+ key,
3757
+ run,
3758
+ resolvers: [resolve],
3759
+ priority,
3760
+ sequence: this.nextSequence
3761
+ });
3762
+ this.nextSequence += 1;
3388
3763
  }
3389
3764
  this.schedulePump();
3390
3765
  });
@@ -3429,6 +3804,8 @@ var SerialIdleTaskQueue = class {
3429
3804
  }
3430
3805
  const now = this.now();
3431
3806
  let earliestWaitMs;
3807
+ let bestIndex = -1;
3808
+ let bestEntry;
3432
3809
  for (let index = 0; index < this.pending.length; index += 1) {
3433
3810
  const candidate = this.pending[index];
3434
3811
  if (!candidate) {
@@ -3437,11 +3814,18 @@ var SerialIdleTaskQueue = class {
3437
3814
  const lastRunAt = this.lastRunAtByKey.get(candidate.key);
3438
3815
  const waitMs = lastRunAt === void 0 ? 0 : lastRunAt + this.minTaskIntervalMs - now;
3439
3816
  if (waitMs <= 0) {
3440
- this.pending.splice(index, 1);
3441
- return { entry: candidate };
3817
+ if (!bestEntry || candidate.priority < bestEntry.priority || candidate.priority === bestEntry.priority && candidate.sequence < bestEntry.sequence) {
3818
+ bestEntry = candidate;
3819
+ bestIndex = index;
3820
+ }
3821
+ continue;
3442
3822
  }
3443
3823
  earliestWaitMs = earliestWaitMs === void 0 ? waitMs : Math.min(earliestWaitMs, waitMs);
3444
3824
  }
3825
+ if (bestEntry && bestIndex >= 0) {
3826
+ this.pending.splice(bestIndex, 1);
3827
+ return { entry: bestEntry };
3828
+ }
3445
3829
  return earliestWaitMs === void 0 ? void 0 : { retryDelayMs: earliestWaitMs };
3446
3830
  }
3447
3831
  async runNext() {
@@ -22440,13 +22824,14 @@ function ensureDocxViewerPageSurfaceRegistry(editor) {
22440
22824
  pageElements: /* @__PURE__ */ new Map(),
22441
22825
  pageContentKeys: /* @__PURE__ */ new Map(),
22442
22826
  pageSizes: /* @__PURE__ */ new Map(),
22827
+ pageThumbnailSnapshots: /* @__PURE__ */ new Map(),
22443
22828
  listeners: /* @__PURE__ */ new Set()
22444
22829
  };
22445
22830
  docxViewerPageSurfaceRegistryByEditor.set(owner, registry);
22446
22831
  }
22447
22832
  return registry;
22448
22833
  }
22449
- function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage, pageSizesByPage = []) {
22834
+ function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage, pageSizesByPage = [], thumbnailSnapshotsByPage = []) {
22450
22835
  const registry = ensureDocxViewerPageSurfaceRegistry(editor);
22451
22836
  let changed = false;
22452
22837
  contentKeysByPage.forEach((contentKey, pageIndex) => {
@@ -22464,6 +22849,20 @@ function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage, pageSiz
22464
22849
  changed = true;
22465
22850
  }
22466
22851
  });
22852
+ thumbnailSnapshotsByPage.forEach((snapshot, pageIndex) => {
22853
+ const previous = registry.pageThumbnailSnapshots.get(pageIndex);
22854
+ if (!snapshot) {
22855
+ if (previous) {
22856
+ registry.pageThumbnailSnapshots.delete(pageIndex);
22857
+ changed = true;
22858
+ }
22859
+ return;
22860
+ }
22861
+ if (previous?.key !== snapshot.key) {
22862
+ registry.pageThumbnailSnapshots.set(pageIndex, snapshot);
22863
+ changed = true;
22864
+ }
22865
+ });
22467
22866
  registry.pageContentKeys.forEach((_, pageIndex) => {
22468
22867
  if (pageIndex >= contentKeysByPage.length) {
22469
22868
  registry.pageContentKeys.delete(pageIndex);
@@ -22476,6 +22875,12 @@ function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage, pageSiz
22476
22875
  changed = true;
22477
22876
  }
22478
22877
  });
22878
+ registry.pageThumbnailSnapshots.forEach((_, pageIndex) => {
22879
+ if (pageIndex >= thumbnailSnapshotsByPage.length) {
22880
+ registry.pageThumbnailSnapshots.delete(pageIndex);
22881
+ changed = true;
22882
+ }
22883
+ });
22479
22884
  if (changed) {
22480
22885
  notifyDocxViewerPageSurfaceSubscribers(registry);
22481
22886
  }
@@ -22556,6 +22961,359 @@ function resolveDocxViewerPageSurfaceSize(element, fallbackWidthPx, fallbackHeig
22556
22961
  heightPx: Math.max(1, Math.round(fallbackHeightPx))
22557
22962
  };
22558
22963
  }
22964
+ var DOCX_DIRECT_THUMBNAIL_MAX_ELEMENTS_PER_PAGE = 260;
22965
+ var DOCX_DIRECT_THUMBNAIL_MAX_TEXT_RUNS = 28;
22966
+ var DOCX_DIRECT_THUMBNAIL_MAX_TEXT_CHARS = 900;
22967
+ var DOCX_DIRECT_THUMBNAIL_MAX_TABLE_CELLS = 220;
22968
+ var DOCX_DIRECT_THUMBNAIL_MAX_CELL_TEXT_CHARS = 120;
22969
+ function docxThumbnailCssNumber(value) {
22970
+ if (typeof value === "number" && Number.isFinite(value)) {
22971
+ return value;
22972
+ }
22973
+ if (typeof value === "string") {
22974
+ const parsed = Number.parseFloat(value);
22975
+ return Number.isFinite(parsed) ? parsed : 0;
22976
+ }
22977
+ return 0;
22978
+ }
22979
+ function normalizeDocxThumbnailColor(value) {
22980
+ const normalized = value?.trim();
22981
+ if (!normalized || normalized.toLowerCase() === "auto") {
22982
+ return void 0;
22983
+ }
22984
+ if (/^[0-9a-fA-F]{6}$/.test(normalized)) {
22985
+ return `#${normalized}`;
22986
+ }
22987
+ return normalized;
22988
+ }
22989
+ function docxThumbnailTextRunStylesMatch(left, right) {
22990
+ return left.bold === right.bold && left.italic === right.italic && left.color === right.color && left.backgroundColor === right.backgroundColor && left.fontSizePx === right.fontSizePx && left.fontFamily === right.fontFamily;
22991
+ }
22992
+ function appendDocxThumbnailTextRun(runs, run, remaining) {
22993
+ if (remaining.chars <= 0 || runs.length >= DOCX_DIRECT_THUMBNAIL_MAX_TEXT_RUNS) {
22994
+ return;
22995
+ }
22996
+ const text = run.text.slice(0, remaining.chars);
22997
+ if (!text) {
22998
+ return;
22999
+ }
23000
+ remaining.chars -= text.length;
23001
+ const nextRun = { ...run, text };
23002
+ const previous = runs[runs.length - 1];
23003
+ if (previous && docxThumbnailTextRunStylesMatch(previous, nextRun)) {
23004
+ previous.text += nextRun.text;
23005
+ return;
23006
+ }
23007
+ runs.push(nextRun);
23008
+ }
23009
+ function docxThumbnailFallbackHeadingRunStyle(paragraph) {
23010
+ const headingLevel = paragraph.style?.headingLevel;
23011
+ return headingLevel && headingLevel >= 1 && headingLevel <= 6 ? DEFAULT_WORD_HEADING_RUN_STYLES[headingLevel] : void 0;
23012
+ }
23013
+ function docxThumbnailTextRunsFromParagraph(paragraph, documentTheme, maxChars = DOCX_DIRECT_THUMBNAIL_MAX_TEXT_CHARS) {
23014
+ const runs = [];
23015
+ const remaining = { chars: maxChars };
23016
+ const fallbackHeadingStyle = docxThumbnailFallbackHeadingRunStyle(paragraph);
23017
+ const fallbackFontFamily = cssFontFamily(fallbackHeadingStyle?.fontFamily) ?? cssFontFamily(paragraphDominantFontFamily(paragraph));
23018
+ paragraph.children.forEach((child) => {
23019
+ if (remaining.chars <= 0) {
23020
+ return;
23021
+ }
23022
+ const style = child.type === "text" || child.type === "form-field" ? child.style : void 0;
23023
+ const text = child.type === "text" ? child.text : child.type === "form-field" ? formFieldDisplayValue2(child) : child.type === "image" ? child.alt || "[image]" : "";
23024
+ appendDocxThumbnailTextRun(
23025
+ runs,
23026
+ {
23027
+ text,
23028
+ bold: style?.bold ?? fallbackHeadingStyle?.bold,
23029
+ italic: style?.italic ?? fallbackHeadingStyle?.italic,
23030
+ color: normalizeDocxThumbnailColor(
23031
+ themedRunColor(style?.color ?? fallbackHeadingStyle?.color, documentTheme)
23032
+ ),
23033
+ backgroundColor: normalizeDocxThumbnailColor(
23034
+ style?.backgroundColor ?? resolveHighlightColor(style?.highlight)
23035
+ ),
23036
+ fontSizePx: style?.fontSizePt && style.fontSizePt > 0 ? Math.max(6, style.fontSizePt * 96 / 72) : fallbackHeadingStyle?.fontSizePt ? Math.max(6, fallbackHeadingStyle.fontSizePt * 96 / 72) : paragraphBaseFontSizePx(paragraph),
23037
+ fontFamily: cssFontFamily(style?.fontFamily) ?? fallbackFontFamily
23038
+ },
23039
+ remaining
23040
+ );
23041
+ });
23042
+ return runs;
23043
+ }
23044
+ function docxThumbnailCellTextRuns(cell, documentTheme) {
23045
+ const paragraph = tableCellParagraphsRecursively(cell.nodes).find(
23046
+ (candidate) => paragraphText(candidate).trim().length > 0
23047
+ );
23048
+ if (!paragraph) {
23049
+ return void 0;
23050
+ }
23051
+ const runs = docxThumbnailTextRunsFromParagraph(
23052
+ paragraph,
23053
+ documentTheme,
23054
+ DOCX_DIRECT_THUMBNAIL_MAX_CELL_TEXT_CHARS
23055
+ );
23056
+ return runs.length > 0 ? runs : void 0;
23057
+ }
23058
+ function buildDocxThumbnailParagraphElements(params) {
23059
+ const {
23060
+ paragraph,
23061
+ segment,
23062
+ contentLeftPx,
23063
+ contentWidthPx,
23064
+ yPx,
23065
+ heightPx,
23066
+ numberingDefinitions,
23067
+ docGridLinePitchPx,
23068
+ documentTheme
23069
+ } = params;
23070
+ const blockStyle = paragraphBlockStyle(
23071
+ paragraph,
23072
+ numberingDefinitions,
23073
+ void 0,
23074
+ docGridLinePitchPx
23075
+ );
23076
+ const paragraphLineRange = segment.paragraphLineRange;
23077
+ const marginTopPx = paragraphLineRange && paragraphLineRange.startLineIndex > 0 ? 0 : Math.max(0, docxThumbnailCssNumber(blockStyle.marginTop));
23078
+ const marginBottomPx = paragraphLineRange && paragraphLineRange.endLineIndex < paragraphLineRange.totalLineCount ? 0 : Math.max(0, docxThumbnailCssNumber(blockStyle.marginBottom));
23079
+ const marginLeftPx = docxThumbnailCssNumber(blockStyle.marginLeft);
23080
+ const marginRightPx = Math.max(0, docxThumbnailCssNumber(blockStyle.marginRight));
23081
+ const xPx = contentLeftPx + marginLeftPx;
23082
+ const widthPx = Math.max(8, contentWidthPx - marginLeftPx - marginRightPx);
23083
+ const bodyYPx = yPx + marginTopPx;
23084
+ const bodyHeightPx = Math.max(1, heightPx - marginTopPx - marginBottomPx);
23085
+ const runs = docxThumbnailTextRunsFromParagraph(paragraph, documentTheme);
23086
+ const elements = [];
23087
+ elements.push({
23088
+ kind: "paragraph",
23089
+ xPx,
23090
+ yPx: bodyYPx,
23091
+ widthPx,
23092
+ heightPx: bodyHeightPx,
23093
+ align: paragraph.style?.align,
23094
+ backgroundColor: normalizeDocxThumbnailColor(
23095
+ paragraph.style?.backgroundColor
23096
+ ),
23097
+ lineHeightPx: paragraphLineRange?.lineHeightPx ?? estimateParagraphLineHeightPx(paragraph, docGridLinePitchPx),
23098
+ startLineIndex: paragraphLineRange?.startLineIndex,
23099
+ runs
23100
+ });
23101
+ const hasVisibleText = runs.some((run) => run.text.trim().length > 0);
23102
+ if (!hasVisibleText) {
23103
+ const imageRuns = paragraph.children.filter(
23104
+ (child) => child.type === "image"
23105
+ );
23106
+ imageRuns.slice(0, 4).forEach((imageRun) => {
23107
+ const imageWidthPx = Math.max(18, imageRun.widthPx ?? widthPx * 0.5);
23108
+ const imageHeightPx = Math.max(18, imageRun.heightPx ?? bodyHeightPx * 0.5);
23109
+ const scale = Math.min(
23110
+ 1,
23111
+ (widthPx - 4) / imageWidthPx,
23112
+ (bodyHeightPx - 4) / imageHeightPx
23113
+ );
23114
+ elements.push({
23115
+ kind: "image-placeholder",
23116
+ xPx: xPx + 2,
23117
+ yPx: bodyYPx + 2,
23118
+ widthPx: Math.max(12, imageWidthPx * scale),
23119
+ heightPx: Math.max(12, imageHeightPx * scale)
23120
+ });
23121
+ });
23122
+ }
23123
+ return elements;
23124
+ }
23125
+ function buildDocxThumbnailTableElement(params) {
23126
+ const {
23127
+ table,
23128
+ segment,
23129
+ contentLeftPx,
23130
+ contentWidthPx,
23131
+ contentHeightPx,
23132
+ yPx,
23133
+ heightPx,
23134
+ numberingDefinitions,
23135
+ docGridLinePitchPx,
23136
+ documentTheme
23137
+ } = params;
23138
+ const columnCount = tableColumnCount(table);
23139
+ const tableIndentPx = twipsToSignedPixels(table.style?.indentTwips) ?? 0;
23140
+ const tableWidthPx = twipsToPixels(table.style?.widthTwips);
23141
+ const definedWidthsTwips = columnWidthsFromTableDefinition(table, columnCount);
23142
+ const rawTableColumnWidthsPx = definedWidthsTwips && definedWidthsTwips.length > 0 ? normalizeColumnWidthsPx(
23143
+ definedWidthsTwips.map((widthTwips) => twipsToPixels(widthTwips) ?? 0),
23144
+ columnCount,
23145
+ tableWidthPx,
23146
+ 1
23147
+ ) : defaultColumnWidthsPx(columnCount, tableWidthPx);
23148
+ const rawResolvedTableWidthPx = tableWidthPx ?? rawTableColumnWidthsPx.reduce((sum, widthPx) => sum + widthPx, 0);
23149
+ const maxTableWidthPx = Math.max(
23150
+ 24,
23151
+ contentWidthPx - tableIndentPx - resolveCollapsedTableHorizontalOuterBleedPx(table, columnCount)
23152
+ );
23153
+ const resolvedTableWidthPx = clampTableWidthPx(
23154
+ rawResolvedTableWidthPx,
23155
+ maxTableWidthPx
23156
+ );
23157
+ const { columnWidthsPx } = resolveFittedTableColumnWidths(
23158
+ table,
23159
+ rawTableColumnWidthsPx,
23160
+ resolvedTableWidthPx
23161
+ );
23162
+ const rowHeightsPx = estimateTableRowHeightsPx(
23163
+ table,
23164
+ contentWidthPx,
23165
+ numberingDefinitions,
23166
+ docGridLinePitchPx,
23167
+ contentHeightPx
23168
+ );
23169
+ const startRowIndex = Math.max(
23170
+ 0,
23171
+ segment.tableRowSlice?.rowIndex ?? segment.tableRowRange?.startRowIndex ?? 0
23172
+ );
23173
+ const endRowIndex = Math.min(
23174
+ table.rows.length,
23175
+ segment.tableRowSlice ? startRowIndex + 1 : segment.tableRowRange?.endRowIndex ?? table.rows.length
23176
+ );
23177
+ const cells = [];
23178
+ let rowYPx = segment.tableRowSlice ? -Math.max(0, segment.tableRowSlice.startOffsetPx) : 0;
23179
+ for (let rowIndex = startRowIndex; rowIndex < endRowIndex && cells.length < DOCX_DIRECT_THUMBNAIL_MAX_TABLE_CELLS; rowIndex += 1) {
23180
+ const row = table.rows[rowIndex];
23181
+ if (!row) {
23182
+ continue;
23183
+ }
23184
+ const rowHeightPx = segment.tableRowSlice && rowIndex === segment.tableRowSlice.rowIndex ? Math.max(1, segment.tableRowSlice.totalRowHeightPx) : Math.max(1, rowHeightsPx[rowIndex] ?? MIN_PARAGRAPH_LINE_HEIGHT_PX);
23185
+ let columnCursor = 0;
23186
+ row.cells.forEach((cell) => {
23187
+ if (cells.length >= DOCX_DIRECT_THUMBNAIL_MAX_TABLE_CELLS) {
23188
+ return;
23189
+ }
23190
+ const span = cell.style?.gridSpan && cell.style.gridSpan > 1 ? cell.style.gridSpan : 1;
23191
+ const xPx = columnWidthsPx.slice(0, columnCursor).reduce((sum, widthPx2) => sum + widthPx2, 0);
23192
+ const widthPx = columnWidthsPx.slice(columnCursor, columnCursor + span).reduce((sum, widthPx2) => sum + widthPx2, 0);
23193
+ columnCursor += span;
23194
+ cells.push({
23195
+ xPx,
23196
+ yPx: rowYPx,
23197
+ widthPx: Math.max(1, widthPx),
23198
+ heightPx: rowHeightPx,
23199
+ backgroundColor: normalizeDocxThumbnailColor(
23200
+ cell.style?.backgroundColor ?? row.style?.backgroundColor
23201
+ ),
23202
+ runs: docxThumbnailCellTextRuns(cell, documentTheme)
23203
+ });
23204
+ });
23205
+ rowYPx += rowHeightPx;
23206
+ }
23207
+ if (cells.length === 0) {
23208
+ return void 0;
23209
+ }
23210
+ return {
23211
+ kind: "table",
23212
+ xPx: contentLeftPx + tableIndentPx,
23213
+ yPx,
23214
+ widthPx: Math.max(1, resolvedTableWidthPx),
23215
+ heightPx: Math.max(1, heightPx),
23216
+ cells
23217
+ };
23218
+ }
23219
+ function buildDocxPageThumbnailRenderSnapshotEntries(params) {
23220
+ const {
23221
+ model,
23222
+ pageNodeSegmentsByPage,
23223
+ pageSectionInfoByIndex,
23224
+ contentKeysByPage,
23225
+ fallbackLayout,
23226
+ documentTheme,
23227
+ docGridLinePitchPxByNodeIndex,
23228
+ numberingDefinitions
23229
+ } = params;
23230
+ return pageNodeSegmentsByPage.map((pageSegments, pageIndex) => {
23231
+ const key = `${contentKeysByPage[pageIndex] ?? ""}|theme:${documentTheme}`;
23232
+ let cachedSnapshot;
23233
+ return {
23234
+ key,
23235
+ getSnapshot: () => {
23236
+ if (cachedSnapshot) {
23237
+ return cachedSnapshot;
23238
+ }
23239
+ const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? fallbackLayout;
23240
+ const contentLeftPx = pageLayout.marginsPx.left;
23241
+ const contentTopPx = pageLayout.marginsPx.top;
23242
+ const contentWidthPx = Math.max(
23243
+ 1,
23244
+ pageLayout.pageWidthPx - pageLayout.marginsPx.left - pageLayout.marginsPx.right
23245
+ );
23246
+ const contentHeightPx = Math.max(
23247
+ 1,
23248
+ pageLayout.pageHeightPx - pageLayout.marginsPx.top - pageLayout.marginsPx.bottom
23249
+ );
23250
+ const elements = [];
23251
+ let yPx = contentTopPx;
23252
+ for (const segment of pageSegments) {
23253
+ if (elements.length >= DOCX_DIRECT_THUMBNAIL_MAX_ELEMENTS_PER_PAGE) {
23254
+ break;
23255
+ }
23256
+ const node = model.nodes[segment.nodeIndex];
23257
+ if (!node) {
23258
+ continue;
23259
+ }
23260
+ const docGridLinePitchPx = docGridLinePitchPxByNodeIndex.get(
23261
+ segment.nodeIndex
23262
+ );
23263
+ const segmentHeightPx = estimateRenderedPageSegmentHeightPx(
23264
+ node,
23265
+ segment,
23266
+ model,
23267
+ contentWidthPx,
23268
+ numberingDefinitions,
23269
+ docGridLinePitchPx
23270
+ );
23271
+ if (node.type === "paragraph" && !segment.tableRowRange) {
23272
+ elements.push(
23273
+ ...buildDocxThumbnailParagraphElements({
23274
+ paragraph: node,
23275
+ segment,
23276
+ contentLeftPx,
23277
+ contentTopPx,
23278
+ contentWidthPx,
23279
+ yPx,
23280
+ heightPx: segmentHeightPx,
23281
+ numberingDefinitions,
23282
+ docGridLinePitchPx,
23283
+ documentTheme
23284
+ })
23285
+ );
23286
+ } else if (node.type === "table") {
23287
+ const tableElement = buildDocxThumbnailTableElement({
23288
+ table: node,
23289
+ segment,
23290
+ contentLeftPx,
23291
+ contentWidthPx,
23292
+ contentHeightPx,
23293
+ yPx,
23294
+ heightPx: segmentHeightPx,
23295
+ numberingDefinitions,
23296
+ docGridLinePitchPx,
23297
+ documentTheme
23298
+ });
23299
+ if (tableElement) {
23300
+ elements.push(tableElement);
23301
+ }
23302
+ }
23303
+ yPx += Math.max(1, segmentHeightPx);
23304
+ }
23305
+ cachedSnapshot = {
23306
+ key,
23307
+ sourceWidthPx: pageLayout.pageWidthPx,
23308
+ sourceHeightPx: pageLayout.pageHeightPx,
23309
+ pageBackgroundColor: documentTheme === "dark" ? "#111827" : "#ffffff",
23310
+ elements
23311
+ };
23312
+ return cachedSnapshot;
23313
+ }
23314
+ };
23315
+ });
23316
+ }
22559
23317
  function DocxDetachedThumbnailPageSurface({
22560
23318
  editor,
22561
23319
  pageIndex
@@ -22581,17 +23339,19 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
22581
23339
  host;
22582
23340
  root;
22583
23341
  activePageIndex;
23342
+ activeRenderKey;
22584
23343
  async renderPageSurface(params) {
22585
23344
  if (typeof document === "undefined" || typeof window === "undefined") {
22586
23345
  return void 0;
22587
23346
  }
22588
- const { editor, registry, pageIndex } = params;
23347
+ const { editor, registry, pageIndex, renderKey } = params;
22589
23348
  await this.ensureRoot();
22590
23349
  if (!this.root) {
22591
23350
  return void 0;
22592
23351
  }
22593
- if (this.activePageIndex !== pageIndex) {
23352
+ if (this.activePageIndex !== pageIndex || this.activeRenderKey !== renderKey) {
22594
23353
  this.activePageIndex = pageIndex;
23354
+ this.activeRenderKey = renderKey;
22595
23355
  this.root.render(
22596
23356
  /* @__PURE__ */ jsx(
22597
23357
  DocxDetachedThumbnailPageSurface,
@@ -22614,6 +23374,7 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
22614
23374
  }
22615
23375
  this.host = void 0;
22616
23376
  this.activePageIndex = void 0;
23377
+ this.activeRenderKey = void 0;
22617
23378
  }
22618
23379
  async ensureRoot() {
22619
23380
  if (this.root) {
@@ -22654,8 +23415,42 @@ var DocxDetachedThumbnailSurfaceRenderer = class {
22654
23415
  return pageElement?.isConnected ? pageElement : void 0;
22655
23416
  }
22656
23417
  };
22657
- var DOCX_THUMBNAIL_SURFACE_CACHE_MAX_ENTRIES = 32;
23418
+ var DOCX_THUMBNAIL_SURFACE_CACHE_MAX_ENTRIES = 64;
22658
23419
  var DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS = 200;
23420
+ var DOCX_THUMBNAIL_RENDER_PRIORITY_VISIBLE = 0;
23421
+ var DOCX_THUMBNAIL_RENDER_PRIORITY_ATTACHED = 1;
23422
+ var DOCX_THUMBNAIL_RENDER_PRIORITY_PREFETCH = 2;
23423
+ function normalizeDocxThumbnailMinRasterIntervalMs(value) {
23424
+ return Number.isFinite(value) && Number(value) >= 0 ? Number(value) : DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS;
23425
+ }
23426
+ function normalizeDocxThumbnailPageIndexes(indexes, totalPages) {
23427
+ if (!indexes?.length || totalPages <= 0) {
23428
+ return [];
23429
+ }
23430
+ const seen = /* @__PURE__ */ new Set();
23431
+ const normalized = [];
23432
+ indexes.forEach((pageIndex) => {
23433
+ if (!Number.isFinite(pageIndex)) {
23434
+ return;
23435
+ }
23436
+ const roundedPageIndex = Math.trunc(pageIndex);
23437
+ if (roundedPageIndex < 0 || roundedPageIndex >= totalPages || seen.has(roundedPageIndex)) {
23438
+ return;
23439
+ }
23440
+ seen.add(roundedPageIndex);
23441
+ normalized.push(roundedPageIndex);
23442
+ });
23443
+ return normalized;
23444
+ }
23445
+ function docxThumbnailPageIndexesKey(pageIndexes) {
23446
+ return pageIndexes.join(",");
23447
+ }
23448
+ function docxThumbnailCanvasQueueKey(canvasId) {
23449
+ return `canvas:${canvasId}`;
23450
+ }
23451
+ function docxThumbnailPrefetchQueueKey(pageIndex) {
23452
+ return `prefetch:${pageIndex}`;
23453
+ }
22659
23454
  function resolveDocxPageThumbnailResolution(options) {
22660
23455
  const safeSourceWidthPx = Math.max(1, Math.round(options.sourceWidthPx));
22661
23456
  const safeSourceHeightPx = Math.max(1, Math.round(options.sourceHeightPx));
@@ -22735,6 +23530,12 @@ function useDocxPageThumbnails(editor, options = {}) {
22735
23530
  const lastPaintedThumbnailKeyByCanvasRef = React.useRef(
22736
23531
  /* @__PURE__ */ new WeakMap()
22737
23532
  );
23533
+ const thumbnailQueueKeyByCanvasRef = React.useRef(
23534
+ /* @__PURE__ */ new WeakMap()
23535
+ );
23536
+ const nextThumbnailCanvasQueueIdRef = React.useRef(0);
23537
+ const queuedPrefetchThumbnailKeysRef = React.useRef(/* @__PURE__ */ new Set());
23538
+ const thumbnailMinRasterIntervalMs = normalizeDocxThumbnailMinRasterIntervalMs(options.minRasterIntervalMs);
22738
23539
  const ensureThumbnailSurfaceCache = React.useCallback(() => {
22739
23540
  if (!thumbnailSurfaceCacheRef.current) {
22740
23541
  thumbnailSurfaceCacheRef.current = new DocxThumbnailSurfaceCache(
@@ -22746,18 +23547,50 @@ function useDocxPageThumbnails(editor, options = {}) {
22746
23547
  const ensureThumbnailRasterQueue = React.useCallback(() => {
22747
23548
  if (!thumbnailRasterQueueRef.current) {
22748
23549
  thumbnailRasterQueueRef.current = new SerialIdleTaskQueue({
22749
- minTaskIntervalMs: DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS
23550
+ minTaskIntervalMs: thumbnailMinRasterIntervalMs
22750
23551
  });
22751
23552
  }
22752
23553
  return thumbnailRasterQueueRef.current;
22753
- }, []);
23554
+ }, [thumbnailMinRasterIntervalMs]);
23555
+ const thumbnailQueueKeyForCanvas = React.useCallback(
23556
+ (canvas) => {
23557
+ const existing = thumbnailQueueKeyByCanvasRef.current.get(canvas);
23558
+ if (existing) {
23559
+ return existing;
23560
+ }
23561
+ const nextKey = docxThumbnailCanvasQueueKey(
23562
+ nextThumbnailCanvasQueueIdRef.current
23563
+ );
23564
+ nextThumbnailCanvasQueueIdRef.current += 1;
23565
+ thumbnailQueueKeyByCanvasRef.current.set(canvas, nextKey);
23566
+ return nextKey;
23567
+ },
23568
+ []
23569
+ );
23570
+ React.useEffect(() => {
23571
+ thumbnailRasterQueueRef.current?.clear();
23572
+ thumbnailRasterQueueRef.current = void 0;
23573
+ queuedPrefetchThumbnailKeysRef.current.clear();
23574
+ }, [thumbnailMinRasterIntervalMs]);
22754
23575
  React.useEffect(() => {
22755
23576
  thumbnailSurfaceCacheRef.current?.clear();
22756
23577
  thumbnailRasterQueueRef.current?.clear();
22757
23578
  detachedThumbnailSurfaceRendererRef.current?.clear();
22758
23579
  detachedThumbnailSurfaceRendererRef.current = void 0;
22759
23580
  lastPaintedThumbnailKeyByCanvasRef.current = /* @__PURE__ */ new WeakMap();
23581
+ thumbnailQueueKeyByCanvasRef.current = /* @__PURE__ */ new WeakMap();
23582
+ nextThumbnailCanvasQueueIdRef.current = 0;
23583
+ queuedPrefetchThumbnailKeysRef.current.clear();
22760
23584
  }, [editor.documentLoadNonce, pageSurfaceRegistryOwner]);
23585
+ React.useEffect(() => {
23586
+ detachedThumbnailSurfaceRendererRef.current?.clear();
23587
+ detachedThumbnailSurfaceRendererRef.current = void 0;
23588
+ }, [
23589
+ editor.documentTheme,
23590
+ editor.model,
23591
+ editor.showComments,
23592
+ editor.showTrackedChanges
23593
+ ]);
22761
23594
  React.useEffect(
22762
23595
  () => () => {
22763
23596
  detachedThumbnailSurfaceRendererRef.current?.clear();
@@ -22782,6 +23615,125 @@ function useDocxPageThumbnails(editor, options = {}) {
22782
23615
  },
22783
23616
  [editor.documentTheme, pageSurfaceRegistry, thumbnailResolutionOptionsKey]
22784
23617
  );
23618
+ const totalThumbnailPages = Math.max(1, editor.totalPages);
23619
+ const visibleThumbnailPageIndexes = React.useMemo(
23620
+ () => normalizeDocxThumbnailPageIndexes(
23621
+ options.renderWindow?.visiblePageIndexes,
23622
+ totalThumbnailPages
23623
+ ),
23624
+ [options.renderWindow?.visiblePageIndexes, totalThumbnailPages]
23625
+ );
23626
+ const prefetchThumbnailPageIndexes = React.useMemo(
23627
+ () => normalizeDocxThumbnailPageIndexes(
23628
+ options.renderWindow?.prefetchPageIndexes,
23629
+ totalThumbnailPages
23630
+ ),
23631
+ [options.renderWindow?.prefetchPageIndexes, totalThumbnailPages]
23632
+ );
23633
+ const visibleThumbnailPageIndexesKey = docxThumbnailPageIndexesKey(
23634
+ visibleThumbnailPageIndexes
23635
+ );
23636
+ const prefetchThumbnailPageIndexesKey = docxThumbnailPageIndexesKey(
23637
+ prefetchThumbnailPageIndexes
23638
+ );
23639
+ const visibleThumbnailPageIndexSet = React.useMemo(
23640
+ () => new Set(visibleThumbnailPageIndexes),
23641
+ [visibleThumbnailPageIndexesKey]
23642
+ );
23643
+ const thumbnailRenderPriorityForPage = React.useCallback(
23644
+ (pageIndex, fallbackPriority = DOCX_THUMBNAIL_RENDER_PRIORITY_ATTACHED) => visibleThumbnailPageIndexSet.has(pageIndex) ? DOCX_THUMBNAIL_RENDER_PRIORITY_VISIBLE : fallbackPriority,
23645
+ [visibleThumbnailPageIndexSet]
23646
+ );
23647
+ const renderPageThumbnailSurface = React.useCallback(
23648
+ async (pageIndex, renderOptions) => {
23649
+ const force = renderOptions?.force === true;
23650
+ const runSkipKey = thumbnailSkipKeyForPage(pageIndex);
23651
+ const detachedRenderKey = [
23652
+ runSkipKey ?? `load:${editor.documentLoadNonce}`,
23653
+ editor.showComments ? "comments:1" : "comments:0",
23654
+ editor.showTrackedChanges ? "tracked:1" : "tracked:0"
23655
+ ].join("|");
23656
+ const thumbnailSnapshotEntry = pageSurfaceRegistry.pageThumbnailSnapshots.get(pageIndex);
23657
+ const fallbackSourceSize = resolveDocxViewerRegisteredPageSurfaceSize(
23658
+ pageSurfaceRegistry,
23659
+ pageIndex,
23660
+ fallbackLayout.pageWidthPx,
23661
+ fallbackLayout.pageHeightPx
23662
+ );
23663
+ const resolution = resolveDocxPageThumbnailResolution({
23664
+ sourceWidthPx: fallbackSourceSize.widthPx,
23665
+ sourceHeightPx: fallbackSourceSize.heightPx,
23666
+ resolution: options.resolution,
23667
+ maxWidthPx: options.maxWidthPx,
23668
+ maxHeightPx: options.maxHeightPx,
23669
+ pixelRatio: options.pixelRatio
23670
+ });
23671
+ const surfaceKey = runSkipKey === void 0 ? void 0 : `${runSkipKey}|${fallbackSourceSize.widthPx}x${fallbackSourceSize.heightPx}|${resolution.pixelWidthPx}x${resolution.pixelHeightPx}`;
23672
+ const surfaceCache = ensureThumbnailSurfaceCache();
23673
+ let surface = !force && surfaceKey !== void 0 ? surfaceCache.get(surfaceKey) : void 0;
23674
+ if (!surface) {
23675
+ const thumbnailSnapshot = thumbnailSnapshotEntry?.getSnapshot();
23676
+ if (thumbnailSnapshot) {
23677
+ surface = renderDocxThumbnailSnapshotSurface({
23678
+ snapshot: thumbnailSnapshot,
23679
+ widthPx: resolution.widthPx,
23680
+ heightPx: resolution.heightPx,
23681
+ pixelWidthPx: resolution.pixelWidthPx,
23682
+ pixelHeightPx: resolution.pixelHeightPx
23683
+ });
23684
+ if (surfaceKey !== void 0) {
23685
+ surfaceCache.set(surfaceKey, surface);
23686
+ }
23687
+ return { surface, resolution, runSkipKey };
23688
+ }
23689
+ let livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
23690
+ if (!livePageElement || !livePageElement.isConnected) {
23691
+ if (!detachedThumbnailSurfaceRendererRef.current) {
23692
+ detachedThumbnailSurfaceRendererRef.current = new DocxDetachedThumbnailSurfaceRenderer();
23693
+ }
23694
+ livePageElement = await detachedThumbnailSurfaceRendererRef.current.renderPageSurface({
23695
+ editor,
23696
+ registry: pageSurfaceRegistry,
23697
+ pageIndex,
23698
+ renderKey: detachedRenderKey
23699
+ });
23700
+ }
23701
+ if (!livePageElement || !livePageElement.isConnected) {
23702
+ return void 0;
23703
+ }
23704
+ const sourceSize = resolveDocxViewerPageSurfaceSize(
23705
+ livePageElement,
23706
+ fallbackSourceSize.widthPx,
23707
+ fallbackSourceSize.heightPx
23708
+ );
23709
+ surface = await rasterizeDocxThumbnailSurface({
23710
+ pageElement: livePageElement,
23711
+ sourceWidthPx: sourceSize.widthPx,
23712
+ sourceHeightPx: sourceSize.heightPx,
23713
+ widthPx: resolution.widthPx,
23714
+ heightPx: resolution.heightPx,
23715
+ pixelWidthPx: resolution.pixelWidthPx,
23716
+ pixelHeightPx: resolution.pixelHeightPx
23717
+ });
23718
+ if (surfaceKey !== void 0) {
23719
+ surfaceCache.set(surfaceKey, surface);
23720
+ }
23721
+ }
23722
+ return { surface, resolution, runSkipKey };
23723
+ },
23724
+ [
23725
+ ensureThumbnailSurfaceCache,
23726
+ fallbackLayout.pageHeightPx,
23727
+ fallbackLayout.pageWidthPx,
23728
+ options.resolution,
23729
+ options.maxHeightPx,
23730
+ options.maxWidthPx,
23731
+ options.pixelRatio,
23732
+ pageSurfaceRegistry,
23733
+ thumbnailSkipKeyForPage,
23734
+ editor
23735
+ ]
23736
+ );
22785
23737
  const renderPageThumbnailToCanvas = React.useCallback(
22786
23738
  async (pageIndex, canvas, renderOptions) => {
22787
23739
  if (options.disabled) {
@@ -22798,74 +23750,19 @@ function useDocxPageThumbnails(editor, options = {}) {
22798
23750
  updatePageThumbnailState(pageIndex, "ready");
22799
23751
  return;
22800
23752
  }
22801
- updatePageThumbnailState(pageIndex, "rendering");
22802
- await ensureThumbnailRasterQueue().enqueue(targetCanvas, async () => {
23753
+ const paintIntoTarget = async () => {
22803
23754
  if (requiresAttachedTarget && attachedCanvasByPageRef.current.get(pageIndex) !== targetCanvas) {
22804
23755
  return;
22805
23756
  }
22806
- const runSkipKey = thumbnailSkipKeyForPage(pageIndex);
22807
- const fallbackSourceSize = resolveDocxViewerRegisteredPageSurfaceSize(
22808
- pageSurfaceRegistry,
22809
- pageIndex,
22810
- fallbackLayout.pageWidthPx,
22811
- fallbackLayout.pageHeightPx
22812
- );
22813
- const resolution = resolveDocxPageThumbnailResolution({
22814
- sourceWidthPx: fallbackSourceSize.widthPx,
22815
- sourceHeightPx: fallbackSourceSize.heightPx,
22816
- resolution: options.resolution,
22817
- maxWidthPx: options.maxWidthPx,
22818
- maxHeightPx: options.maxHeightPx,
22819
- pixelRatio: options.pixelRatio
22820
- });
22821
- const surfaceKey = runSkipKey === void 0 ? void 0 : `${runSkipKey}|${fallbackSourceSize.widthPx}x${fallbackSourceSize.heightPx}|${resolution.pixelWidthPx}x${resolution.pixelHeightPx}`;
22822
- const surfaceCache = ensureThumbnailSurfaceCache();
22823
23757
  try {
22824
- let surface = !force && surfaceKey !== void 0 ? surfaceCache.get(surfaceKey) : void 0;
22825
- if (!surface) {
22826
- let livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22827
- let renderedDetachedSurface = false;
22828
- try {
22829
- if (!livePageElement || !livePageElement.isConnected) {
22830
- if (!detachedThumbnailSurfaceRendererRef.current) {
22831
- detachedThumbnailSurfaceRendererRef.current = new DocxDetachedThumbnailSurfaceRenderer();
22832
- }
22833
- livePageElement = await detachedThumbnailSurfaceRendererRef.current.renderPageSurface(
22834
- {
22835
- editor,
22836
- registry: pageSurfaceRegistry,
22837
- pageIndex
22838
- }
22839
- );
22840
- renderedDetachedSurface = true;
22841
- }
22842
- if (!livePageElement || !livePageElement.isConnected) {
22843
- updatePageThumbnailState(pageIndex, "unavailable");
22844
- return;
22845
- }
22846
- const sourceSize = resolveDocxViewerPageSurfaceSize(
22847
- livePageElement,
22848
- fallbackSourceSize.widthPx,
22849
- fallbackSourceSize.heightPx
22850
- );
22851
- surface = await rasterizeDocxThumbnailSurface({
22852
- pageElement: livePageElement,
22853
- sourceWidthPx: sourceSize.widthPx,
22854
- sourceHeightPx: sourceSize.heightPx,
22855
- widthPx: resolution.widthPx,
22856
- heightPx: resolution.heightPx,
22857
- pixelWidthPx: resolution.pixelWidthPx,
22858
- pixelHeightPx: resolution.pixelHeightPx
22859
- });
22860
- if (surfaceKey !== void 0) {
22861
- surfaceCache.set(surfaceKey, surface);
22862
- }
22863
- } finally {
22864
- if (renderedDetachedSurface) {
22865
- detachedThumbnailSurfaceRendererRef.current?.clear();
22866
- }
22867
- }
23758
+ const rendered = await renderPageThumbnailSurface(pageIndex, {
23759
+ force
23760
+ });
23761
+ if (!rendered) {
23762
+ updatePageThumbnailState(pageIndex, "unavailable");
23763
+ return;
22868
23764
  }
23765
+ const { surface, resolution, runSkipKey } = rendered;
22869
23766
  blitDocxThumbnailSurface(surface, targetCanvas, resolution);
22870
23767
  if (runSkipKey !== void 0) {
22871
23768
  lastPaintedThumbnailKeyByCanvasRef.current.set(
@@ -22881,33 +23778,116 @@ function useDocxPageThumbnails(editor, options = {}) {
22881
23778
  error instanceof Error ? error : new Error("Failed to render DOCX page thumbnail.")
22882
23779
  );
22883
23780
  }
22884
- });
23781
+ };
23782
+ updatePageThumbnailState(pageIndex, "rendering");
23783
+ if (pageSurfaceRegistry.pageThumbnailSnapshots.has(pageIndex)) {
23784
+ await paintIntoTarget();
23785
+ return;
23786
+ }
23787
+ await ensureThumbnailRasterQueue().enqueue(
23788
+ thumbnailQueueKeyForCanvas(targetCanvas),
23789
+ paintIntoTarget,
23790
+ {
23791
+ priority: renderOptions?.priority ?? thumbnailRenderPriorityForPage(
23792
+ pageIndex,
23793
+ DOCX_THUMBNAIL_RENDER_PRIORITY_ATTACHED
23794
+ )
23795
+ }
23796
+ );
22885
23797
  },
22886
23798
  [
22887
23799
  ensureThumbnailRasterQueue,
22888
- ensureThumbnailSurfaceCache,
22889
- fallbackLayout.pageHeightPx,
22890
- fallbackLayout.pageWidthPx,
22891
23800
  options.disabled,
22892
- options.resolution,
22893
- options.maxHeightPx,
22894
- options.maxWidthPx,
22895
- options.pixelRatio,
22896
23801
  pageSurfaceRegistry,
23802
+ renderPageThumbnailSurface,
22897
23803
  thumbnailSkipKeyForPage,
22898
- updatePageThumbnailState,
22899
- editor
23804
+ thumbnailQueueKeyForCanvas,
23805
+ thumbnailRenderPriorityForPage,
23806
+ updatePageThumbnailState
22900
23807
  ]
22901
23808
  );
23809
+ const prefetchPageThumbnailSurface = React.useCallback(
23810
+ async (pageIndex) => {
23811
+ if (options.disabled) {
23812
+ return;
23813
+ }
23814
+ const queueKey = docxThumbnailPrefetchQueueKey(pageIndex);
23815
+ queuedPrefetchThumbnailKeysRef.current.add(queueKey);
23816
+ await ensureThumbnailRasterQueue().enqueue(
23817
+ queueKey,
23818
+ async () => {
23819
+ try {
23820
+ await renderPageThumbnailSurface(pageIndex);
23821
+ } catch {
23822
+ }
23823
+ },
23824
+ { priority: DOCX_THUMBNAIL_RENDER_PRIORITY_PREFETCH }
23825
+ );
23826
+ queuedPrefetchThumbnailKeysRef.current.delete(queueKey);
23827
+ },
23828
+ [ensureThumbnailRasterQueue, options.disabled, renderPageThumbnailSurface]
23829
+ );
22902
23830
  const requestAttachedThumbnailRenders = React.useCallback(
22903
23831
  async (renderOptions) => {
22904
- const tasks = [...attachedCanvasByPageRef.current.keys()].map(
22905
- (pageIndex) => renderPageThumbnailToCanvas(pageIndex, void 0, renderOptions)
23832
+ const attachedPageIndexes = [
23833
+ ...attachedCanvasByPageRef.current.keys()
23834
+ ].sort((leftPageIndex, rightPageIndex) => {
23835
+ const leftPriority = thumbnailRenderPriorityForPage(leftPageIndex);
23836
+ const rightPriority = thumbnailRenderPriorityForPage(rightPageIndex);
23837
+ return leftPriority - rightPriority || leftPageIndex - rightPageIndex;
23838
+ });
23839
+ const tasks = attachedPageIndexes.map(
23840
+ (pageIndex) => renderPageThumbnailToCanvas(pageIndex, void 0, {
23841
+ ...renderOptions,
23842
+ priority: thumbnailRenderPriorityForPage(pageIndex)
23843
+ })
22906
23844
  );
22907
23845
  await Promise.all(tasks);
22908
23846
  },
22909
- [renderPageThumbnailToCanvas]
23847
+ [renderPageThumbnailToCanvas, thumbnailRenderPriorityForPage]
22910
23848
  );
23849
+ const requestPrefetchThumbnailRenders = React.useCallback(async () => {
23850
+ if (options.disabled) {
23851
+ queuedPrefetchThumbnailKeysRef.current.forEach((queueKey) => {
23852
+ thumbnailRasterQueueRef.current?.cancel(queueKey);
23853
+ });
23854
+ queuedPrefetchThumbnailKeysRef.current.clear();
23855
+ return;
23856
+ }
23857
+ const requestedPrefetchKeys = new Set(
23858
+ prefetchThumbnailPageIndexes.map(
23859
+ (pageIndex) => docxThumbnailPrefetchQueueKey(pageIndex)
23860
+ )
23861
+ );
23862
+ queuedPrefetchThumbnailKeysRef.current.forEach((queueKey) => {
23863
+ if (!requestedPrefetchKeys.has(queueKey)) {
23864
+ thumbnailRasterQueueRef.current?.cancel(queueKey);
23865
+ queuedPrefetchThumbnailKeysRef.current.delete(queueKey);
23866
+ }
23867
+ });
23868
+ const tasks = prefetchThumbnailPageIndexes.map(
23869
+ (pageIndex) => prefetchPageThumbnailSurface(pageIndex)
23870
+ );
23871
+ await Promise.all(tasks);
23872
+ }, [
23873
+ options.disabled,
23874
+ prefetchPageThumbnailSurface,
23875
+ prefetchThumbnailPageIndexes
23876
+ ]);
23877
+ React.useEffect(() => {
23878
+ void requestPrefetchThumbnailRenders();
23879
+ }, [
23880
+ editor.documentLoadNonce,
23881
+ editor.documentTheme,
23882
+ editor.model,
23883
+ mountedPageElements,
23884
+ options.maxHeightPx,
23885
+ options.maxWidthPx,
23886
+ options.pixelRatio,
23887
+ options.resolution,
23888
+ prefetchThumbnailPageIndexesKey,
23889
+ requestPrefetchThumbnailRenders
23890
+ ]);
22911
23891
  const rerenderAttachedThumbnails = React.useCallback(
22912
23892
  async () => requestAttachedThumbnailRenders({ force: true }),
22913
23893
  [requestAttachedThumbnailRenders]
@@ -22936,7 +23916,7 @@ function useDocxPageThumbnails(editor, options = {}) {
22936
23916
  options.pixelRatio,
22937
23917
  requestAttachedThumbnailRenders
22938
23918
  ]);
22939
- const thumbnails = React.useMemo(() => {
23919
+ const thumbnailGeometryItems = React.useMemo(() => {
22940
23920
  const totalPages = Math.max(1, editor.totalPages);
22941
23921
  return Array.from({ length: totalPages }, (_, pageIndex) => {
22942
23922
  const pageElement = mountedPageElements.get(pageIndex);
@@ -22958,15 +23938,14 @@ function useDocxPageThumbnails(editor, options = {}) {
22958
23938
  maxHeightPx: options.maxHeightPx,
22959
23939
  pixelRatio: options.pixelRatio
22960
23940
  });
22961
- const state = pageThumbnailStates.get(pageIndex);
22962
23941
  return {
23942
+ // Internal: drives the default status below; stripped before exposure.
23943
+ hasElement: Boolean(pageElement),
22963
23944
  pageIndex,
22964
23945
  pageNumber: pageIndex + 1,
22965
23946
  sourceWidthPx: sourceSize.widthPx,
22966
23947
  sourceHeightPx: sourceSize.heightPx,
22967
23948
  isMounted: Boolean(pageElement && pageElement.isConnected),
22968
- status: state?.status ?? (pageElement ? "idle" : "unavailable"),
22969
- error: state?.error,
22970
23949
  paint: (canvas) => {
22971
23950
  if (!canvas || options.disabled) {
22972
23951
  return false;
@@ -22983,7 +23962,9 @@ function useDocxPageThumbnails(editor, options = {}) {
22983
23962
  }
22984
23963
  const previousCanvas = attachedCanvasByPageRef.current.get(pageIndex);
22985
23964
  if (previousCanvas) {
22986
- thumbnailRasterQueueRef.current?.cancel(previousCanvas);
23965
+ thumbnailRasterQueueRef.current?.cancel(
23966
+ thumbnailQueueKeyForCanvas(previousCanvas)
23967
+ );
22987
23968
  }
22988
23969
  attachedCanvasByPageRef.current.delete(pageIndex);
22989
23970
  };
@@ -23019,8 +24000,20 @@ function useDocxPageThumbnails(editor, options = {}) {
23019
24000
  options.maxWidthPx,
23020
24001
  options.pixelRatio,
23021
24002
  pageSurfaceRegistry,
23022
- pageThumbnailStates
24003
+ thumbnailQueueKeyForCanvas
23023
24004
  ]);
24005
+ const thumbnails = React.useMemo(
24006
+ () => thumbnailGeometryItems.map((geometryItem) => {
24007
+ const { hasElement, ...item } = geometryItem;
24008
+ const state = pageThumbnailStates.get(item.pageIndex);
24009
+ return {
24010
+ ...item,
24011
+ status: state?.status ?? (hasElement ? "idle" : "unavailable"),
24012
+ error: state?.error
24013
+ };
24014
+ }),
24015
+ [thumbnailGeometryItems, pageThumbnailStates]
24016
+ );
23024
24017
  const paintThumbnail = React.useCallback(
23025
24018
  (pageIndex, canvas) => {
23026
24019
  if (!canvas || options.disabled) {
@@ -25404,15 +26397,39 @@ function DocxEditorViewer({
25404
26397
  }),
25405
26398
  [documentLayout, pageNodeSegmentsByPage, pageSectionInfoByIndex]
25406
26399
  );
26400
+ const pageThumbnailSnapshotEntriesByPage = React.useMemo(
26401
+ () => buildDocxPageThumbnailRenderSnapshotEntries({
26402
+ model: editor.model,
26403
+ pageNodeSegmentsByPage,
26404
+ pageSectionInfoByIndex,
26405
+ contentKeysByPage: pageThumbnailContentKeysByPage,
26406
+ fallbackLayout: documentLayout,
26407
+ documentTheme: editor.documentTheme,
26408
+ docGridLinePitchPxByNodeIndex,
26409
+ numberingDefinitions: editor.model.metadata.numberingDefinitions
26410
+ }),
26411
+ [
26412
+ docGridLinePitchPxByNodeIndex,
26413
+ documentLayout,
26414
+ editor.documentTheme,
26415
+ editor.model,
26416
+ editor.model.metadata.numberingDefinitions,
26417
+ pageNodeSegmentsByPage,
26418
+ pageSectionInfoByIndex,
26419
+ pageThumbnailContentKeysByPage
26420
+ ]
26421
+ );
25407
26422
  React.useEffect(() => {
25408
26423
  syncDocxViewerPageSurfaceContentKeys(
25409
26424
  editor,
25410
26425
  pageThumbnailContentKeysByPage,
25411
- pageThumbnailSurfaceSizesByPage
26426
+ pageThumbnailSurfaceSizesByPage,
26427
+ pageThumbnailSnapshotEntriesByPage
25412
26428
  );
25413
26429
  }, [
25414
26430
  pageSurfaceRegistryOwner,
25415
26431
  pageThumbnailContentKeysByPage,
26432
+ pageThumbnailSnapshotEntriesByPage,
25416
26433
  pageThumbnailSurfaceSizesByPage
25417
26434
  ]);
25418
26435
  const resolveStyleRefFieldValueForPage = React.useMemo(() => {