@harbour-enterprises/superdoc 1.0.0-next.2 → 1.0.0-next.4

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.
Files changed (40) hide show
  1. package/dist/chunks/{PdfViewer-B-xTd4XY.cjs → PdfViewer-CtSTAdvv.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-eykNsWyi.es.js → PdfViewer-DtdN17V4.es.js} +2 -2
  3. package/dist/chunks/{eventemitter3-CcXAdeql.es.js → eventemitter3-44XulWQe.es.js} +1 -1
  4. package/dist/chunks/{index-rF5HExWB.cjs → index-Bj1kFbYe.cjs} +465 -228
  5. package/dist/chunks/{index-DpQ8ZYM0.es.js → index-Cxv7dMYN.es.js} +468 -231
  6. package/dist/chunks/{index-BDVXUeCy-7mwhYeJ7.es.js → index-D_KE9gpD-aIqhxcuF.es.js} +1 -1
  7. package/dist/chunks/{index-BDVXUeCy-Di6ozaOM.cjs → index-D_KE9gpD-radGpP4I.cjs} +1 -1
  8. package/dist/chunks/{jszip-5vvIqAEE.es.js → jszip-VP334ufO.es.js} +1 -1
  9. package/dist/chunks/{super-editor.es-CxajnL9u.es.js → super-editor.es-B2fSLkzN.es.js} +1033 -493
  10. package/dist/chunks/{super-editor.es-CcKbh84I.cjs → super-editor.es-BhQu31e4.cjs} +1032 -492
  11. package/dist/chunks/{vue-Dysv_7z5.es.js → vue-BuPTonTJ.es.js} +27 -27
  12. package/dist/chunks/xml-js-LkEmUa9-.es.js +2 -0
  13. package/dist/packages/superdoc/src/composables/useUiFontFamily.d.ts +42 -0
  14. package/dist/packages/superdoc/src/composables/useUiFontFamily.d.ts.map +1 -0
  15. package/dist/packages/superdoc/src/core/SuperDoc.d.ts +3 -3
  16. package/dist/packages/superdoc/src/core/SuperDoc.d.ts.map +1 -1
  17. package/dist/packages/superdoc/src/core/types/index.d.ts +4 -167
  18. package/dist/packages/superdoc/src/core/types/index.d.ts.map +1 -1
  19. package/dist/style.css +88 -86
  20. package/dist/super-editor/ai-writer.es.js +3 -3
  21. package/dist/super-editor/chunks/{converter-DN_dhslo.js → converter-CVqUjX24.js} +1 -1
  22. package/dist/super-editor/chunks/{docx-zipper-Bhl_yBjL.js → docx-zipper-CsWjoVKD.js} +1 -1
  23. package/dist/super-editor/chunks/{editor-3klx7hyV.js → editor-Cc8nus2C.js} +429 -129
  24. package/dist/super-editor/chunks/{index-BDVXUeCy.js → index-D_KE9gpD.js} +1 -1
  25. package/dist/super-editor/chunks/{toolbar-8YA9ltNC.js → toolbar-CoOpR1xE.js} +804 -568
  26. package/dist/super-editor/converter.es.js +1 -1
  27. package/dist/super-editor/docx-zipper.es.js +2 -2
  28. package/dist/super-editor/editor.es.js +3 -3
  29. package/dist/super-editor/file-zipper.es.js +1 -1
  30. package/dist/super-editor/style.css +22 -21
  31. package/dist/super-editor/super-editor.es.js +10 -6
  32. package/dist/super-editor/toolbar.es.js +2 -2
  33. package/dist/super-editor.cjs +1 -1
  34. package/dist/super-editor.es.js +2 -2
  35. package/dist/superdoc.cjs +2 -2
  36. package/dist/superdoc.es.js +2 -2
  37. package/dist/superdoc.umd.js +1495 -718
  38. package/dist/superdoc.umd.js.map +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunks/xml-js-ClO_jHnq.es.js +0 -2
@@ -42427,7 +42427,7 @@ const _SuperConverter = class _SuperConverter2 {
42427
42427
  static getStoredSuperdocVersion(docx) {
42428
42428
  return _SuperConverter2.getStoredCustomProperty(docx, "SuperdocVersion");
42429
42429
  }
42430
- static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-next.2") {
42430
+ static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "1.0.0-next.4") {
42431
42431
  return _SuperConverter2.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
42432
42432
  }
42433
42433
  /**
@@ -58566,28 +58566,28 @@ const setImageNodeSelection = (view, pos) => {
58566
58566
  }
58567
58567
  return false;
58568
58568
  };
58569
- function canRenderFont(fontName, fallbackFont = "sans-serif") {
58570
- const _canRenderFont = (fontName2, fallbackFont2) => {
58569
+ function canRenderFont(fontName, uiDisplayFallbackFont = "sans-serif") {
58570
+ const _canRenderFont = (fontName2, uiDisplayFallbackFont2) => {
58571
58571
  const canvas2 = document.createElement("canvas");
58572
58572
  const ctx2 = canvas2.getContext("2d");
58573
58573
  ctx2.textBaseline = "top";
58574
58574
  const text = "abcdefghijklmnopqrstuvwxyz0123456789";
58575
- ctx2.font = `72px ${fallbackFont2}`;
58575
+ ctx2.font = `72px ${uiDisplayFallbackFont2}`;
58576
58576
  const initialTextMeasurement = ctx2.measureText(text);
58577
58577
  const fallbackWidth = initialTextMeasurement.width;
58578
58578
  const fallbackHeight = initialTextMeasurement.actualBoundingBoxDescent;
58579
- ctx2.font = `72px "${fontName2}", ${fallbackFont2}`;
58579
+ ctx2.font = `72px "${fontName2}", ${uiDisplayFallbackFont2}`;
58580
58580
  const customTextMeasurement = ctx2.measureText(text);
58581
58581
  const customFontWidth = customTextMeasurement.width;
58582
58582
  const customFontHeight = customTextMeasurement.actualBoundingBoxDescent;
58583
58583
  const isAvailable = customFontWidth !== fallbackWidth || customFontHeight !== fallbackHeight;
58584
58584
  return isAvailable;
58585
58585
  };
58586
- if (_canRenderFont(fontName, fallbackFont)) {
58586
+ if (_canRenderFont(fontName, uiDisplayFallbackFont)) {
58587
58587
  return true;
58588
58588
  }
58589
- const oppositeFallbackFont = fallbackFont === "sans-serif" ? "serif" : "sans-serif";
58590
- return _canRenderFont(fontName, oppositeFallbackFont);
58589
+ const oppositeUiDisplayFallbackFont = uiDisplayFallbackFont === "sans-serif" ? "serif" : "sans-serif";
58590
+ return _canRenderFont(fontName, oppositeUiDisplayFallbackFont);
58591
58591
  }
58592
58592
  const { findChildren: findChildren$3 } = helpers;
58593
58593
  function getAllFieldAnnotations(state2) {
@@ -59655,7 +59655,7 @@ const isHeadless = (editor) => {
59655
59655
  const shouldSkipNodeView = (editor) => {
59656
59656
  return isHeadless(editor);
59657
59657
  };
59658
- const summaryVersion = "1.0.0-next.2";
59658
+ const summaryVersion = "1.0.0-next.4";
59659
59659
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
59660
59660
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
59661
59661
  function mapAttributes(attrs) {
@@ -60444,7 +60444,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60444
60444
  { default: remarkStringify },
60445
60445
  { default: remarkGfm }
60446
60446
  ] = await Promise.all([
60447
- Promise.resolve().then(() => require("./index-BDVXUeCy-Di6ozaOM.cjs")),
60447
+ Promise.resolve().then(() => require("./index-D_KE9gpD-radGpP4I.cjs")),
60448
60448
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
60449
60449
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
60450
60450
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -60649,7 +60649,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
60649
60649
  * Process collaboration migrations
60650
60650
  */
60651
60651
  processCollaborationMigrations() {
60652
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-next.2");
60652
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-next.4");
60653
60653
  if (!this.options.ydoc) return;
60654
60654
  const metaMap = this.options.ydoc.getMap("meta");
60655
60655
  let docVersion = metaMap.get("version");
@@ -66254,6 +66254,34 @@ function calculateTabWidth(params2) {
66254
66254
  tabStopPosUsed: nextStop.pos
66255
66255
  };
66256
66256
  }
66257
+ const SPACE_CHARS$1 = /* @__PURE__ */ new Set([" ", " "]);
66258
+ function shouldApplyJustify(params2) {
66259
+ const { alignment: alignment2, hasExplicitPositioning, isLastLineOfParagraph, paragraphEndsWithLineBreak, skipJustifyOverride } = params2;
66260
+ if (alignment2 !== "justify" && alignment2 !== "both") {
66261
+ return false;
66262
+ }
66263
+ if (skipJustifyOverride === true) {
66264
+ return false;
66265
+ }
66266
+ if (hasExplicitPositioning) {
66267
+ return false;
66268
+ }
66269
+ if (isLastLineOfParagraph && !paragraphEndsWithLineBreak) {
66270
+ return false;
66271
+ }
66272
+ return true;
66273
+ }
66274
+ function calculateJustifySpacing(params2) {
66275
+ const { lineWidth, availableWidth, spaceCount, shouldJustify } = params2;
66276
+ if (!shouldJustify) {
66277
+ return 0;
66278
+ }
66279
+ if (spaceCount <= 0) {
66280
+ return 0;
66281
+ }
66282
+ const slack = availableWidth - lineWidth;
66283
+ return slack / spaceCount;
66284
+ }
66257
66285
  function resolveSpacingIndent$1(style2, numbering) {
66258
66286
  const spacing = {
66259
66287
  before: style2.spacing?.before ?? 0,
@@ -66520,13 +66548,14 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
66520
66548
  };
66521
66549
  }
66522
66550
  }
66551
+ const normalizedAlign = normalizeAlignment(resolvedExtended.justification);
66523
66552
  const hydrated = {
66524
66553
  resolved,
66525
66554
  spacing: resolvedSpacing,
66526
66555
  indent: resolvedIndent,
66527
66556
  borders: cloneIfObject(resolvedExtended.borders),
66528
66557
  shading: cloneIfObject(resolvedExtended.shading),
66529
- alignment: resolvedExtended.justification,
66558
+ alignment: normalizedAlign,
66530
66559
  tabStops: cloneIfObject(resolvedExtended.tabStops),
66531
66560
  keepLines: resolvedExtended.keepLines,
66532
66561
  keepNext: resolvedExtended.keepNext,
@@ -67227,7 +67256,7 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
67227
67256
  } else if (styleAlignment) {
67228
67257
  paragraphAttrs.alignment = styleAlignment;
67229
67258
  } else if (computed2.paragraph.alignment) {
67230
- paragraphAttrs.alignment = computed2.paragraph.alignment;
67259
+ paragraphAttrs.alignment = normalizeAlignment(computed2.paragraph.alignment);
67231
67260
  }
67232
67261
  const spacingPx = spacingPtToPx(spacing, normalizedSpacing);
67233
67262
  if (spacingPx) paragraphAttrs.spacing = spacingPx;
@@ -68379,9 +68408,9 @@ const extractFirstTextRunFont = (para) => {
68379
68408
  const font = findFirstTextFont(para.content);
68380
68409
  return font;
68381
68410
  };
68382
- const applyBaseRunDefaults = (run2, defaults, fallbackFont, fallbackSize) => {
68411
+ const applyBaseRunDefaults = (run2, defaults, uiDisplayFallbackFont, fallbackSize) => {
68383
68412
  if (!run2) return;
68384
- if (defaults.fontFamily && run2.fontFamily === fallbackFont) {
68413
+ if (defaults.fontFamily && run2.fontFamily === uiDisplayFallbackFont) {
68385
68414
  run2.fontFamily = defaults.fontFamily;
68386
68415
  }
68387
68416
  if (defaults.fontSizePx != null && run2.fontSize === fallbackSize) {
@@ -70184,7 +70213,7 @@ function tableNodeToBlock(node, nextBlockId, positions, defaultFont, defaultSize
70184
70213
  let measurementCanvas = null;
70185
70214
  let measurementCtx = null;
70186
70215
  const TAB_CHAR_LENGTH = 1;
70187
- const SPACE_CHARS = /* @__PURE__ */ new Set([" ", " "]);
70216
+ const SPACE_CHARS = SPACE_CHARS$1;
70188
70217
  const isTabRun$1 = (run2) => run2?.kind === "tab";
70189
70218
  function getMeasurementContext() {
70190
70219
  if (measurementCtx) return measurementCtx;
@@ -70210,29 +70239,50 @@ const countSpaces = (text) => {
70210
70239
  }
70211
70240
  return spaces;
70212
70241
  };
70213
- const getJustifyAdjustment = (block, line, availableWidthOverride, alignmentOverride) => {
70242
+ const getJustifyAdjustment = (block, line, availableWidthOverride, alignmentOverride, isLastLineOfParagraph, paragraphEndsWithLineBreak, skipJustifyOverride) => {
70214
70243
  if (block.kind !== "paragraph") {
70215
70244
  return { extraPerSpace: 0, totalSpaces: 0 };
70216
70245
  }
70217
- const alignment2 = alignmentOverride ?? block.attrs?.alignment;
70218
- const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
70219
- const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
70220
- const slack = Math.max(0, availableWidth - line.width);
70221
- if (alignment2 !== "justify" || hasExplicitPositioning || slack <= 0) {
70246
+ if (block.runs.length === 0) {
70222
70247
  return { extraPerSpace: 0, totalSpaces: 0 };
70223
70248
  }
70224
- const runs = sliceRunsForLine$1(block, line);
70225
- const totalSpaces = runs.reduce((sum, run2) => {
70226
- if (isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation") {
70227
- return sum;
70228
- }
70229
- return sum + countSpaces(run2.text ?? "");
70230
- }, 0);
70231
- if (totalSpaces <= 0) {
70249
+ const alignment2 = alignmentOverride ?? block.attrs?.alignment;
70250
+ const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0) ?? false;
70251
+ const lastRunIndex = block.runs.length - 1;
70252
+ const lastRun = block.runs[lastRunIndex];
70253
+ const derivedIsLastLine = line.toRun >= lastRunIndex;
70254
+ const derivedEndsWithLineBreak = lastRun ? lastRun.kind === "lineBreak" : false;
70255
+ const shouldJustify = shouldApplyJustify({
70256
+ alignment: alignment2,
70257
+ hasExplicitPositioning,
70258
+ isLastLineOfParagraph: derivedIsLastLine,
70259
+ paragraphEndsWithLineBreak: derivedEndsWithLineBreak,
70260
+ skipJustifyOverride
70261
+ });
70262
+ if (!shouldJustify) {
70232
70263
  return { extraPerSpace: 0, totalSpaces: 0 };
70233
70264
  }
70265
+ let totalSpaces = line.spaceCount ?? 0;
70266
+ if (totalSpaces === 0) {
70267
+ const runs = sliceRunsForLine$1(block, line);
70268
+ totalSpaces = runs.reduce((sum, run2) => {
70269
+ if (isTabRun$1(run2) || "src" in run2 || run2.kind === "lineBreak" || run2.kind === "break" || run2.kind === "fieldAnnotation") {
70270
+ return sum;
70271
+ }
70272
+ return sum + countSpaces(run2.text ?? "");
70273
+ }, 0);
70274
+ }
70275
+ const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
70276
+ const lineWidth = line.naturalWidth ?? line.width;
70277
+ const extraPerSpace = calculateJustifySpacing({
70278
+ lineWidth,
70279
+ availableWidth,
70280
+ spaceCount: totalSpaces,
70281
+ shouldJustify: true
70282
+ // Already checked above
70283
+ });
70234
70284
  return {
70235
- extraPerSpace: slack / totalSpaces,
70285
+ extraPerSpace,
70236
70286
  totalSpaces
70237
70287
  };
70238
70288
  };
@@ -70299,7 +70349,7 @@ function measureCharacterX(block, line, charOffset, availableWidthOverride, alig
70299
70349
  line.width;
70300
70350
  const justify = getJustifyAdjustment(block, line, availableWidth, alignmentOverride);
70301
70351
  const alignment2 = alignmentOverride ?? (block.kind === "paragraph" ? block.attrs?.alignment : void 0);
70302
- const renderedLineWidth = alignment2 === "justify" ? line.width + Math.max(0, availableWidth - line.width) : line.width;
70352
+ const renderedLineWidth = alignment2 === "justify" && justify.extraPerSpace !== 0 ? availableWidth : line.width;
70303
70353
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
70304
70354
  const alignmentOffset = !hasExplicitPositioning && alignment2 === "center" ? Math.max(0, (availableWidth - renderedLineWidth) / 2) : !hasExplicitPositioning && alignment2 === "right" ? Math.max(0, availableWidth - renderedLineWidth) : 0;
70305
70355
  if (hasExplicitPositioning && line.segments && ctx2) {
@@ -70342,13 +70392,13 @@ function measureCharacterX(block, line, charOffset, availableWidthOverride, alig
70342
70392
  const textUpToTarget = text.slice(0, offsetInRun);
70343
70393
  const measured2 = ctx2.measureText(textUpToTarget);
70344
70394
  const spacingWidth = computeLetterSpacingWidth(run2, offsetInRun, runLength);
70345
- const spacesInPortion = justify.extraPerSpace > 0 ? countSpaces(textUpToTarget) : 0;
70395
+ const spacesInPortion = justify.extraPerSpace !== 0 ? countSpaces(textUpToTarget) : 0;
70346
70396
  return alignmentOffset + currentX + measured2.width + spacingWidth + justify.extraPerSpace * (spaceTally + spacesInPortion);
70347
70397
  }
70348
70398
  ctx2.font = getRunFontString(run2);
70349
70399
  const measured = ctx2.measureText(text);
70350
70400
  const runLetterSpacing = computeLetterSpacingWidth(run2, runLength, runLength);
70351
- const spacesInRun = justify.extraPerSpace > 0 ? countSpaces(text) : 0;
70401
+ const spacesInRun = justify.extraPerSpace !== 0 ? countSpaces(text) : 0;
70352
70402
  currentX += measured.width + runLetterSpacing + justify.extraPerSpace * spacesInRun;
70353
70403
  spaceTally += spacesInRun;
70354
70404
  currentCharOffset += runLength;
@@ -75500,9 +75550,66 @@ const _DomPainter = class _DomPainter2 {
75500
75550
  const firstLineOffset = suppressFirstLineIndent ? 0 : (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
75501
75551
  const lastRun = block.runs.length > 0 ? block.runs[block.runs.length - 1] : null;
75502
75552
  const paragraphEndsWithLineBreak = lastRun?.kind === "lineBreak";
75553
+ let listFirstLineMarkerTabWidth;
75554
+ if (!fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
75555
+ const markerBoxWidth = fragment.markerWidth;
75556
+ const markerTextWidth = fragment.markerTextWidth != null && isFinite(fragment.markerTextWidth) && fragment.markerTextWidth >= 0 ? fragment.markerTextWidth : markerBoxWidth;
75557
+ const suffix2 = wordLayout.marker.suffix ?? "tab";
75558
+ if (suffix2 === "tab") {
75559
+ const markerJustification = wordLayout.marker.justification ?? "left";
75560
+ const isFirstLineIndentMode = wordLayout.firstLineIndentMode === true;
75561
+ let markerStartPos;
75562
+ if (isFirstLineIndentMode && wordLayout.marker.markerX !== void 0 && Number.isFinite(wordLayout.marker.markerX)) {
75563
+ markerStartPos = wordLayout.marker.markerX;
75564
+ } else {
75565
+ const hanging = paraIndent?.hanging ?? 0;
75566
+ const firstLine = paraIndent?.firstLine ?? 0;
75567
+ markerStartPos = paraIndentLeft - hanging + firstLine;
75568
+ }
75569
+ const validMarkerStartPos = Number.isFinite(markerStartPos) ? markerStartPos : 0;
75570
+ let tabWidth;
75571
+ if (markerJustification === "left") {
75572
+ const currentPos = validMarkerStartPos + markerTextWidth;
75573
+ if (isFirstLineIndentMode) {
75574
+ const textStartTarget = wordLayout.marker.textStartX !== void 0 && Number.isFinite(wordLayout.marker.textStartX) ? wordLayout.marker.textStartX : wordLayout.textStartPx;
75575
+ if (textStartTarget !== void 0 && Number.isFinite(textStartTarget) && textStartTarget > currentPos) {
75576
+ tabWidth = textStartTarget - currentPos;
75577
+ } else {
75578
+ tabWidth = LIST_MARKER_GAP$1;
75579
+ }
75580
+ } else {
75581
+ const firstLine = paraIndent?.firstLine ?? 0;
75582
+ const textStart = paraIndentLeft + firstLine;
75583
+ tabWidth = textStart - currentPos;
75584
+ if (tabWidth <= 0) {
75585
+ tabWidth = DEFAULT_TAB_INTERVAL_PX$1 - currentPos % DEFAULT_TAB_INTERVAL_PX$1;
75586
+ } else if (tabWidth < LIST_MARKER_GAP$1) {
75587
+ tabWidth = LIST_MARKER_GAP$1;
75588
+ }
75589
+ }
75590
+ } else {
75591
+ const gutterWidth = fragment.markerGutter ?? wordLayout.marker.gutterWidthPx;
75592
+ tabWidth = gutterWidth !== void 0 && Number.isFinite(gutterWidth) && gutterWidth > 0 ? gutterWidth : LIST_MARKER_GAP$1;
75593
+ }
75594
+ if (tabWidth < LIST_MARKER_GAP$1) {
75595
+ tabWidth = LIST_MARKER_GAP$1;
75596
+ }
75597
+ listFirstLineMarkerTabWidth = validMarkerStartPos + markerTextWidth + tabWidth;
75598
+ } else if (suffix2 === "space") {
75599
+ const hanging = paraIndent?.hanging ?? 0;
75600
+ const firstLine = paraIndent?.firstLine ?? 0;
75601
+ const markerStartPos = paraIndentLeft - hanging + firstLine;
75602
+ const validMarkerStartPos = Number.isFinite(markerStartPos) ? markerStartPos : 0;
75603
+ listFirstLineMarkerTabWidth = validMarkerStartPos + markerTextWidth + 4;
75604
+ }
75605
+ }
75503
75606
  lines.forEach((line, index2) => {
75504
- const fallbackAvailableWidth = Math.max(0, fragment.width - (paraIndentLeft + paraIndentRight));
75505
- const availableWidthOverride = line.maxWidth ?? fallbackAvailableWidth;
75607
+ const positiveIndentReduction = Math.max(0, paraIndentLeft) + Math.max(0, paraIndentRight);
75608
+ const fallbackAvailableWidth = Math.max(0, fragment.width - positiveIndentReduction);
75609
+ let availableWidthOverride = line.maxWidth != null ? Math.min(line.maxWidth, fallbackAvailableWidth) : fallbackAvailableWidth;
75610
+ if (index2 === 0 && listFirstLineMarkerTabWidth != null) {
75611
+ availableWidthOverride = fragment.width - listFirstLineMarkerTabWidth - Math.max(0, paraIndentRight);
75612
+ }
75506
75613
  const isLastLineOfFragment = index2 === lines.length - 1;
75507
75614
  const isLastLineOfParagraph = isLastLineOfFragment && !fragment.continuesOnNext;
75508
75615
  const shouldSkipJustifyForLastLine = isLastLineOfParagraph && !paragraphEndsWithLineBreak;
@@ -75528,7 +75635,10 @@ const _DomPainter = class _DomPainter2 {
75528
75635
  }
75529
75636
  } else if (paraIndentLeft && paraIndentLeft > 0) {
75530
75637
  lineEl.style.paddingLeft = `${paraIndentLeft}px`;
75531
- } else if (!isFirstLine && paraIndent?.hanging && paraIndent.hanging > 0) {
75638
+ } else if (!isFirstLine && paraIndent?.hanging && paraIndent.hanging > 0 && // Only apply hanging padding when left indent is NOT negative.
75639
+ // When left indent is negative, the fragment position already accounts for it.
75640
+ // Adding padding here would shift body lines right, causing right-side overflow.
75641
+ !(paraIndentLeft != null && paraIndentLeft < 0)) {
75532
75642
  lineEl.style.paddingLeft = `${paraIndent.hanging}px`;
75533
75643
  }
75534
75644
  }
@@ -75557,6 +75667,7 @@ const _DomPainter = class _DomPainter2 {
75557
75667
  lineEl.style.paddingLeft = `${validMarkerStartPos}px`;
75558
75668
  const markerContainer = this.doc.createElement("span");
75559
75669
  markerContainer.style.display = "inline-block";
75670
+ markerContainer.style.wordSpacing = "0px";
75560
75671
  const markerEl = this.doc.createElement("span");
75561
75672
  markerEl.classList.add("superdoc-paragraph-marker");
75562
75673
  markerEl.textContent = wordLayout.marker.markerText ?? "";
@@ -75642,10 +75753,15 @@ const _DomPainter = class _DomPainter2 {
75642
75753
  }
75643
75754
  }
75644
75755
  tabEl.style.display = "inline-block";
75756
+ tabEl.style.wordSpacing = "0px";
75645
75757
  tabEl.style.width = `${tabWidth}px`;
75646
75758
  lineEl.prepend(tabEl);
75647
75759
  } else if (suffix2 === "space") {
75648
- lineEl.prepend(this.doc.createTextNode(" "));
75760
+ const spaceEl = this.doc.createElement("span");
75761
+ spaceEl.classList.add("superdoc-marker-suffix-space");
75762
+ spaceEl.style.wordSpacing = "0px";
75763
+ spaceEl.textContent = " ";
75764
+ lineEl.prepend(spaceEl);
75649
75765
  }
75650
75766
  lineEl.prepend(markerContainer);
75651
75767
  }
@@ -76937,11 +77053,8 @@ const _DomPainter = class _DomPainter2 {
76937
77053
  el.setAttribute("styleid", styleId);
76938
77054
  }
76939
77055
  const alignment2 = block.attrs?.alignment;
76940
- const effectiveAlignment = alignment2;
76941
- if (effectiveAlignment === "center" || effectiveAlignment === "right") {
76942
- el.style.textAlign = effectiveAlignment;
76943
- } else if (effectiveAlignment === "justify") {
76944
- el.style.textAlign = "left";
77056
+ if (alignment2 === "center" || alignment2 === "right") {
77057
+ el.style.textAlign = alignment2;
76945
77058
  } else {
76946
77059
  el.style.textAlign = "left";
76947
77060
  }
@@ -76952,9 +77065,8 @@ const _DomPainter = class _DomPainter2 {
76952
77065
  if (lineRange.pmEnd != null) {
76953
77066
  el.dataset.pmEnd = String(lineRange.pmEnd);
76954
77067
  }
76955
- const runsForLine = sliceRunsForLine(block, line);
77068
+ let runsForLine = sliceRunsForLine(block, line);
76956
77069
  const trackedConfig = this.resolveTrackedChangesConfig(block);
76957
- runsForLine.length > 0 ? runsForLine.filter((r2) => (r2.kind === "text" || r2.kind === void 0) && "text" in r2 && r2.text != null).map((r2) => r2.text) : gatherTextSlicesForLine(block, line);
76958
77070
  if (runsForLine.length === 0) {
76959
77071
  const span = this.doc.createElement("span");
76960
77072
  span.innerHTML = "&nbsp;";
@@ -77001,7 +77113,156 @@ const _DomPainter = class _DomPainter2 {
77001
77113
  });
77002
77114
  }
77003
77115
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
77004
- availableWidthOverride ?? line.maxWidth ?? line.width;
77116
+ const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
77117
+ const justifyShouldApply = shouldApplyJustify({
77118
+ alignment: block.attrs?.alignment,
77119
+ hasExplicitPositioning: hasExplicitPositioning ?? false,
77120
+ // Caller already folds last-line + trailing lineBreak behavior into skipJustify.
77121
+ isLastLineOfParagraph: false,
77122
+ paragraphEndsWithLineBreak: false,
77123
+ skipJustifyOverride: skipJustify
77124
+ });
77125
+ const countSpaces2 = (text) => {
77126
+ let count = 0;
77127
+ for (let i = 0; i < text.length; i += 1) {
77128
+ if (SPACE_CHARS$1.has(text[i])) count += 1;
77129
+ }
77130
+ return count;
77131
+ };
77132
+ if (justifyShouldApply) {
77133
+ const stableDataAttrs = (attrs) => {
77134
+ if (!attrs) return void 0;
77135
+ const keys2 = Object.keys(attrs).sort();
77136
+ const out = {};
77137
+ keys2.forEach((key2) => {
77138
+ out[key2] = attrs[key2];
77139
+ });
77140
+ return out;
77141
+ };
77142
+ const mergeSignature = (run2) => JSON.stringify({
77143
+ kind: run2.kind ?? "text",
77144
+ fontFamily: run2.fontFamily,
77145
+ fontSize: run2.fontSize,
77146
+ bold: run2.bold ?? false,
77147
+ italic: run2.italic ?? false,
77148
+ letterSpacing: run2.letterSpacing ?? null,
77149
+ color: run2.color ?? null,
77150
+ underline: run2.underline ?? null,
77151
+ strike: run2.strike ?? false,
77152
+ highlight: run2.highlight ?? null,
77153
+ textTransform: run2.textTransform ?? null,
77154
+ token: run2.token ?? null,
77155
+ pageRefMetadata: run2.pageRefMetadata ?? null,
77156
+ trackedChange: run2.trackedChange ?? null,
77157
+ sdt: run2.sdt ?? null,
77158
+ link: run2.link ?? null,
77159
+ comments: run2.comments ?? null,
77160
+ dataAttrs: stableDataAttrs(run2.dataAttrs) ?? null
77161
+ });
77162
+ const isWhitespaceOnly = (text) => {
77163
+ if (text.length === 0) return false;
77164
+ for (let i = 0; i < text.length; i += 1) {
77165
+ if (!SPACE_CHARS$1.has(text[i])) return false;
77166
+ }
77167
+ return true;
77168
+ };
77169
+ const cloneTextRun = (run2) => ({
77170
+ ...run2,
77171
+ comments: run2.comments ? [...run2.comments] : void 0,
77172
+ dataAttrs: run2.dataAttrs ? { ...run2.dataAttrs } : void 0,
77173
+ underline: run2.underline ? { ...run2.underline } : void 0,
77174
+ pageRefMetadata: run2.pageRefMetadata ? { ...run2.pageRefMetadata } : void 0
77175
+ });
77176
+ const normalized = runsForLine.map((run2) => {
77177
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) return run2;
77178
+ return cloneTextRun(run2);
77179
+ });
77180
+ const merged = [];
77181
+ for (let i = 0; i < normalized.length; i += 1) {
77182
+ const run2 = normalized[i];
77183
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) {
77184
+ merged.push(run2);
77185
+ continue;
77186
+ }
77187
+ const textRun = run2;
77188
+ if (!isWhitespaceOnly(textRun.text ?? "")) {
77189
+ merged.push(textRun);
77190
+ continue;
77191
+ }
77192
+ const prev = merged[merged.length - 1];
77193
+ if (prev && (prev.kind === "text" || prev.kind === void 0) && "text" in prev) {
77194
+ const prevTextRun = prev;
77195
+ if (mergeSignature(prevTextRun) === mergeSignature(textRun)) {
77196
+ const extra = textRun.text ?? "";
77197
+ prevTextRun.text = (prevTextRun.text ?? "") + extra;
77198
+ if (prevTextRun.pmStart != null) {
77199
+ prevTextRun.pmEnd = prevTextRun.pmStart + prevTextRun.text.length;
77200
+ } else if (prevTextRun.pmEnd != null) {
77201
+ prevTextRun.pmEnd = prevTextRun.pmEnd + extra.length;
77202
+ }
77203
+ continue;
77204
+ }
77205
+ }
77206
+ const next = normalized[i + 1];
77207
+ if (next && (next.kind === "text" || next.kind === void 0) && "text" in next) {
77208
+ const nextTextRun = next;
77209
+ if (mergeSignature(nextTextRun) === mergeSignature(textRun)) {
77210
+ const extra = textRun.text ?? "";
77211
+ nextTextRun.text = extra + (nextTextRun.text ?? "");
77212
+ if (textRun.pmStart != null) {
77213
+ nextTextRun.pmStart = textRun.pmStart;
77214
+ } else if (nextTextRun.pmStart != null) {
77215
+ nextTextRun.pmStart = nextTextRun.pmStart - extra.length;
77216
+ }
77217
+ if (nextTextRun.pmStart != null && nextTextRun.pmEnd == null) {
77218
+ nextTextRun.pmEnd = nextTextRun.pmStart + nextTextRun.text.length;
77219
+ }
77220
+ continue;
77221
+ }
77222
+ }
77223
+ merged.push(textRun);
77224
+ }
77225
+ runsForLine = merged;
77226
+ const hasNonSpaceText = runsForLine.some(
77227
+ (run2) => (run2.kind === "text" || run2.kind === void 0) && "text" in run2 && (run2.text ?? "").trim().length > 0
77228
+ );
77229
+ if (hasNonSpaceText) {
77230
+ for (let i = runsForLine.length - 1; i >= 0; i -= 1) {
77231
+ const run2 = runsForLine[i];
77232
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2)) continue;
77233
+ const text = run2.text ?? "";
77234
+ let trimCount = 0;
77235
+ for (let j2 = text.length - 1; j2 >= 0 && text[j2] === " "; j2 -= 1) {
77236
+ trimCount += 1;
77237
+ }
77238
+ if (trimCount === 0) break;
77239
+ const nextText = text.slice(0, Math.max(0, text.length - trimCount));
77240
+ if (nextText.length === 0) {
77241
+ runsForLine.splice(i, 1);
77242
+ continue;
77243
+ }
77244
+ run2.text = nextText;
77245
+ if (run2.pmEnd != null) {
77246
+ run2.pmEnd = run2.pmEnd - trimCount;
77247
+ }
77248
+ break;
77249
+ }
77250
+ }
77251
+ }
77252
+ const spaceCount = line.spaceCount ?? runsForLine.reduce((sum, run2) => {
77253
+ if (run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2) || run2.text == null) return sum;
77254
+ return sum + countSpaces2(run2.text);
77255
+ }, 0);
77256
+ const lineWidth = line.naturalWidth ?? line.width;
77257
+ const spacingPerSpace = calculateJustifySpacing({
77258
+ lineWidth,
77259
+ availableWidth,
77260
+ spaceCount,
77261
+ shouldJustify: justifyShouldApply
77262
+ });
77263
+ if (spacingPerSpace !== 0) {
77264
+ el.style.wordSpacing = `${spacingPerSpace}px`;
77265
+ }
77005
77266
  if (hasExplicitPositioning && line.segments) {
77006
77267
  const paraIndent = block.attrs?.indent;
77007
77268
  const indentLeft = paraIndent?.left ?? 0;
@@ -77873,7 +78134,7 @@ const applyParagraphBlockStyles = (element, attrs) => {
77873
78134
  element.setAttribute("styleid", attrs.styleId);
77874
78135
  }
77875
78136
  if (attrs.alignment) {
77876
- element.style.textAlign = attrs.alignment;
78137
+ element.style.textAlign = attrs.alignment === "justify" || attrs.alignment === "both" ? "left" : attrs.alignment;
77877
78138
  }
77878
78139
  if (attrs.dropCap) {
77879
78140
  element.classList.add("sd-editor-dropcap");
@@ -77938,23 +78199,6 @@ const applyParagraphShadingStyles = (element, shading) => {
77938
78199
  if (!shading?.fill) return;
77939
78200
  element.style.backgroundColor = shading.fill;
77940
78201
  };
77941
- const gatherTextSlicesForLine = (block, line) => {
77942
- const slices = [];
77943
- const startRun = line.fromRun ?? 0;
77944
- const endRun = line.toRun ?? startRun;
77945
- for (let runIndex = startRun; runIndex <= endRun; runIndex += 1) {
77946
- const run2 = block.runs[runIndex];
77947
- if (!run2 || run2.kind !== "text" && run2.kind !== void 0 || !("text" in run2) || !run2.text) continue;
77948
- const isFirst = runIndex === startRun;
77949
- const isLast = runIndex === endRun;
77950
- const start2 = isFirst ? line.fromChar ?? 0 : 0;
77951
- const end2 = isLast ? line.toChar ?? run2.text.length : run2.text.length;
77952
- if (start2 >= end2) continue;
77953
- const slice2 = run2.text.slice(start2, end2);
77954
- if (slice2) slices.push(slice2);
77955
- }
77956
- return slices;
77957
- };
77958
78202
  const sliceRunsForLine = (block, line) => {
77959
78203
  const result = [];
77960
78204
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
@@ -78576,7 +78820,8 @@ function calculateTextStartIndent(params2) {
78576
78820
  let indentAdjust = paraIndentLeft;
78577
78821
  if (isListItem2 && isFirstLine && isFirstLineIndentMode) {
78578
78822
  const textStartFallback = paraIndentLeft + Math.max(firstLineIndent, 0) + markerWidth;
78579
- indentAdjust = typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
78823
+ const markerTextStartX = wordLayout?.marker?.textStartX;
78824
+ indentAdjust = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : textStartFallback;
78580
78825
  } else if (isFirstLine && !isListItem2) {
78581
78826
  indentAdjust += firstLineOffset;
78582
78827
  }
@@ -79266,6 +79511,20 @@ const asSafeNumber = (value) => {
79266
79511
  }
79267
79512
  return value;
79268
79513
  };
79514
+ function calculateFirstLineIndent(block, measure) {
79515
+ const wordLayout = block.attrs?.wordLayout;
79516
+ if (!wordLayout?.firstLineIndentMode) {
79517
+ return 0;
79518
+ }
79519
+ if (!wordLayout.marker || !measure.marker) {
79520
+ return 0;
79521
+ }
79522
+ const markerWidthRaw = measure.marker.markerWidth ?? wordLayout.marker.markerBoxWidthPx ?? 0;
79523
+ const markerWidth = Number.isFinite(markerWidthRaw) && markerWidthRaw >= 0 ? markerWidthRaw : 0;
79524
+ const gutterWidthRaw = measure.marker.gutterWidth ?? 0;
79525
+ const gutterWidth = Number.isFinite(gutterWidthRaw) && gutterWidthRaw >= 0 ? gutterWidthRaw : 0;
79526
+ return markerWidth + gutterWidth;
79527
+ }
79269
79528
  function layoutParagraphBlock(ctx2, anchors) {
79270
79529
  const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
79271
79530
  const remeasureParagraph2 = ctx2.remeasureParagraph;
@@ -79395,17 +79654,8 @@ function layoutParagraphBlock(ctx2, anchors) {
79395
79654
  const remeasureWidth = Math.max(1, columnWidth - indentLeft - indentRight);
79396
79655
  let didRemeasureForColumnWidth = false;
79397
79656
  if (typeof remeasureParagraph2 === "function" && typeof measurementWidth === "number" && measurementWidth > remeasureWidth) {
79398
- let firstLineIndent = 0;
79399
- const wordLayout = block.attrs?.wordLayout;
79400
- if (wordLayout?.marker && measure.marker) {
79401
- const markerJustification = wordLayout.marker.justification ?? "left";
79402
- if (markerJustification === "left") {
79403
- const markerWidth = measure.marker.markerWidth ?? 0;
79404
- const gutterWidth = measure.marker.gutterWidth ?? wordLayout.marker.gutterWidthPx ?? 0;
79405
- firstLineIndent = markerWidth + gutterWidth;
79406
- }
79407
- }
79408
- const newMeasure = remeasureParagraph2(block, remeasureWidth, firstLineIndent);
79657
+ const firstLineIndent = calculateFirstLineIndent(block, measure);
79658
+ const newMeasure = remeasureParagraph2(block, columnWidth, firstLineIndent);
79409
79659
  lines = normalizeLines(newMeasure);
79410
79660
  didRemeasureForColumnWidth = true;
79411
79661
  }
@@ -79486,16 +79736,7 @@ function layoutParagraphBlock(ctx2, anchors) {
79486
79736
  }
79487
79737
  const narrowestRemeasureWidth = Math.max(1, narrowestWidth - indentLeft - indentRight);
79488
79738
  if (narrowestRemeasureWidth < remeasureWidth) {
79489
- let firstLineIndent = 0;
79490
- const wordLayout = block.attrs?.wordLayout;
79491
- if (wordLayout?.marker && measure.marker) {
79492
- const markerJustification = wordLayout.marker.justification ?? "left";
79493
- if (markerJustification === "left") {
79494
- const markerWidth = measure.marker.markerWidth ?? 0;
79495
- const gutterWidth = measure.marker.gutterWidth ?? wordLayout.marker.gutterWidthPx ?? 0;
79496
- firstLineIndent = markerWidth + gutterWidth;
79497
- }
79498
- }
79739
+ const firstLineIndent = calculateFirstLineIndent(block, measure);
79499
79740
  const newMeasure = remeasureParagraph2(block, narrowestRemeasureWidth, firstLineIndent);
79500
79741
  lines = normalizeLines(newMeasure);
79501
79742
  didRemeasureForFloats = true;
@@ -82642,7 +82883,8 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
82642
82883
  const indentHanging = Math.max(0, indent?.hanging ?? 0);
82643
82884
  const rawFirstLineOffset = Math.max(0, firstLineIndent || indentFirstLine - indentHanging);
82644
82885
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
82645
- const textStartPx = wordLayout?.textStartPx;
82886
+ const markerTextStartX = wordLayout?.marker?.textStartX;
82887
+ const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
82646
82888
  const treatAsHanging = textStartPx && indentLeft === 0 && indentHanging === 0;
82647
82889
  const firstLineWidth = typeof textStartPx === "number" && textStartPx > indentLeft && !treatAsHanging ? Math.max(1, maxWidth - textStartPx - indentRight) : Math.max(1, contentWidth - rawFirstLineOffset);
82648
82890
  const tabStops = buildTabStopsPx$1(indent, attrs?.tabs, attrs?.tabIntervalTwips);
@@ -82654,6 +82896,7 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
82654
82896
  const startRun = currentRun;
82655
82897
  const startChar = currentChar;
82656
82898
  let width = 0;
82899
+ let widthAtLastBreak = -1;
82657
82900
  let lastBreakRun = -1;
82658
82901
  let lastBreakChar = -1;
82659
82902
  let endRun = currentRun;
@@ -82671,6 +82914,7 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
82671
82914
  endChar = 1;
82672
82915
  lastBreakRun = r2;
82673
82916
  lastBreakChar = 1;
82917
+ widthAtLastBreak = width;
82674
82918
  continue;
82675
82919
  }
82676
82920
  const text = runText(run2);
@@ -82681,6 +82925,7 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
82681
82925
  if (lastBreakRun >= 0) {
82682
82926
  endRun = lastBreakRun;
82683
82927
  endChar = lastBreakChar;
82928
+ width = widthAtLastBreak >= 0 ? widthAtLastBreak : width;
82684
82929
  } else {
82685
82930
  endRun = r2;
82686
82931
  endChar = c2;
@@ -82695,6 +82940,7 @@ function remeasureParagraph(block, maxWidth, firstLineIndent = 0) {
82695
82940
  if (ch === " " || ch === " " || ch === "-") {
82696
82941
  lastBreakRun = r2;
82697
82942
  lastBreakChar = c2 + 1;
82943
+ widthAtLastBreak = width;
82698
82944
  }
82699
82945
  }
82700
82946
  if (didBreakInThisLine) break;
@@ -84405,7 +84651,9 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
84405
84651
  }
84406
84652
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
84407
84653
  const isListItem3 = markerWidth > 0;
84408
- const alignmentOverride = isListItem3 ? "left" : void 0;
84654
+ const paraAlignment = block.attrs?.alignment;
84655
+ const isJustified = paraAlignment === "justify" || paraAlignment === "both";
84656
+ const alignmentOverride = isListItem3 && !isJustified ? "left" : void 0;
84409
84657
  const pos = mapPointToPm(block, line, pageRelativePoint.x - fragment.x, isRTL, availableWidth, alignmentOverride);
84410
84658
  if (pos == null) {
84411
84659
  logClickStage("warn", "no-position", {
@@ -84472,7 +84720,9 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
84472
84720
  }
84473
84721
  const cellMarkerWidth = cellMeasure.marker?.markerWidth ?? 0;
84474
84722
  const isListItem3 = cellMarkerWidth > 0;
84475
- const alignmentOverride = isListItem3 ? "left" : void 0;
84723
+ const cellAlignment = cellBlock.attrs?.alignment;
84724
+ const isJustified = cellAlignment === "justify" || cellAlignment === "both";
84725
+ const alignmentOverride = isListItem3 && !isJustified ? "left" : void 0;
84476
84726
  const pos = mapPointToPm(cellBlock, line, localX, isRTL, availableWidth, alignmentOverride);
84477
84727
  if (pos != null) {
84478
84728
  logClickStage("log", "success", {
@@ -84641,7 +84891,9 @@ function selectionToRects(layout, blocks, measures, from2, to, geometryHelper) {
84641
84891
  const charOffsetTo = pmPosToCharOffset(block, line, sliceTo);
84642
84892
  const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
84643
84893
  const isListItemFlag = isListItem(markerWidth, block);
84644
- const alignmentOverride = isListItemFlag ? "left" : void 0;
84894
+ const blockAlignment = block.attrs?.alignment;
84895
+ const isJustified = blockAlignment === "justify" || blockAlignment === "both";
84896
+ const alignmentOverride = isListItemFlag && !isJustified ? "left" : void 0;
84645
84897
  const startX = mapPmToX(block, line, charOffsetFrom, fragment.width, alignmentOverride);
84646
84898
  const endX = mapPmToX(block, line, charOffsetTo, fragment.width, alignmentOverride);
84647
84899
  const indent = extractParagraphIndent(block.attrs?.indent);
@@ -85383,7 +85635,9 @@ async function measureParagraphBlock(block, maxWidth) {
85383
85635
  const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
85384
85636
  const bodyContentWidth = contentWidth;
85385
85637
  let initialAvailableWidth;
85386
- const textStartPx = wordLayout?.textStartPx;
85638
+ const rawTextStartPx = wordLayout?.textStartPx;
85639
+ const markerTextStartX = wordLayout?.marker?.textStartX;
85640
+ const textStartPx = typeof markerTextStartX === "number" && Number.isFinite(markerTextStartX) ? markerTextStartX : typeof rawTextStartPx === "number" && Number.isFinite(rawTextStartPx) ? rawTextStartPx : void 0;
85387
85641
  if (typeof textStartPx === "number" && textStartPx > indentLeft) {
85388
85642
  initialAvailableWidth = Math.max(1, maxWidth - textStartPx - indentRight);
85389
85643
  } else {
@@ -85518,12 +85772,40 @@ async function measureParagraphBlock(block, maxWidth) {
85518
85772
  runsToProcess.push(run2);
85519
85773
  }
85520
85774
  }
85775
+ const trimTrailingWrapSpaces = (lineToTrim) => {
85776
+ const lastRun = runsToProcess[lineToTrim.toRun];
85777
+ if (!lastRun || !("text" in lastRun) || typeof lastRun.text !== "string") return;
85778
+ const sliceStart = lineToTrim.toRun === lineToTrim.fromRun ? lineToTrim.fromChar : 0;
85779
+ const sliceEnd = lineToTrim.toChar;
85780
+ if (sliceEnd <= sliceStart) return;
85781
+ const sliceText = lastRun.text.slice(sliceStart, sliceEnd);
85782
+ let trimCount = 0;
85783
+ for (let i = sliceText.length - 1; i >= 0 && sliceText[i] === " "; i -= 1) {
85784
+ trimCount += 1;
85785
+ }
85786
+ if (trimCount === 0) return;
85787
+ if (lineToTrim.fromRun === lineToTrim.toRun && sliceText.trim().length === 0) {
85788
+ return;
85789
+ }
85790
+ const keptText = sliceText.slice(0, Math.max(0, sliceText.length - trimCount));
85791
+ const { font } = buildFontString(
85792
+ lastRun
85793
+ );
85794
+ const fullWidth = measureRunWidth(sliceText, font, ctx2, lastRun);
85795
+ const keptWidth = keptText.length > 0 ? measureRunWidth(keptText, font, ctx2, lastRun) : 0;
85796
+ const delta = Math.max(0, fullWidth - keptWidth);
85797
+ lineToTrim.width = roundValue(Math.max(0, lineToTrim.width - delta));
85798
+ lineToTrim.spaceCount = Math.max(0, lineToTrim.spaceCount - trimCount);
85799
+ if (lineToTrim.naturalWidth != null && typeof lineToTrim.naturalWidth === "number") {
85800
+ lineToTrim.naturalWidth = roundValue(Math.max(0, lineToTrim.naturalWidth - delta));
85801
+ }
85802
+ };
85521
85803
  for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
85522
85804
  const run2 = runsToProcess[runIndex];
85523
85805
  if (run2.kind === "break") {
85524
85806
  if (currentLine) {
85525
85807
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85526
- const { spaceCount: _sc, ...lineBase } = currentLine;
85808
+ const lineBase = currentLine;
85527
85809
  const completedLine = { ...lineBase, ...metrics };
85528
85810
  addBarTabsToLine(completedLine);
85529
85811
  lines.push(completedLine);
@@ -85568,7 +85850,7 @@ async function measureParagraphBlock(block, maxWidth) {
85568
85850
  toRun: runIndex,
85569
85851
  toChar: 0,
85570
85852
  width: 0,
85571
- maxWidth: getEffectiveWidth(initialAvailableWidth),
85853
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85572
85854
  segments: [],
85573
85855
  ...metrics
85574
85856
  };
@@ -85603,7 +85885,7 @@ async function measureParagraphBlock(block, maxWidth) {
85603
85885
  width: 0,
85604
85886
  maxFontSize: 12,
85605
85887
  // Default font size for tabs
85606
- maxWidth: getEffectiveWidth(initialAvailableWidth),
85888
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85607
85889
  segments: [],
85608
85890
  spaceCount: 0
85609
85891
  };
@@ -85653,7 +85935,7 @@ async function measureParagraphBlock(block, maxWidth) {
85653
85935
  width: imageWidth,
85654
85936
  maxFontSize: imageHeight,
85655
85937
  // Use image height for line height calculation
85656
- maxWidth: getEffectiveWidth(initialAvailableWidth),
85938
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85657
85939
  spaceCount: 0,
85658
85940
  segments: [
85659
85941
  {
@@ -85669,8 +85951,9 @@ async function measureParagraphBlock(block, maxWidth) {
85669
85951
  }
85670
85952
  const appliedTabAlign = lastAppliedTabAlign;
85671
85953
  if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
85954
+ trimTrailingWrapSpaces(currentLine);
85672
85955
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85673
- const { spaceCount: _sc, ...lineBase } = currentLine;
85956
+ const lineBase = currentLine;
85674
85957
  const completedLine = {
85675
85958
  ...lineBase,
85676
85959
  ...metrics
@@ -85743,7 +86026,7 @@ async function measureParagraphBlock(block, maxWidth) {
85743
86026
  // Field annotations are atomic units
85744
86027
  width: annotationWidth,
85745
86028
  maxFontSize: annotationHeight,
85746
- maxWidth: getEffectiveWidth(initialAvailableWidth),
86029
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85747
86030
  spaceCount: 0,
85748
86031
  segments: [
85749
86032
  {
@@ -85758,8 +86041,9 @@ async function measureParagraphBlock(block, maxWidth) {
85758
86041
  continue;
85759
86042
  }
85760
86043
  if (currentLine.width + annotationWidth > currentLine.maxWidth && currentLine.width > 0) {
86044
+ trimTrailingWrapSpaces(currentLine);
85761
86045
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85762
- const { spaceCount: _sc, ...lineBase } = currentLine;
86046
+ const lineBase = currentLine;
85763
86047
  const completedLine = {
85764
86048
  ...lineBase,
85765
86049
  ...metrics
@@ -85832,15 +86116,16 @@ async function measureParagraphBlock(block, maxWidth) {
85832
86116
  width: spacesWidth,
85833
86117
  maxFontSize: run2.fontSize,
85834
86118
  maxFontInfo: getFontInfoFromRun(run2),
85835
- maxWidth: getEffectiveWidth(initialAvailableWidth),
86119
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85836
86120
  segments: [{ runIndex, fromChar: spacesStartChar, toChar: spacesEndChar, width: spacesWidth }],
85837
86121
  spaceCount: spacesLength
85838
86122
  };
85839
86123
  } else {
85840
86124
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
85841
86125
  if (currentLine.width + boundarySpacing + spacesWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2 && currentLine.width > 0) {
86126
+ trimTrailingWrapSpaces(currentLine);
85842
86127
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85843
- const { spaceCount: _sc, ...lineBase } = currentLine;
86128
+ const lineBase = currentLine;
85844
86129
  const completedLine = {
85845
86130
  ...lineBase,
85846
86131
  ...metrics
@@ -85876,6 +86161,13 @@ async function measureParagraphBlock(block, maxWidth) {
85876
86161
  continue;
85877
86162
  }
85878
86163
  const words = segment.split(" ");
86164
+ let lastNonEmptyWordIndex = -1;
86165
+ for (let i = words.length - 1; i >= 0; i -= 1) {
86166
+ if (words[i] !== "") {
86167
+ lastNonEmptyWordIndex = i;
86168
+ break;
86169
+ }
86170
+ }
85879
86171
  let segmentStartX;
85880
86172
  if (currentLine && pendingTabAlignment) {
85881
86173
  segmentStartX = alignSegmentAtTab(segment, font, run2);
@@ -85898,15 +86190,16 @@ async function measureParagraphBlock(block, maxWidth) {
85898
86190
  width: singleSpaceWidth,
85899
86191
  maxFontSize: run2.fontSize,
85900
86192
  maxFontInfo: getFontInfoFromRun(run2),
85901
- maxWidth: getEffectiveWidth(initialAvailableWidth),
86193
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
85902
86194
  segments: [{ runIndex, fromChar: spaceStartChar, toChar: spaceEndChar, width: singleSpaceWidth }],
85903
86195
  spaceCount: 1
85904
86196
  };
85905
86197
  } else {
85906
86198
  const boundarySpacing2 = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
85907
86199
  if (currentLine.width + boundarySpacing2 + singleSpaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2 && currentLine.width > 0) {
86200
+ trimTrailingWrapSpaces(currentLine);
85908
86201
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85909
- const { spaceCount: _sc, ...lineBase } = currentLine;
86202
+ const lineBase = currentLine;
85910
86203
  const completedLine = { ...lineBase, ...metrics };
85911
86204
  addBarTabsToLine(completedLine);
85912
86205
  lines.push(completedLine);
@@ -85938,19 +86231,19 @@ async function measureParagraphBlock(block, maxWidth) {
85938
86231
  charPosInRun = spaceEndChar;
85939
86232
  continue;
85940
86233
  }
85941
- const isLastWordInSegment = wordIndex === words.length - 1;
85942
- const isLastWord = isLastWordInSegment && isLastSegment;
85943
86234
  const wordOnlyWidth = measureRunWidth(word, font, ctx2, run2);
85944
- const spaceWidth = isLastWord ? 0 : measureRunWidth(" ", font, ctx2, run2);
85945
- const wordCommitWidth = isLastWord ? wordOnlyWidth : wordOnlyWidth + spaceWidth;
86235
+ const shouldIncludeDelimiterSpace = wordIndex < lastNonEmptyWordIndex;
86236
+ const spaceWidth = shouldIncludeDelimiterSpace ? measureRunWidth(" ", font, ctx2, run2) : 0;
86237
+ const wordCommitWidth = wordOnlyWidth + spaceWidth;
85946
86238
  const wordStartChar = charPosInRun;
85947
86239
  const wordEndNoSpace = charPosInRun + word.length;
85948
- const wordEndWithSpace = charPosInRun + (isLastWord ? word.length : word.length + 1);
86240
+ const wordEndWithSpace = wordEndNoSpace + (shouldIncludeDelimiterSpace ? 1 : 0);
85949
86241
  const effectiveMaxWidth = currentLine ? currentLine.maxWidth : getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : contentWidth);
85950
86242
  if (wordOnlyWidth > effectiveMaxWidth && word.length > 1) {
85951
86243
  if (currentLine && currentLine.width > 0 && currentLine.segments && currentLine.segments.length > 0) {
86244
+ trimTrailingWrapSpaces(currentLine);
85952
86245
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85953
- const { spaceCount: _sc, ...lineBase } = currentLine;
86246
+ const lineBase = currentLine;
85954
86247
  const completedLine = { ...lineBase, ...metrics };
85955
86248
  addBarTabsToLine(completedLine);
85956
86249
  lines.push(completedLine);
@@ -85984,7 +86277,7 @@ async function measureParagraphBlock(block, maxWidth) {
85984
86277
  });
85985
86278
  if (isLastChunk) {
85986
86279
  const ls = run2.letterSpacing ?? 0;
85987
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86280
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
85988
86281
  currentLine.toChar = wordEndWithSpace;
85989
86282
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
85990
86283
  charPosInRun = wordEndWithSpace;
@@ -85993,8 +86286,9 @@ async function measureParagraphBlock(block, maxWidth) {
85993
86286
  charPosInRun = wordEndWithSpace;
85994
86287
  }
85995
86288
  } else {
86289
+ trimTrailingWrapSpaces(currentLine);
85996
86290
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
85997
- const { spaceCount: _sc, ...lineBase } = currentLine;
86291
+ const lineBase = currentLine;
85998
86292
  const completedLine = { ...lineBase, ...metrics };
85999
86293
  addBarTabsToLine(completedLine);
86000
86294
  lines.push(completedLine);
@@ -86016,7 +86310,7 @@ async function measureParagraphBlock(block, maxWidth) {
86016
86310
  spaceCount: 0
86017
86311
  };
86018
86312
  const ls = run2.letterSpacing ?? 0;
86019
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86313
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86020
86314
  currentLine.toChar = wordEndWithSpace;
86021
86315
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
86022
86316
  charPosInRun = wordEndWithSpace;
@@ -86053,12 +86347,12 @@ async function measureParagraphBlock(block, maxWidth) {
86053
86347
  width: wordOnlyWidth,
86054
86348
  maxFontSize: run2.fontSize,
86055
86349
  maxFontInfo: getFontInfoFromRun(run2),
86056
- maxWidth: getEffectiveWidth(initialAvailableWidth),
86350
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
86057
86351
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
86058
86352
  spaceCount: 0
86059
86353
  };
86060
86354
  const ls = run2.letterSpacing ?? 0;
86061
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86355
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86062
86356
  currentLine.toChar = wordEndWithSpace;
86063
86357
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
86064
86358
  charPosInRun = wordEndWithSpace;
@@ -86072,15 +86366,16 @@ async function measureParagraphBlock(block, maxWidth) {
86072
86366
  const boundarySpacing = currentLine.width > 0 ? run2.letterSpacing ?? 0 : 0;
86073
86367
  const justifyAlignment = block.attrs?.alignment === "justify";
86074
86368
  const totalWidthWithWord = currentLine.width + boundarySpacing + wordCommitWidth + // Safe cast: only TextRuns produce word segments from split(), other run types are handled earlier
86075
- (isLastWord ? 0 : run2.letterSpacing ?? 0);
86369
+ (shouldIncludeDelimiterSpace ? run2.letterSpacing ?? 0 : 0);
86076
86370
  const availableWidth = currentLine.maxWidth - WIDTH_FUDGE_PX2;
86077
86371
  let shouldBreak = currentLine.width + boundarySpacing + wordOnlyWidth > availableWidth && currentLine.width > 0 && !isTocEntry;
86078
86372
  let compressedWidth = null;
86079
86373
  if (shouldBreak && justifyAlignment) {
86080
- const isParagraphLastWord = isLastWord && runIndex === runsToProcess.length - 1;
86374
+ const isLastNonEmptyWordInSegment = wordIndex === lastNonEmptyWordIndex;
86375
+ const isParagraphLastWord = isLastSegment && isLastNonEmptyWordInSegment && runIndex === runsToProcess.length - 1;
86081
86376
  if (!isParagraphLastWord) {
86082
86377
  const existingSpaces = currentLine.spaceCount ?? 0;
86083
- const candidateSpaces = existingSpaces + (isLastWord ? 0 : 1);
86378
+ const candidateSpaces = existingSpaces + (shouldIncludeDelimiterSpace ? 1 : 0);
86084
86379
  if (candidateSpaces > 0) {
86085
86380
  const overflow = totalWidthWithWord - availableWidth;
86086
86381
  if (overflow > 0) {
@@ -86096,8 +86391,9 @@ async function measureParagraphBlock(block, maxWidth) {
86096
86391
  }
86097
86392
  }
86098
86393
  if (shouldBreak) {
86394
+ trimTrailingWrapSpaces(currentLine);
86099
86395
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
86100
- const { spaceCount: _sc, ...lineBase } = currentLine;
86396
+ const lineBase = currentLine;
86101
86397
  const completedLine = {
86102
86398
  ...lineBase,
86103
86399
  ...metrics
@@ -86118,7 +86414,7 @@ async function measureParagraphBlock(block, maxWidth) {
86118
86414
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }],
86119
86415
  spaceCount: 0
86120
86416
  };
86121
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86417
+ if (shouldIncludeDelimiterSpace && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86122
86418
  currentLine.toChar = wordEndWithSpace;
86123
86419
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run2.letterSpacing ?? 0));
86124
86420
  charPosInRun = wordEndWithSpace;
@@ -86128,7 +86424,7 @@ async function measureParagraphBlock(block, maxWidth) {
86128
86424
  }
86129
86425
  } else {
86130
86426
  currentLine.toRun = runIndex;
86131
- if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86427
+ if (shouldIncludeDelimiterSpace && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX2) {
86132
86428
  currentLine.toChar = wordEndNoSpace;
86133
86429
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
86134
86430
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
@@ -86142,8 +86438,9 @@ async function measureParagraphBlock(block, maxWidth) {
86142
86438
  wordOnlyWidth,
86143
86439
  useExplicitXHere ? segmentStartX : void 0
86144
86440
  );
86441
+ trimTrailingWrapSpaces(currentLine);
86145
86442
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
86146
- const { spaceCount: _sc, ...lineBase } = currentLine;
86443
+ const lineBase = currentLine;
86147
86444
  const completedLine = { ...lineBase, ...metrics };
86148
86445
  addBarTabsToLine(completedLine);
86149
86446
  lines.push(completedLine);
@@ -86153,20 +86450,23 @@ async function measureParagraphBlock(block, maxWidth) {
86153
86450
  charPosInRun = wordEndNoSpace + 1;
86154
86451
  continue;
86155
86452
  }
86156
- const newToChar = isLastWord ? wordEndNoSpace : wordEndWithSpace;
86453
+ const newToChar = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
86157
86454
  currentLine.toChar = newToChar;
86158
86455
  const useExplicitX = wordIndex === 0 && segmentStartX !== void 0;
86159
86456
  const explicitX = useExplicitX ? segmentStartX : void 0;
86160
- const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (isLastWord ? 0 : run2.letterSpacing ?? 0);
86457
+ const targetWidth = compressedWidth != null ? compressedWidth : currentLine.width + boundarySpacing + wordCommitWidth + (shouldIncludeDelimiterSpace ? run2.letterSpacing ?? 0 : 0);
86458
+ if (compressedWidth != null) {
86459
+ currentLine.naturalWidth = roundValue(totalWidthWithWord);
86460
+ }
86161
86461
  currentLine.width = roundValue(targetWidth);
86162
86462
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run2);
86163
86463
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run2.fontSize);
86164
86464
  appendSegment(currentLine.segments, runIndex, wordStartChar, newToChar, wordCommitWidth, explicitX);
86165
- if (!isLastWord) {
86465
+ if (shouldIncludeDelimiterSpace) {
86166
86466
  currentLine.spaceCount += 1;
86167
86467
  }
86168
86468
  }
86169
- charPosInRun = isLastWord ? wordEndNoSpace : wordEndWithSpace;
86469
+ charPosInRun = shouldIncludeDelimiterSpace ? wordEndWithSpace : wordEndNoSpace;
86170
86470
  }
86171
86471
  if (lastAppliedTabAlign && currentLine) {
86172
86472
  const appliedTab = lastAppliedTabAlign;
@@ -86186,7 +86486,7 @@ async function measureParagraphBlock(block, maxWidth) {
86186
86486
  width: 0,
86187
86487
  maxFontSize: run2.fontSize,
86188
86488
  maxFontInfo: getFontInfoFromRun(run2),
86189
- maxWidth: getEffectiveWidth(initialAvailableWidth),
86489
+ maxWidth: getEffectiveWidth(lines.length === 0 ? initialAvailableWidth : bodyContentWidth),
86190
86490
  segments: [],
86191
86491
  spaceCount: 0
86192
86492
  };
@@ -86218,8 +86518,8 @@ async function measureParagraphBlock(block, maxWidth) {
86218
86518
  }
86219
86519
  }
86220
86520
  if (!currentLine && lines.length === 0) {
86221
- const fallbackFontSize = (block.runs[0]?.kind === "text" ? block.runs[0].fontSize : void 0) ?? 12;
86222
- const metrics = calculateTypographyMetrics(fallbackFontSize, spacing);
86521
+ const uiDisplayFallbackFontSize = (block.runs[0]?.kind === "text" ? block.runs[0].fontSize : void 0) ?? 12;
86522
+ const metrics = calculateTypographyMetrics(uiDisplayFallbackFontSize, spacing);
86223
86523
  const fallbackLine = {
86224
86524
  fromRun: 0,
86225
86525
  fromChar: 0,
@@ -86234,7 +86534,7 @@ async function measureParagraphBlock(block, maxWidth) {
86234
86534
  }
86235
86535
  if (currentLine) {
86236
86536
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
86237
- const { spaceCount: _sc, ...lineBase } = currentLine;
86537
+ const lineBase = currentLine;
86238
86538
  const finalLine = {
86239
86539
  ...lineBase,
86240
86540
  ...metrics
@@ -110856,316 +111156,6 @@ const toolbarIcons = {
110856
111156
  paste: pasteIconSvg,
110857
111157
  strikethrough: strikethroughSvg
110858
111158
  };
110859
- const _hoisted_1$4$1 = { class: "toolbar-icon" };
110860
- const _hoisted_2$3$1 = ["innerHTML"];
110861
- const _sfc_main$5$1 = {
110862
- __name: "ToolbarButtonIcon",
110863
- props: {
110864
- name: {
110865
- type: String,
110866
- required: true
110867
- },
110868
- color: {
110869
- type: String,
110870
- default: null
110871
- },
110872
- icon: {
110873
- type: String,
110874
- default: null
110875
- }
110876
- },
110877
- setup(__props) {
110878
- const props = __props;
110879
- const getBarColor = vue.computed(() => {
110880
- if (props.name === "color") return { backgroundColor: props.color || "#111111" };
110881
- if (props.name === "highlight") return { backgroundColor: props.color || "#D6D6D6" };
110882
- });
110883
- const hasColorBar = vue.computed(() => {
110884
- return ["color", "highlight"].includes(props.name);
110885
- });
110886
- return (_ctx, _cache) => {
110887
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4$1, [
110888
- vue.createBaseVNode("div", {
110889
- class: vue.normalizeClass(["toolbar-icon__icon", [`toolbar-icon__icon--${props.name}`]]),
110890
- innerHTML: __props.icon
110891
- }, null, 10, _hoisted_2$3$1),
110892
- hasColorBar.value ? (vue.openBlock(), vue.createElementBlock("div", {
110893
- key: 0,
110894
- class: "color-bar",
110895
- style: vue.normalizeStyle(getBarColor.value)
110896
- }, null, 4)) : vue.createCommentVNode("", true)
110897
- ]);
110898
- };
110899
- }
110900
- };
110901
- const ToolbarButtonIcon = /* @__PURE__ */ _export_sfc(_sfc_main$5$1, [["__scopeId", "data-v-6d7523ab"]]);
110902
- const _hoisted_1$3$1 = ["role", "aria-label", "onKeydown"];
110903
- const _hoisted_2$2$1 = ["data-item"];
110904
- const _hoisted_3$2$1 = {
110905
- key: 1,
110906
- class: "button-label"
110907
- };
110908
- const _hoisted_4$1$1 = { key: 2 };
110909
- const _hoisted_5$4 = ["onKeydown", "id"];
110910
- const _hoisted_6$2 = ["placeholder", "onKeydown", "id"];
110911
- const _hoisted_7$1 = ["innerHTML"];
110912
- const _hoisted_8$1 = {
110913
- "aria-live": "polite",
110914
- class: "visually-hidden"
110915
- };
110916
- const _sfc_main$4$1 = {
110917
- __name: "ToolbarButton",
110918
- props: {
110919
- iconColor: {
110920
- type: String,
110921
- default: null
110922
- },
110923
- active: {
110924
- type: Boolean,
110925
- default: false
110926
- },
110927
- isNarrow: {
110928
- type: Boolean,
110929
- default: false
110930
- },
110931
- isWide: {
110932
- type: Boolean,
110933
- default: false
110934
- },
110935
- toolbarItem: {
110936
- type: Object,
110937
- required: true
110938
- },
110939
- defaultLabel: {
110940
- type: String,
110941
- default: null
110942
- },
110943
- isOverflowItem: {
110944
- type: Boolean,
110945
- default: false
110946
- }
110947
- },
110948
- emits: ["buttonClick", "textSubmit"],
110949
- setup(__props, { emit: __emit }) {
110950
- const emit = __emit;
110951
- const props = __props;
110952
- const {
110953
- name,
110954
- active,
110955
- icon,
110956
- label,
110957
- hideLabel,
110958
- iconColor,
110959
- hasCaret,
110960
- disabled,
110961
- inlineTextInputVisible,
110962
- hasInlineTextInput,
110963
- minWidth,
110964
- style: style2,
110965
- attributes
110966
- } = props.toolbarItem;
110967
- const inlineTextInput = vue.ref(label);
110968
- const inlineInput = vue.ref(null);
110969
- const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
110970
- const handleClick2 = () => {
110971
- if (hasInlineTextInput) {
110972
- vue.nextTick(() => {
110973
- inlineInput.value?.focus();
110974
- inlineInput.value?.select();
110975
- });
110976
- }
110977
- emit("buttonClick");
110978
- };
110979
- const handleInputSubmit = () => {
110980
- const value = inlineTextInput.value;
110981
- const cleanValue = value.match(/^\d+(\.5)?$/) ? value : Math.floor(parseFloat(value)).toString();
110982
- emit("textSubmit", cleanValue);
110983
- inlineTextInput.value = cleanValue;
110984
- };
110985
- const getStyle = vue.computed(() => {
110986
- if (style2.value) return style2.value;
110987
- return {
110988
- minWidth: props.minWidth
110989
- };
110990
- });
110991
- const caretIcon = vue.computed(() => {
110992
- return active.value ? toolbarIcons.dropdownCaretUp : toolbarIcons.dropdownCaretDown;
110993
- });
110994
- return (_ctx, _cache) => {
110995
- return vue.openBlock(), vue.createElementBlock("div", {
110996
- class: vue.normalizeClass(["toolbar-item", vue.unref(attributes).className]),
110997
- style: vue.normalizeStyle(getStyle.value),
110998
- role: __props.isOverflowItem ? "menuitem" : "button",
110999
- "aria-label": vue.unref(attributes).ariaLabel,
111000
- onClick: handleClick2,
111001
- onKeydown: vue.withKeys(vue.withModifiers(handleClick2, ["stop"]), ["enter"]),
111002
- tabindex: "0"
111003
- }, [
111004
- vue.createBaseVNode("div", {
111005
- class: vue.normalizeClass(["toolbar-button", {
111006
- active: vue.unref(active),
111007
- disabled: vue.unref(disabled),
111008
- narrow: __props.isNarrow,
111009
- wide: __props.isWide,
111010
- "has-inline-text-input": vue.unref(hasInlineTextInput),
111011
- "high-contrast": vue.unref(isHighContrastMode2)
111012
- }]),
111013
- "data-item": `btn-${vue.unref(name) || ""}`
111014
- }, [
111015
- vue.unref(icon) ? (vue.openBlock(), vue.createBlock(ToolbarButtonIcon, {
111016
- key: 0,
111017
- color: vue.unref(iconColor),
111018
- class: "toolbar-icon",
111019
- icon: vue.unref(icon),
111020
- name: vue.unref(name)
111021
- }, null, 8, ["color", "icon", "name"])) : vue.createCommentVNode("", true),
111022
- vue.unref(label) && !vue.unref(hideLabel) && !vue.unref(inlineTextInputVisible) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$2$1, vue.toDisplayString(vue.unref(label)), 1)) : vue.createCommentVNode("", true),
111023
- vue.unref(inlineTextInputVisible) ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4$1$1, [
111024
- vue.unref(name) === "fontSize" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
111025
- key: 0,
111026
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => inlineTextInput.value = $event),
111027
- onKeydown: vue.withKeys(vue.withModifiers(handleInputSubmit, ["prevent"]), ["enter"]),
111028
- type: "text",
111029
- class: vue.normalizeClass(["button-text-input button-text-input--font-size", { "high-contrast": vue.unref(isHighContrastMode2) }]),
111030
- id: "inlineTextInput-" + vue.unref(name),
111031
- autocomplete: "off",
111032
- ref_key: "inlineInput",
111033
- ref: inlineInput
111034
- }, null, 42, _hoisted_5$4)), [
111035
- [vue.vModelText, inlineTextInput.value]
111036
- ]) : vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
111037
- key: 1,
111038
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => inlineTextInput.value = $event),
111039
- placeholder: vue.unref(label),
111040
- onKeydown: vue.withKeys(vue.withModifiers(handleInputSubmit, ["prevent"]), ["enter"]),
111041
- type: "text",
111042
- class: "button-text-input",
111043
- id: "inlineTextInput-" + vue.unref(name),
111044
- autocomplete: "off",
111045
- ref_key: "inlineInput",
111046
- ref: inlineInput
111047
- }, null, 40, _hoisted_6$2)), [
111048
- [vue.vModelText, inlineTextInput.value]
111049
- ])
111050
- ])) : vue.createCommentVNode("", true),
111051
- vue.unref(hasCaret) ? (vue.openBlock(), vue.createElementBlock("div", {
111052
- key: 3,
111053
- class: "dropdown-caret",
111054
- innerHTML: caretIcon.value,
111055
- style: vue.normalizeStyle({ opacity: vue.unref(disabled) ? 0.6 : 1 })
111056
- }, null, 12, _hoisted_7$1)) : vue.createCommentVNode("", true),
111057
- vue.createBaseVNode("div", _hoisted_8$1, vue.toDisplayString(`${vue.unref(attributes).ariaLabel} ${vue.unref(active) ? "selected" : "unset"}`), 1)
111058
- ], 10, _hoisted_2$2$1)
111059
- ], 46, _hoisted_1$3$1);
111060
- };
111061
- }
111062
- };
111063
- const ToolbarButton = /* @__PURE__ */ _export_sfc(_sfc_main$4$1, [["__scopeId", "data-v-ea93b080"]]);
111064
- const _hoisted_1$2$1 = {
111065
- class: "toolbar-separator",
111066
- role: "separator",
111067
- "aria-label": "Toolbar separator"
111068
- };
111069
- const _sfc_main$3$1 = {
111070
- __name: "ToolbarSeparator",
111071
- props: {
111072
- active: {
111073
- type: Boolean,
111074
- default: false
111075
- }
111076
- },
111077
- emits: ["command"],
111078
- setup(__props, { emit: __emit }) {
111079
- const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
111080
- const getSeparatorColor = () => {
111081
- if (isHighContrastMode2.value) {
111082
- return "#000";
111083
- }
111084
- return "#dbdbdb";
111085
- };
111086
- return (_ctx, _cache) => {
111087
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2$1, [
111088
- vue.createBaseVNode("div", {
111089
- class: "separator-inner",
111090
- style: vue.normalizeStyle({ backgroundColor: getSeparatorColor() })
111091
- }, null, 4)
111092
- ]);
111093
- };
111094
- }
111095
- };
111096
- const ToolbarSeparator = /* @__PURE__ */ _export_sfc(_sfc_main$3$1, [["__scopeId", "data-v-4ef9aa18"]]);
111097
- const _hoisted_1$1$1 = { class: "overflow-menu" };
111098
- const _hoisted_2$1$1 = { class: "overflow-menu-trigger" };
111099
- const _hoisted_3$1$1 = {
111100
- key: 0,
111101
- class: "overflow-menu_items",
111102
- role: "group"
111103
- };
111104
- const _sfc_main$2$1 = {
111105
- __name: "OverflowMenu",
111106
- props: {
111107
- toolbarItem: {
111108
- type: Object,
111109
- required: true
111110
- },
111111
- overflowItems: {
111112
- type: Array,
111113
- required: true
111114
- }
111115
- },
111116
- emits: ["buttonClick", "close"],
111117
- setup(__props, { emit: __emit }) {
111118
- const { proxy } = vue.getCurrentInstance();
111119
- const emit = __emit;
111120
- const props = __props;
111121
- const isOverflowMenuOpened = vue.computed(() => props.toolbarItem.expand.value);
111122
- const hasOpenDropdown = vue.ref(false);
111123
- const overflowToolbarItem = vue.computed(() => ({
111124
- ...props.toolbarItem,
111125
- active: isOverflowMenuOpened.value
111126
- }));
111127
- const toggleOverflowMenu = () => {
111128
- emit("buttonClick", props.toolbarItem);
111129
- };
111130
- const handleCommand = ({ item, argument }) => {
111131
- proxy.$toolbar.emitCommand({ item, argument });
111132
- };
111133
- const handleKeyDown2 = (e) => {
111134
- if (e.key === "Escape") {
111135
- if (isOverflowMenuOpened.value && !hasOpenDropdown.value) {
111136
- e.preventDefault();
111137
- emit("close");
111138
- }
111139
- }
111140
- };
111141
- vue.onMounted(() => {
111142
- document.addEventListener("keydown", handleKeyDown2, true);
111143
- });
111144
- vue.onBeforeUnmount(() => {
111145
- document.removeEventListener("keydown", handleKeyDown2, true);
111146
- });
111147
- return (_ctx, _cache) => {
111148
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1$1, [
111149
- vue.createBaseVNode("div", _hoisted_2$1$1, [
111150
- vue.createVNode(ToolbarButton, {
111151
- "toolbar-item": overflowToolbarItem.value,
111152
- onButtonClick: toggleOverflowMenu
111153
- }, null, 8, ["toolbar-item"])
111154
- ]),
111155
- isOverflowMenuOpened.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1$1, [
111156
- vue.createVNode(ButtonGroup, {
111157
- class: "superdoc-toolbar-overflow",
111158
- "toolbar-items": __props.overflowItems,
111159
- "from-overflow": "",
111160
- onCommand: handleCommand,
111161
- onDropdownUpdateShow: _cache[0] || (_cache[0] = ($event) => hasOpenDropdown.value = $event)
111162
- }, null, 8, ["toolbar-items"])
111163
- ])) : vue.createCommentVNode("", true)
111164
- ]);
111165
- };
111166
- }
111167
- };
111168
- const OverflowMenu = /* @__PURE__ */ _export_sfc(_sfc_main$2$1, [["__scopeId", "data-v-ef28da92"]]);
111169
111159
  function plugin$1(options) {
111170
111160
  let _bPrefix = ".";
111171
111161
  let _ePrefix = "__";
@@ -114776,30 +114766,30 @@ const defaultClsPrefix = "n";
114776
114766
  function useConfig(props = {}, options = {
114777
114767
  defaultBordered: true
114778
114768
  }) {
114779
- const NConfigProvider = vue.inject(configProviderInjectionKey, null);
114769
+ const NConfigProvider2 = vue.inject(configProviderInjectionKey, null);
114780
114770
  return {
114781
114771
  // NConfigProvider,
114782
- inlineThemeDisabled: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.inlineThemeDisabled,
114783
- mergedRtlRef: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedRtlRef,
114784
- mergedComponentPropsRef: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedComponentPropsRef,
114785
- mergedBreakpointsRef: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedBreakpointsRef,
114772
+ inlineThemeDisabled: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.inlineThemeDisabled,
114773
+ mergedRtlRef: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedRtlRef,
114774
+ mergedComponentPropsRef: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedComponentPropsRef,
114775
+ mergedBreakpointsRef: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedBreakpointsRef,
114786
114776
  mergedBorderedRef: vue.computed(() => {
114787
114777
  var _a2, _b2;
114788
114778
  const {
114789
114779
  bordered
114790
114780
  } = props;
114791
114781
  if (bordered !== void 0) return bordered;
114792
- return (_b2 = (_a2 = NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedBorderedRef.value) !== null && _a2 !== void 0 ? _a2 : options.defaultBordered) !== null && _b2 !== void 0 ? _b2 : true;
114782
+ return (_b2 = (_a2 = NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedBorderedRef.value) !== null && _a2 !== void 0 ? _a2 : options.defaultBordered) !== null && _b2 !== void 0 ? _b2 : true;
114793
114783
  }),
114794
- mergedClsPrefixRef: NConfigProvider ? NConfigProvider.mergedClsPrefixRef : vue.shallowRef(defaultClsPrefix),
114795
- namespaceRef: vue.computed(() => NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedNamespaceRef.value)
114784
+ mergedClsPrefixRef: NConfigProvider2 ? NConfigProvider2.mergedClsPrefixRef : vue.shallowRef(defaultClsPrefix),
114785
+ namespaceRef: vue.computed(() => NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedNamespaceRef.value)
114796
114786
  };
114797
114787
  }
114798
114788
  function useThemeClass(componentName, hashRef, cssVarsRef, props) {
114799
114789
  if (!cssVarsRef) throwError("useThemeClass", "cssVarsRef is not passed");
114800
- const NConfigProvider = vue.inject(configProviderInjectionKey, null);
114801
- const mergedThemeHashRef = NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedThemeHashRef;
114802
- const styleMountTarget = NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.styleMountTarget;
114790
+ const NConfigProvider2 = vue.inject(configProviderInjectionKey, null);
114791
+ const mergedThemeHashRef = NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeHashRef;
114792
+ const styleMountTarget = NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.styleMountTarget;
114803
114793
  const themeClassRef = vue.ref("");
114804
114794
  const ssrAdapter2 = useSsrAdapter();
114805
114795
  let renderCallback;
@@ -116144,7 +116134,7 @@ function useRtl(mountId, rtlStateRef, clsPrefixRef) {
116144
116134
  }
116145
116135
  return componentRtlState;
116146
116136
  });
116147
- const NConfigProvider = vue.inject(configProviderInjectionKey, null);
116137
+ const NConfigProvider2 = vue.inject(configProviderInjectionKey, null);
116148
116138
  const mountStyle = () => {
116149
116139
  vue.watchEffect(() => {
116150
116140
  const {
@@ -116164,7 +116154,7 @@ function useRtl(mountId, rtlStateRef, clsPrefixRef) {
116164
116154
  bPrefix: clsPrefix ? `.${clsPrefix}-` : void 0
116165
116155
  },
116166
116156
  ssr: ssrAdapter2,
116167
- parent: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.styleMountTarget
116157
+ parent: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.styleMountTarget
116168
116158
  });
116169
116159
  });
116170
116160
  };
@@ -116222,7 +116212,7 @@ function createTheme(theme) {
116222
116212
  }
116223
116213
  function useTheme(resolveId, mountId, style2, defaultTheme, props, clsPrefixRef) {
116224
116214
  const ssrAdapter2 = useSsrAdapter();
116225
- const NConfigProvider = vue.inject(configProviderInjectionKey, null);
116215
+ const NConfigProvider2 = vue.inject(configProviderInjectionKey, null);
116226
116216
  if (style2) {
116227
116217
  const mountStyle = () => {
116228
116218
  const clsPrefix = clsPrefixRef === null || clsPrefixRef === void 0 ? void 0 : clsPrefixRef.value;
@@ -116234,15 +116224,15 @@ function useTheme(resolveId, mountId, style2, defaultTheme, props, clsPrefixRef)
116234
116224
  },
116235
116225
  anchorMetaName: cssrAnchorMetaName,
116236
116226
  ssr: ssrAdapter2,
116237
- parent: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.styleMountTarget
116227
+ parent: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.styleMountTarget
116238
116228
  });
116239
- if (!(NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.preflightStyleDisabled)) {
116229
+ if (!(NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.preflightStyleDisabled)) {
116240
116230
  globalStyle.mount({
116241
116231
  id: "n-global",
116242
116232
  head: true,
116243
116233
  anchorMetaName: cssrAnchorMetaName,
116244
116234
  ssr: ssrAdapter2,
116245
- parent: NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.styleMountTarget
116235
+ parent: NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.styleMountTarget
116246
116236
  });
116247
116237
  }
116248
116238
  };
@@ -116274,11 +116264,11 @@ function useTheme(resolveId, mountId, style2, defaultTheme, props, clsPrefixRef)
116274
116264
  self: globalSelf = void 0,
116275
116265
  peers: globalPeers = {}
116276
116266
  } = {}
116277
- } = (NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedThemeRef.value) || {};
116267
+ } = (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeRef.value) || {};
116278
116268
  const {
116279
116269
  common: globalCommonOverrides = void 0,
116280
116270
  [resolveId]: globalSelfOverrides = {}
116281
- } = (NConfigProvider === null || NConfigProvider === void 0 ? void 0 : NConfigProvider.mergedThemeOverridesRef.value) || {};
116271
+ } = (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeOverridesRef.value) || {};
116282
116272
  const {
116283
116273
  common: globalSelfCommonOverrides,
116284
116274
  peers: globalPeersOverrides = {}
@@ -119036,6 +119026,209 @@ const NPopover = vue.defineComponent({
119036
119026
  });
119037
119027
  }
119038
119028
  });
119029
+ const configProviderProps = {
119030
+ abstract: Boolean,
119031
+ bordered: {
119032
+ type: Boolean,
119033
+ default: void 0
119034
+ },
119035
+ clsPrefix: String,
119036
+ locale: Object,
119037
+ dateLocale: Object,
119038
+ namespace: String,
119039
+ rtl: Array,
119040
+ tag: {
119041
+ type: String,
119042
+ default: "div"
119043
+ },
119044
+ hljs: Object,
119045
+ katex: Object,
119046
+ theme: Object,
119047
+ themeOverrides: Object,
119048
+ componentOptions: Object,
119049
+ icons: Object,
119050
+ breakpoints: Object,
119051
+ preflightStyleDisabled: Boolean,
119052
+ styleMountTarget: Object,
119053
+ inlineThemeDisabled: {
119054
+ type: Boolean,
119055
+ default: void 0
119056
+ },
119057
+ // deprecated
119058
+ as: {
119059
+ type: String,
119060
+ validator: () => {
119061
+ warn("config-provider", "`as` is deprecated, please use `tag` instead.");
119062
+ return true;
119063
+ },
119064
+ default: void 0
119065
+ }
119066
+ };
119067
+ const NConfigProvider = vue.defineComponent({
119068
+ name: "ConfigProvider",
119069
+ alias: ["App"],
119070
+ props: configProviderProps,
119071
+ setup(props) {
119072
+ const NConfigProvider2 = vue.inject(configProviderInjectionKey, null);
119073
+ const mergedThemeRef = vue.computed(() => {
119074
+ const {
119075
+ theme
119076
+ } = props;
119077
+ if (theme === null) return void 0;
119078
+ const inheritedTheme = NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeRef.value;
119079
+ return theme === void 0 ? inheritedTheme : inheritedTheme === void 0 ? theme : Object.assign({}, inheritedTheme, theme);
119080
+ });
119081
+ const mergedThemeOverridesRef = vue.computed(() => {
119082
+ const {
119083
+ themeOverrides
119084
+ } = props;
119085
+ if (themeOverrides === null) return void 0;
119086
+ if (themeOverrides === void 0) {
119087
+ return NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeOverridesRef.value;
119088
+ } else {
119089
+ const inheritedThemeOverrides = NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedThemeOverridesRef.value;
119090
+ if (inheritedThemeOverrides === void 0) {
119091
+ return themeOverrides;
119092
+ } else {
119093
+ return merge$1({}, inheritedThemeOverrides, themeOverrides);
119094
+ }
119095
+ }
119096
+ });
119097
+ const mergedNamespaceRef = useMemo(() => {
119098
+ const {
119099
+ namespace: namespace2
119100
+ } = props;
119101
+ return namespace2 === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedNamespaceRef.value : namespace2;
119102
+ });
119103
+ const mergedBorderedRef = useMemo(() => {
119104
+ const {
119105
+ bordered
119106
+ } = props;
119107
+ return bordered === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedBorderedRef.value : bordered;
119108
+ });
119109
+ const mergedIconsRef = vue.computed(() => {
119110
+ const {
119111
+ icons: icons2
119112
+ } = props;
119113
+ return icons2 === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedIconsRef.value : icons2;
119114
+ });
119115
+ const mergedComponentPropsRef = vue.computed(() => {
119116
+ const {
119117
+ componentOptions
119118
+ } = props;
119119
+ if (componentOptions !== void 0) return componentOptions;
119120
+ return NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedComponentPropsRef.value;
119121
+ });
119122
+ const mergedClsPrefixRef = vue.computed(() => {
119123
+ const {
119124
+ clsPrefix
119125
+ } = props;
119126
+ if (clsPrefix !== void 0) return clsPrefix;
119127
+ if (NConfigProvider2) return NConfigProvider2.mergedClsPrefixRef.value;
119128
+ return defaultClsPrefix;
119129
+ });
119130
+ const mergedRtlRef = vue.computed(() => {
119131
+ var _a2;
119132
+ const {
119133
+ rtl
119134
+ } = props;
119135
+ if (rtl === void 0) {
119136
+ return NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedRtlRef.value;
119137
+ }
119138
+ const rtlEnabledState = {};
119139
+ for (const rtlInfo of rtl) {
119140
+ rtlEnabledState[rtlInfo.name] = vue.markRaw(rtlInfo);
119141
+ (_a2 = rtlInfo.peers) === null || _a2 === void 0 ? void 0 : _a2.forEach((peerRtlInfo) => {
119142
+ if (!(peerRtlInfo.name in rtlEnabledState)) {
119143
+ rtlEnabledState[peerRtlInfo.name] = vue.markRaw(peerRtlInfo);
119144
+ }
119145
+ });
119146
+ }
119147
+ return rtlEnabledState;
119148
+ });
119149
+ const mergedBreakpointsRef = vue.computed(() => {
119150
+ return props.breakpoints || (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedBreakpointsRef.value);
119151
+ });
119152
+ const inlineThemeDisabled = props.inlineThemeDisabled || (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.inlineThemeDisabled);
119153
+ const preflightStyleDisabled = props.preflightStyleDisabled || (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.preflightStyleDisabled);
119154
+ const styleMountTarget = props.styleMountTarget || (NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.styleMountTarget);
119155
+ const mergedThemeHashRef = vue.computed(() => {
119156
+ const {
119157
+ value: theme
119158
+ } = mergedThemeRef;
119159
+ const {
119160
+ value: mergedThemeOverrides
119161
+ } = mergedThemeOverridesRef;
119162
+ const hasThemeOverrides = mergedThemeOverrides && Object.keys(mergedThemeOverrides).length !== 0;
119163
+ const themeName = theme === null || theme === void 0 ? void 0 : theme.name;
119164
+ if (themeName) {
119165
+ if (hasThemeOverrides) {
119166
+ return `${themeName}-${murmur2(JSON.stringify(mergedThemeOverridesRef.value))}`;
119167
+ }
119168
+ return themeName;
119169
+ } else {
119170
+ if (hasThemeOverrides) {
119171
+ return murmur2(JSON.stringify(mergedThemeOverridesRef.value));
119172
+ }
119173
+ return "";
119174
+ }
119175
+ });
119176
+ vue.provide(configProviderInjectionKey, {
119177
+ mergedThemeHashRef,
119178
+ mergedBreakpointsRef,
119179
+ mergedRtlRef,
119180
+ mergedIconsRef,
119181
+ mergedComponentPropsRef,
119182
+ mergedBorderedRef,
119183
+ mergedNamespaceRef,
119184
+ mergedClsPrefixRef,
119185
+ mergedLocaleRef: vue.computed(() => {
119186
+ const {
119187
+ locale
119188
+ } = props;
119189
+ if (locale === null) return void 0;
119190
+ return locale === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedLocaleRef.value : locale;
119191
+ }),
119192
+ mergedDateLocaleRef: vue.computed(() => {
119193
+ const {
119194
+ dateLocale
119195
+ } = props;
119196
+ if (dateLocale === null) return void 0;
119197
+ return dateLocale === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedDateLocaleRef.value : dateLocale;
119198
+ }),
119199
+ mergedHljsRef: vue.computed(() => {
119200
+ const {
119201
+ hljs
119202
+ } = props;
119203
+ return hljs === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedHljsRef.value : hljs;
119204
+ }),
119205
+ mergedKatexRef: vue.computed(() => {
119206
+ const {
119207
+ katex
119208
+ } = props;
119209
+ return katex === void 0 ? NConfigProvider2 === null || NConfigProvider2 === void 0 ? void 0 : NConfigProvider2.mergedKatexRef.value : katex;
119210
+ }),
119211
+ mergedThemeRef,
119212
+ mergedThemeOverridesRef,
119213
+ inlineThemeDisabled: inlineThemeDisabled || false,
119214
+ preflightStyleDisabled: preflightStyleDisabled || false,
119215
+ styleMountTarget
119216
+ });
119217
+ return {
119218
+ mergedClsPrefix: mergedClsPrefixRef,
119219
+ mergedBordered: mergedBorderedRef,
119220
+ mergedNamespace: mergedNamespaceRef,
119221
+ mergedTheme: mergedThemeRef,
119222
+ mergedThemeOverrides: mergedThemeOverridesRef
119223
+ };
119224
+ },
119225
+ render() {
119226
+ var _a2, _b2, _c, _d;
119227
+ return !this.abstract ? vue.h(this.as || this.tag, {
119228
+ class: `${this.mergedClsPrefix || defaultClsPrefix}-config-provider`
119229
+ }, (_b2 = (_a2 = this.$slots).default) === null || _b2 === void 0 ? void 0 : _b2.call(_a2)) : (_d = (_c = this.$slots).default) === null || _d === void 0 ? void 0 : _d.call(_c);
119230
+ }
119231
+ });
119039
119232
  const commonVariables = {
119040
119233
  padding: "4px 0",
119041
119234
  optionIconSizeSmall: "14px",
@@ -120513,6 +120706,316 @@ const NSkeleton = vue.defineComponent({
120513
120706
  return child;
120514
120707
  }
120515
120708
  });
120709
+ const _hoisted_1$4$1 = { class: "toolbar-icon" };
120710
+ const _hoisted_2$3$1 = ["innerHTML"];
120711
+ const _sfc_main$5$1 = {
120712
+ __name: "ToolbarButtonIcon",
120713
+ props: {
120714
+ name: {
120715
+ type: String,
120716
+ required: true
120717
+ },
120718
+ color: {
120719
+ type: String,
120720
+ default: null
120721
+ },
120722
+ icon: {
120723
+ type: String,
120724
+ default: null
120725
+ }
120726
+ },
120727
+ setup(__props) {
120728
+ const props = __props;
120729
+ const getBarColor = vue.computed(() => {
120730
+ if (props.name === "color") return { backgroundColor: props.color || "#111111" };
120731
+ if (props.name === "highlight") return { backgroundColor: props.color || "#D6D6D6" };
120732
+ });
120733
+ const hasColorBar = vue.computed(() => {
120734
+ return ["color", "highlight"].includes(props.name);
120735
+ });
120736
+ return (_ctx, _cache) => {
120737
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4$1, [
120738
+ vue.createBaseVNode("div", {
120739
+ class: vue.normalizeClass(["toolbar-icon__icon", [`toolbar-icon__icon--${props.name}`]]),
120740
+ innerHTML: __props.icon
120741
+ }, null, 10, _hoisted_2$3$1),
120742
+ hasColorBar.value ? (vue.openBlock(), vue.createElementBlock("div", {
120743
+ key: 0,
120744
+ class: "color-bar",
120745
+ style: vue.normalizeStyle(getBarColor.value)
120746
+ }, null, 4)) : vue.createCommentVNode("", true)
120747
+ ]);
120748
+ };
120749
+ }
120750
+ };
120751
+ const ToolbarButtonIcon = /* @__PURE__ */ _export_sfc(_sfc_main$5$1, [["__scopeId", "data-v-6d7523ab"]]);
120752
+ const _hoisted_1$3$1 = ["role", "aria-label", "onKeydown"];
120753
+ const _hoisted_2$2$1 = ["data-item"];
120754
+ const _hoisted_3$2$1 = {
120755
+ key: 1,
120756
+ class: "button-label"
120757
+ };
120758
+ const _hoisted_4$1$1 = { key: 2 };
120759
+ const _hoisted_5$4 = ["onKeydown", "id"];
120760
+ const _hoisted_6$2 = ["placeholder", "onKeydown", "id"];
120761
+ const _hoisted_7$1 = ["innerHTML"];
120762
+ const _hoisted_8$1 = {
120763
+ "aria-live": "polite",
120764
+ class: "visually-hidden"
120765
+ };
120766
+ const _sfc_main$4$1 = {
120767
+ __name: "ToolbarButton",
120768
+ props: {
120769
+ iconColor: {
120770
+ type: String,
120771
+ default: null
120772
+ },
120773
+ active: {
120774
+ type: Boolean,
120775
+ default: false
120776
+ },
120777
+ isNarrow: {
120778
+ type: Boolean,
120779
+ default: false
120780
+ },
120781
+ isWide: {
120782
+ type: Boolean,
120783
+ default: false
120784
+ },
120785
+ toolbarItem: {
120786
+ type: Object,
120787
+ required: true
120788
+ },
120789
+ defaultLabel: {
120790
+ type: String,
120791
+ default: null
120792
+ },
120793
+ isOverflowItem: {
120794
+ type: Boolean,
120795
+ default: false
120796
+ }
120797
+ },
120798
+ emits: ["buttonClick", "textSubmit"],
120799
+ setup(__props, { emit: __emit }) {
120800
+ const emit = __emit;
120801
+ const props = __props;
120802
+ const {
120803
+ name,
120804
+ active,
120805
+ icon,
120806
+ label,
120807
+ hideLabel,
120808
+ iconColor,
120809
+ hasCaret,
120810
+ disabled,
120811
+ inlineTextInputVisible,
120812
+ hasInlineTextInput,
120813
+ minWidth,
120814
+ style: style2,
120815
+ attributes
120816
+ } = props.toolbarItem;
120817
+ const inlineTextInput = vue.ref(label);
120818
+ const inlineInput = vue.ref(null);
120819
+ const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
120820
+ const handleClick2 = () => {
120821
+ if (hasInlineTextInput) {
120822
+ vue.nextTick(() => {
120823
+ inlineInput.value?.focus();
120824
+ inlineInput.value?.select();
120825
+ });
120826
+ }
120827
+ emit("buttonClick");
120828
+ };
120829
+ const handleInputSubmit = () => {
120830
+ const value = inlineTextInput.value;
120831
+ const cleanValue = value.match(/^\d+(\.5)?$/) ? value : Math.floor(parseFloat(value)).toString();
120832
+ emit("textSubmit", cleanValue);
120833
+ inlineTextInput.value = cleanValue;
120834
+ };
120835
+ const getStyle = vue.computed(() => {
120836
+ if (style2.value) return style2.value;
120837
+ return {
120838
+ minWidth: props.minWidth
120839
+ };
120840
+ });
120841
+ const caretIcon = vue.computed(() => {
120842
+ return active.value ? toolbarIcons.dropdownCaretUp : toolbarIcons.dropdownCaretDown;
120843
+ });
120844
+ return (_ctx, _cache) => {
120845
+ return vue.openBlock(), vue.createElementBlock("div", {
120846
+ class: vue.normalizeClass(["toolbar-item", vue.unref(attributes).className]),
120847
+ style: vue.normalizeStyle(getStyle.value),
120848
+ role: __props.isOverflowItem ? "menuitem" : "button",
120849
+ "aria-label": vue.unref(attributes).ariaLabel,
120850
+ onClick: handleClick2,
120851
+ onKeydown: vue.withKeys(vue.withModifiers(handleClick2, ["stop"]), ["enter"]),
120852
+ tabindex: "0"
120853
+ }, [
120854
+ vue.createBaseVNode("div", {
120855
+ class: vue.normalizeClass(["toolbar-button", {
120856
+ active: vue.unref(active),
120857
+ disabled: vue.unref(disabled),
120858
+ narrow: __props.isNarrow,
120859
+ wide: __props.isWide,
120860
+ "has-inline-text-input": vue.unref(hasInlineTextInput),
120861
+ "high-contrast": vue.unref(isHighContrastMode2)
120862
+ }]),
120863
+ "data-item": `btn-${vue.unref(name) || ""}`
120864
+ }, [
120865
+ vue.unref(icon) ? (vue.openBlock(), vue.createBlock(ToolbarButtonIcon, {
120866
+ key: 0,
120867
+ color: vue.unref(iconColor),
120868
+ class: "toolbar-icon",
120869
+ icon: vue.unref(icon),
120870
+ name: vue.unref(name)
120871
+ }, null, 8, ["color", "icon", "name"])) : vue.createCommentVNode("", true),
120872
+ vue.unref(label) && !vue.unref(hideLabel) && !vue.unref(inlineTextInputVisible) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$2$1, vue.toDisplayString(vue.unref(label)), 1)) : vue.createCommentVNode("", true),
120873
+ vue.unref(inlineTextInputVisible) ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4$1$1, [
120874
+ vue.unref(name) === "fontSize" ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
120875
+ key: 0,
120876
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => inlineTextInput.value = $event),
120877
+ onKeydown: vue.withKeys(vue.withModifiers(handleInputSubmit, ["prevent"]), ["enter"]),
120878
+ type: "text",
120879
+ class: vue.normalizeClass(["button-text-input button-text-input--font-size", { "high-contrast": vue.unref(isHighContrastMode2) }]),
120880
+ id: "inlineTextInput-" + vue.unref(name),
120881
+ autocomplete: "off",
120882
+ ref_key: "inlineInput",
120883
+ ref: inlineInput
120884
+ }, null, 42, _hoisted_5$4)), [
120885
+ [vue.vModelText, inlineTextInput.value]
120886
+ ]) : vue.withDirectives((vue.openBlock(), vue.createElementBlock("input", {
120887
+ key: 1,
120888
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => inlineTextInput.value = $event),
120889
+ placeholder: vue.unref(label),
120890
+ onKeydown: vue.withKeys(vue.withModifiers(handleInputSubmit, ["prevent"]), ["enter"]),
120891
+ type: "text",
120892
+ class: "button-text-input",
120893
+ id: "inlineTextInput-" + vue.unref(name),
120894
+ autocomplete: "off",
120895
+ ref_key: "inlineInput",
120896
+ ref: inlineInput
120897
+ }, null, 40, _hoisted_6$2)), [
120898
+ [vue.vModelText, inlineTextInput.value]
120899
+ ])
120900
+ ])) : vue.createCommentVNode("", true),
120901
+ vue.unref(hasCaret) ? (vue.openBlock(), vue.createElementBlock("div", {
120902
+ key: 3,
120903
+ class: "dropdown-caret",
120904
+ innerHTML: caretIcon.value,
120905
+ style: vue.normalizeStyle({ opacity: vue.unref(disabled) ? 0.6 : 1 })
120906
+ }, null, 12, _hoisted_7$1)) : vue.createCommentVNode("", true),
120907
+ vue.createBaseVNode("div", _hoisted_8$1, vue.toDisplayString(`${vue.unref(attributes).ariaLabel} ${vue.unref(active) ? "selected" : "unset"}`), 1)
120908
+ ], 10, _hoisted_2$2$1)
120909
+ ], 46, _hoisted_1$3$1);
120910
+ };
120911
+ }
120912
+ };
120913
+ const ToolbarButton = /* @__PURE__ */ _export_sfc(_sfc_main$4$1, [["__scopeId", "data-v-ea93b080"]]);
120914
+ const _hoisted_1$2$1 = {
120915
+ class: "toolbar-separator",
120916
+ role: "separator",
120917
+ "aria-label": "Toolbar separator"
120918
+ };
120919
+ const _sfc_main$3$1 = {
120920
+ __name: "ToolbarSeparator",
120921
+ props: {
120922
+ active: {
120923
+ type: Boolean,
120924
+ default: false
120925
+ }
120926
+ },
120927
+ emits: ["command"],
120928
+ setup(__props, { emit: __emit }) {
120929
+ const { isHighContrastMode: isHighContrastMode2 } = useHighContrastMode();
120930
+ const getSeparatorColor = () => {
120931
+ if (isHighContrastMode2.value) {
120932
+ return "#000";
120933
+ }
120934
+ return "#dbdbdb";
120935
+ };
120936
+ return (_ctx, _cache) => {
120937
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2$1, [
120938
+ vue.createBaseVNode("div", {
120939
+ class: "separator-inner",
120940
+ style: vue.normalizeStyle({ backgroundColor: getSeparatorColor() })
120941
+ }, null, 4)
120942
+ ]);
120943
+ };
120944
+ }
120945
+ };
120946
+ const ToolbarSeparator = /* @__PURE__ */ _export_sfc(_sfc_main$3$1, [["__scopeId", "data-v-4ef9aa18"]]);
120947
+ const _hoisted_1$1$1 = { class: "overflow-menu" };
120948
+ const _hoisted_2$1$1 = { class: "overflow-menu-trigger" };
120949
+ const _hoisted_3$1$1 = {
120950
+ key: 0,
120951
+ class: "overflow-menu_items",
120952
+ role: "group"
120953
+ };
120954
+ const _sfc_main$2$1 = {
120955
+ __name: "OverflowMenu",
120956
+ props: {
120957
+ toolbarItem: {
120958
+ type: Object,
120959
+ required: true
120960
+ },
120961
+ overflowItems: {
120962
+ type: Array,
120963
+ required: true
120964
+ }
120965
+ },
120966
+ emits: ["buttonClick", "close"],
120967
+ setup(__props, { emit: __emit }) {
120968
+ const { proxy } = vue.getCurrentInstance();
120969
+ const emit = __emit;
120970
+ const props = __props;
120971
+ const isOverflowMenuOpened = vue.computed(() => props.toolbarItem.expand.value);
120972
+ const hasOpenDropdown = vue.ref(false);
120973
+ const overflowToolbarItem = vue.computed(() => ({
120974
+ ...props.toolbarItem,
120975
+ active: isOverflowMenuOpened.value
120976
+ }));
120977
+ const toggleOverflowMenu = () => {
120978
+ emit("buttonClick", props.toolbarItem);
120979
+ };
120980
+ const handleCommand = ({ item, argument }) => {
120981
+ proxy.$toolbar.emitCommand({ item, argument });
120982
+ };
120983
+ const handleKeyDown2 = (e) => {
120984
+ if (e.key === "Escape") {
120985
+ if (isOverflowMenuOpened.value && !hasOpenDropdown.value) {
120986
+ e.preventDefault();
120987
+ emit("close");
120988
+ }
120989
+ }
120990
+ };
120991
+ vue.onMounted(() => {
120992
+ document.addEventListener("keydown", handleKeyDown2, true);
120993
+ });
120994
+ vue.onBeforeUnmount(() => {
120995
+ document.removeEventListener("keydown", handleKeyDown2, true);
120996
+ });
120997
+ return (_ctx, _cache) => {
120998
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1$1, [
120999
+ vue.createBaseVNode("div", _hoisted_2$1$1, [
121000
+ vue.createVNode(ToolbarButton, {
121001
+ "toolbar-item": overflowToolbarItem.value,
121002
+ onButtonClick: toggleOverflowMenu
121003
+ }, null, 8, ["toolbar-item"])
121004
+ ]),
121005
+ isOverflowMenuOpened.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1$1, [
121006
+ vue.createVNode(ButtonGroup, {
121007
+ class: "superdoc-toolbar-overflow",
121008
+ "toolbar-items": __props.overflowItems,
121009
+ "from-overflow": "",
121010
+ onCommand: handleCommand,
121011
+ onDropdownUpdateShow: _cache[0] || (_cache[0] = ($event) => hasOpenDropdown.value = $event)
121012
+ }, null, 8, ["toolbar-items"])
121013
+ ])) : vue.createCommentVNode("", true)
121014
+ ]);
121015
+ };
121016
+ }
121017
+ };
121018
+ const OverflowMenu = /* @__PURE__ */ _export_sfc(_sfc_main$2$1, [["__scopeId", "data-v-ef28da92"]]);
120516
121019
  const _hoisted_1$h = ["onKeydown", "tabindex", "data-item-id"];
120517
121020
  const _hoisted_2$b = { key: 0 };
120518
121021
  const _hoisted_3$9 = { key: 0 };
@@ -120528,6 +121031,16 @@ const _sfc_main$1$1 = {
120528
121031
  type: Array,
120529
121032
  default: () => []
120530
121033
  },
121034
+ /**
121035
+ * The font-family to use for UI elements like dropdowns and tooltips.
121036
+ * This ensures consistent typography across toolbar UI components.
121037
+ * @type {string}
121038
+ * @default 'Arial, Helvetica, sans-serif'
121039
+ */
121040
+ uiFontFamily: {
121041
+ type: String,
121042
+ default: "Arial, Helvetica, sans-serif"
121043
+ },
120531
121044
  position: {
120532
121045
  type: String,
120533
121046
  default: "left"
@@ -120720,6 +121233,7 @@ const _sfc_main$1$1 = {
120720
121233
  options: dropdownOptions(item),
120721
121234
  trigger: item.disabled.value ? null : "click",
120722
121235
  show: item.expand.value,
121236
+ "content-style": { fontFamily: props.uiFontFamily },
120723
121237
  size: "medium",
120724
121238
  placement: "bottom-start",
120725
121239
  class: vue.normalizeClass(["toolbar-button toolbar-dropdown sd-editor-toolbar-dropdown", { "high-contrast": vue.unref(isHighContrastMode2) }]),
@@ -120727,14 +121241,16 @@ const _sfc_main$1$1 = {
120727
121241
  onUpdateShow: handleDropdownUpdateShow,
120728
121242
  style: vue.normalizeStyle(item.dropdownStyles.value),
120729
121243
  "menu-props": () => ({
120730
- role: "menu"
121244
+ role: "menu",
121245
+ style: { fontFamily: props.uiFontFamily }
120731
121246
  }),
120732
121247
  "node-props": (option) => getDropdownAttributes(option, item)
120733
121248
  }, {
120734
121249
  default: vue.withCtx(() => [
120735
121250
  vue.createVNode(vue.unref(NTooltip), {
120736
121251
  trigger: "hover",
120737
- disabled: !item.tooltip?.value
121252
+ disabled: !item.tooltip?.value,
121253
+ "content-style": { fontFamily: props.uiFontFamily }
120738
121254
  }, {
120739
121255
  trigger: vue.withCtx(() => [
120740
121256
  vue.createVNode(ToolbarButton, {
@@ -120751,13 +121267,14 @@ const _sfc_main$1$1 = {
120751
121267
  ])
120752
121268
  ]),
120753
121269
  _: 2
120754
- }, 1032, ["disabled"])
121270
+ }, 1032, ["disabled", "content-style"])
120755
121271
  ]),
120756
121272
  _: 2
120757
- }, 1032, ["options", "trigger", "show", "class", "onSelect", "style", "node-props"])) : isButton(item) ? (vue.openBlock(), vue.createBlock(vue.unref(NTooltip), {
121273
+ }, 1032, ["options", "trigger", "show", "content-style", "class", "onSelect", "style", "menu-props", "node-props"])) : isButton(item) ? (vue.openBlock(), vue.createBlock(vue.unref(NTooltip), {
120758
121274
  key: 2,
120759
121275
  trigger: "hover",
120760
- class: "sd-editor-toolbar-tooltip"
121276
+ class: "sd-editor-toolbar-tooltip",
121277
+ "content-style": { fontFamily: props.uiFontFamily }
120761
121278
  }, {
120762
121279
  trigger: vue.withCtx(() => [
120763
121280
  vue.createVNode(ToolbarButton, {
@@ -120774,7 +121291,7 @@ const _sfc_main$1$1 = {
120774
121291
  ])) : vue.createCommentVNode("", true)
120775
121292
  ]),
120776
121293
  _: 2
120777
- }, 1024)) : vue.createCommentVNode("", true),
121294
+ }, 1032, ["content-style"])) : vue.createCommentVNode("", true),
120778
121295
  isOverflow(item) && __props.overflowItems.length ? (vue.openBlock(), vue.createBlock(OverflowMenu, {
120779
121296
  key: 3,
120780
121297
  "toolbar-item": item,
@@ -120788,13 +121305,21 @@ const _sfc_main$1$1 = {
120788
121305
  };
120789
121306
  }
120790
121307
  };
120791
- const ButtonGroup = /* @__PURE__ */ _export_sfc(_sfc_main$1$1, [["__scopeId", "data-v-c80a1e51"]]);
121308
+ const ButtonGroup = /* @__PURE__ */ _export_sfc(_sfc_main$1$1, [["__scopeId", "data-v-f732136c"]]);
121309
+ const DEFAULT_UI_FONT_FAMILY = "Arial, Helvetica, sans-serif";
120792
121310
  const _sfc_main$j = {
120793
121311
  __name: "Toolbar",
120794
121312
  emits: ["command", "toggle", "select"],
120795
121313
  setup(__props, { emit: __emit }) {
120796
121314
  const { proxy } = vue.getCurrentInstance();
120797
121315
  let toolbarKey = vue.ref(1);
121316
+ const uiFontFamily = vue.computed(() => {
121317
+ const configured = proxy?.$toolbar?.config?.uiDisplayFallbackFont;
121318
+ if (typeof configured === "string" && configured.trim()) {
121319
+ return configured.trim();
121320
+ }
121321
+ return DEFAULT_UI_FONT_FAMILY;
121322
+ });
120798
121323
  const showLeftSide = proxy.$toolbar.config?.toolbarGroups?.includes("left");
120799
121324
  const showRightSide = proxy.$toolbar.config?.toolbarGroups?.includes("right");
120800
121325
  const excludeButtonsList = proxy.$toolbar.config?.toolbarButtonsExclude || [];
@@ -120841,37 +121366,48 @@ const _sfc_main$j = {
120841
121366
  "aria-label": "Toolbar",
120842
121367
  "data-editor-ui-surface": ""
120843
121368
  }, [
120844
- vue.unref(showLeftSide) ? (vue.openBlock(), vue.createBlock(ButtonGroup, {
120845
- key: 0,
120846
- tabindex: "0",
120847
- "toolbar-items": getFilteredItems("left"),
120848
- position: "left",
120849
- onCommand: handleCommand,
120850
- onItemClicked: restoreSelection2,
120851
- class: "superdoc-toolbar-group-side"
120852
- }, null, 8, ["toolbar-items"])) : vue.createCommentVNode("", true),
120853
- vue.createVNode(ButtonGroup, {
120854
- tabindex: "0",
120855
- "toolbar-items": getFilteredItems("center"),
120856
- "overflow-items": vue.unref(proxy).$toolbar.overflowItems,
120857
- position: "center",
120858
- onCommand: handleCommand,
120859
- onItemClicked: restoreSelection2
120860
- }, null, 8, ["toolbar-items", "overflow-items"]),
120861
- vue.unref(showRightSide) ? (vue.openBlock(), vue.createBlock(ButtonGroup, {
120862
- key: 1,
120863
- tabindex: "0",
120864
- "toolbar-items": getFilteredItems("right"),
120865
- position: "right",
120866
- onCommand: handleCommand,
120867
- onItemClicked: restoreSelection2,
120868
- class: "superdoc-toolbar-group-side"
120869
- }, null, 8, ["toolbar-items"])) : vue.createCommentVNode("", true)
121369
+ vue.createVNode(vue.unref(NConfigProvider), {
121370
+ abstract: "",
121371
+ "preflight-style-disabled": ""
121372
+ }, {
121373
+ default: vue.withCtx(() => [
121374
+ vue.unref(showLeftSide) ? (vue.openBlock(), vue.createBlock(ButtonGroup, {
121375
+ key: 0,
121376
+ tabindex: "0",
121377
+ "toolbar-items": getFilteredItems("left"),
121378
+ "ui-font-family": uiFontFamily.value,
121379
+ position: "left",
121380
+ onCommand: handleCommand,
121381
+ onItemClicked: restoreSelection2,
121382
+ class: "superdoc-toolbar-group-side"
121383
+ }, null, 8, ["toolbar-items", "ui-font-family"])) : vue.createCommentVNode("", true),
121384
+ vue.createVNode(ButtonGroup, {
121385
+ tabindex: "0",
121386
+ "toolbar-items": getFilteredItems("center"),
121387
+ "overflow-items": vue.unref(proxy).$toolbar.overflowItems,
121388
+ "ui-font-family": uiFontFamily.value,
121389
+ position: "center",
121390
+ onCommand: handleCommand,
121391
+ onItemClicked: restoreSelection2
121392
+ }, null, 8, ["toolbar-items", "overflow-items", "ui-font-family"]),
121393
+ vue.unref(showRightSide) ? (vue.openBlock(), vue.createBlock(ButtonGroup, {
121394
+ key: 1,
121395
+ tabindex: "0",
121396
+ "toolbar-items": getFilteredItems("right"),
121397
+ "ui-font-family": uiFontFamily.value,
121398
+ position: "right",
121399
+ onCommand: handleCommand,
121400
+ onItemClicked: restoreSelection2,
121401
+ class: "superdoc-toolbar-group-side"
121402
+ }, null, 8, ["toolbar-items", "ui-font-family"])) : vue.createCommentVNode("", true)
121403
+ ]),
121404
+ _: 1
121405
+ })
120870
121406
  ]);
120871
121407
  };
120872
121408
  }
120873
121409
  };
120874
- const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-3f5ec271"]]);
121410
+ const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-c7a72aa9"]]);
120875
121411
  const DEFAULT_API_ENDPOINT = "https://sd-dev-express-gateway-i6xtm.ondigitalocean.app/insights";
120876
121412
  const SYSTEM_PROMPT = "You are an expert copywriter and you are immersed in a document editor. You are to provide document related text responses based on the user prompts. Only write what is asked for. Do not provide explanations. Try to keep placeholders as short as possible. Do not output your prompt. Your instructions are: ";
120877
121413
  async function baseInsightsFetch(payload, options = {}) {
@@ -121388,7 +121924,7 @@ const _sfc_main$i = {
121388
121924
  };
121389
121925
  }
121390
121926
  };
121391
- const AIWriter = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["__scopeId", "data-v-d869be75"]]);
121927
+ const AIWriter = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["__scopeId", "data-v-a4bc3d14"]]);
121392
121928
  async function createZip(blobs, fileNames) {
121393
121929
  const zip = new JSZip();
121394
121930
  blobs.forEach((blob, index2) => {
@@ -124237,6 +124773,10 @@ const _SuperToolbar = class _SuperToolbar2 extends EventEmitter2 {
124237
124773
  this.config.selector = this.config.element;
124238
124774
  }
124239
124775
  this.toolbarContainer = this.findElementBySelector(this.config.selector);
124776
+ if (this.toolbarContainer) {
124777
+ const uiFontFamily = (this.config?.uiDisplayFallbackFont || "").toString().trim() || "Arial, Helvetica, sans-serif";
124778
+ this.toolbarContainer.style.setProperty("--sd-ui-font-family", uiFontFamily);
124779
+ }
124240
124780
  __privateMethod(this, _SuperToolbar_instances, initToolbarGroups_fn).call(this);
124241
124781
  __privateMethod(this, _SuperToolbar_instances, makeToolbarItems_fn).call(this, {
124242
124782
  superToolbar: this,