pptx-react-viewer 4.65.0 → 4.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +10 -0
  3. package/dist/{AiChatPanel-7U7IJRNY.mjs → AiChatPanel-E7CJSTW7.mjs} +1 -1
  4. package/dist/AiChatPanel-E7CJSTW7.mjs.br +0 -0
  5. package/dist/AiChatPanel-E7CJSTW7.mjs.gz +0 -0
  6. package/dist/{AiChatPanel-7AFFNYEN.js → AiChatPanel-PLQ3NBTK.js} +19 -19
  7. package/dist/AiChatPanel-PLQ3NBTK.js.br +0 -0
  8. package/dist/AiChatPanel-PLQ3NBTK.js.gz +0 -0
  9. package/dist/ai.js +2 -2
  10. package/dist/ai.js.br +0 -0
  11. package/dist/ai.js.gz +0 -0
  12. package/dist/ai.mjs +1 -1
  13. package/dist/ai.mjs.br +0 -0
  14. package/dist/ai.mjs.gz +0 -0
  15. package/dist/{chunk-G5JGUSBL.mjs → chunk-3LJ5QUU3.mjs} +271 -261
  16. package/dist/chunk-3LJ5QUU3.mjs.br +0 -0
  17. package/dist/chunk-3LJ5QUU3.mjs.gz +0 -0
  18. package/dist/{chunk-VGU5S37T.js → chunk-F5UOILTY.js} +466 -456
  19. package/dist/chunk-F5UOILTY.js.br +0 -0
  20. package/dist/chunk-F5UOILTY.js.gz +0 -0
  21. package/dist/{chunk-5ZW3GP6C.mjs → chunk-FBSPQYRE.mjs} +72 -738
  22. package/dist/chunk-FBSPQYRE.mjs.br +0 -0
  23. package/dist/chunk-FBSPQYRE.mjs.gz +0 -0
  24. package/dist/{chunk-WAIX4VJ2.mjs → chunk-JZE6BORE.mjs} +1 -1
  25. package/dist/chunk-JZE6BORE.mjs.br +0 -0
  26. package/dist/chunk-JZE6BORE.mjs.gz +0 -0
  27. package/dist/{chunk-VMX3IDQB.mjs → chunk-LRDW6EH7.mjs} +22 -11
  28. package/dist/chunk-LRDW6EH7.mjs.br +0 -0
  29. package/dist/chunk-LRDW6EH7.mjs.gz +0 -0
  30. package/dist/{chunk-PNDORR6S.js → chunk-LVEFHZ76.js} +1 -1
  31. package/dist/chunk-LVEFHZ76.js.br +0 -0
  32. package/dist/chunk-LVEFHZ76.js.gz +0 -0
  33. package/dist/{chunk-5DBKW7F3.js → chunk-P2COO2QO.js} +71 -736
  34. package/dist/chunk-P2COO2QO.js.br +0 -0
  35. package/dist/chunk-P2COO2QO.js.gz +0 -0
  36. package/dist/{chunk-LUKGXRHZ.js → chunk-ZLPMXC55.js} +578 -567
  37. package/dist/chunk-ZLPMXC55.js.br +0 -0
  38. package/dist/chunk-ZLPMXC55.js.gz +0 -0
  39. package/dist/i18n/de.cjs +3 -0
  40. package/dist/i18n/de.cjs.br +0 -0
  41. package/dist/i18n/de.cjs.gz +0 -0
  42. package/dist/i18n/de.mjs +3 -0
  43. package/dist/i18n/de.mjs.br +0 -0
  44. package/dist/i18n/de.mjs.gz +0 -0
  45. package/dist/i18n/es.cjs +3 -0
  46. package/dist/i18n/es.cjs.br +0 -0
  47. package/dist/i18n/es.cjs.gz +0 -0
  48. package/dist/i18n/es.mjs +3 -0
  49. package/dist/i18n/es.mjs.br +0 -0
  50. package/dist/i18n/es.mjs.gz +0 -0
  51. package/dist/i18n/fr.cjs +3 -0
  52. package/dist/i18n/fr.cjs.br +0 -0
  53. package/dist/i18n/fr.cjs.gz +0 -0
  54. package/dist/i18n/fr.mjs +3 -0
  55. package/dist/i18n/fr.mjs.br +0 -0
  56. package/dist/i18n/fr.mjs.gz +0 -0
  57. package/dist/i18n/zh-CN.cjs +3 -0
  58. package/dist/i18n/zh-CN.cjs.br +0 -0
  59. package/dist/i18n/zh-CN.cjs.gz +0 -0
  60. package/dist/i18n/zh-CN.mjs +3 -0
  61. package/dist/i18n/zh-CN.mjs.br +0 -0
  62. package/dist/i18n/zh-CN.mjs.gz +0 -0
  63. package/dist/index.d.ts +4 -1
  64. package/dist/index.js +27 -27
  65. package/dist/index.js.br +0 -0
  66. package/dist/index.js.gz +0 -0
  67. package/dist/index.mjs +4 -4
  68. package/dist/index.mjs.br +0 -0
  69. package/dist/index.mjs.gz +0 -0
  70. package/dist/internals.d.ts +9 -2
  71. package/dist/internals.js +81 -81
  72. package/dist/internals.js.br +0 -0
  73. package/dist/internals.js.gz +0 -0
  74. package/dist/internals.mjs +2 -2
  75. package/dist/internals.mjs.br +0 -0
  76. package/dist/internals.mjs.gz +0 -0
  77. package/dist/viewer/index.d.ts +4 -1
  78. package/dist/viewer/index.js +21 -21
  79. package/dist/viewer/index.js.br +0 -0
  80. package/dist/viewer/index.js.gz +0 -0
  81. package/dist/viewer/index.mjs +4 -4
  82. package/dist/viewer/index.mjs.br +0 -0
  83. package/dist/viewer/index.mjs.gz +0 -0
  84. package/package.json +4 -4
  85. package/dist/AiChatPanel-7AFFNYEN.js.br +0 -0
  86. package/dist/AiChatPanel-7AFFNYEN.js.gz +0 -0
  87. package/dist/AiChatPanel-7U7IJRNY.mjs.br +0 -0
  88. package/dist/AiChatPanel-7U7IJRNY.mjs.gz +0 -0
  89. package/dist/chunk-5DBKW7F3.js.br +0 -0
  90. package/dist/chunk-5DBKW7F3.js.gz +0 -0
  91. package/dist/chunk-5ZW3GP6C.mjs.br +0 -0
  92. package/dist/chunk-5ZW3GP6C.mjs.gz +0 -0
  93. package/dist/chunk-G5JGUSBL.mjs.br +0 -0
  94. package/dist/chunk-G5JGUSBL.mjs.gz +0 -0
  95. package/dist/chunk-LUKGXRHZ.js.br +0 -0
  96. package/dist/chunk-LUKGXRHZ.js.gz +0 -0
  97. package/dist/chunk-PNDORR6S.js.br +0 -0
  98. package/dist/chunk-PNDORR6S.js.gz +0 -0
  99. package/dist/chunk-VGU5S37T.js.br +0 -0
  100. package/dist/chunk-VGU5S37T.js.gz +0 -0
  101. package/dist/chunk-VMX3IDQB.mjs.br +0 -0
  102. package/dist/chunk-VMX3IDQB.mjs.gz +0 -0
  103. package/dist/chunk-WAIX4VJ2.mjs.br +0 -0
  104. package/dist/chunk-WAIX4VJ2.mjs.gz +0 -0
@@ -1,12 +1,12 @@
1
1
  import { translationsEn, keyToLabel } from 'ooxml-ui/pptx/i18n';
2
2
  import React8, { createContext, useContext, useState, useMemo, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
3
3
  import { useTranslation as useTranslation$1 } from 'react-i18next';
4
- import { VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle as getAnimationInitialStyle$1, cloneHistorySnapshot as cloneHistorySnapshot$1, SHAPE_PRESET_DEFS, getImageFitStyle, getImageFillCounterTransform, getComputedFillStyle, getCropShapeClipPath as getCropShapeClipPath$1, getImageTilingStyle as getImageTilingStyle$1, mediaPlaybackAttributes, getOnlineVideoEmbed, ONLINE_VIDEO_IFRAME_SANDBOX, ONLINE_VIDEO_IFRAME_ALLOW, buildTextBlockStyle, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle as buildTextBody3DSceneStyle$1, buildParagraphs, followingText, colorWithOpacity, normalizeHexColor, hexToRgbUnit, build3DExtrusionData as build3DExtrusionData$1, getFrameEffectStyle, getComputedEffectStyle, getComputedStrokeStyle, getAnimationColorBaseStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, screenBorderWidth, markerPath, normalizeStrokeDashType, getSvgStrokeDasharray, screenStrokeWidth, buildSvgGradientDef, isArrowedCustomPath, buildStrokeOutline, getPresetShapeVectorGeometry, isWedgeCalloutPresetShape, svgGradientFillRef, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, canDrillDown, computeSelectionRect, DEFAULT_FONT_FAMILY as DEFAULT_FONT_FAMILY$1, cellStyleToCss, TABLE_CELL_TEXT_DEFAULTS, applyTableCellFontWeight, rectToCells, isCellInRect, tableContainerCss, buildChartViewModel, resolveChartKind, chartPreserveAspectRatio, buildNotesPdfBytes, buildTiledSlidesPdfBytes, buildPreviewAnimation, measurePreviewGeometry, buildMotionPathPreview, mediaFallbackVisual, scheduleMediaTrimAndFade, registerCrossSlideAudio, shouldShowMediaFullscreenStopButton, withInlineListDecorationDefaults, segmentStyleToCss, resolveAutoFitFontScale, applyUnderlineVariant, nestedTextDecorationStyle, textRunColor, scaleFontSizeForAutoFit, resolveFontKerning, resolveScriptFontSet, hasDistinctScriptFonts, authoredLetterSpacingPx, eastAsianBreaksForRun, pieceLetterSpacing, resolveMetricTrackingPx, hollowTextFillStyle, splitsUnderlineIntoWords, stripUnderlineDecoration, buildTabContext, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects as apply3dEffects$1, buildSubpathPaints, computeColumnBoundaries, computeTableMergeCrossings, columnHandleSegments, rowHandleSegments, getTableCellBandStyle as getTableCellBandStyle$1, parseDrawingColor, parseDrawingColorOpacity, getCellDiagonalBorders as getCellDiagonalBorders$1, cellParagraphBlocks, resolveChartPalette, computeChartLegendLayout, resolveChartSvgDef, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, convertOmmlToMathMl, sanitizeMathMl, tableCellCss, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, buildRectPathGradient, screenBorder, cellRunStyle, buildRunTabLines, chartPartToAttrs, splitWordsForUnderline, splitRunForMetrics, splitEastAsianBreaks, splitRunByScriptFont } from 'ooxml-ui/pptx';
4
+ import { VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle as getAnimationInitialStyle$1, cloneHistorySnapshot as cloneHistorySnapshot$1, SHAPE_PRESET_DEFS, getImageFitStyle, getImageFillCounterTransform, getComputedFillStyle, getCropShapeClipPath as getCropShapeClipPath$1, getImageTilingStyle as getImageTilingStyle$1, mediaPlaybackAttributes, getOnlineVideoEmbed, ONLINE_VIDEO_IFRAME_SANDBOX, ONLINE_VIDEO_IFRAME_ALLOW, buildTextBlockStyle, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle as buildTextBody3DSceneStyle$1, buildParagraphs, followingText, colorWithOpacity, normalizeHexColor, hexToRgbUnit, build3DExtrusionData as build3DExtrusionData$1, isWedgeCalloutPresetShape, getFrameEffectStyle, getComputedEffectStyle, getComputedStrokeStyle, getAnimationColorBaseStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, screenBorderWidth, markerPath, normalizeStrokeDashType, getSvgStrokeDasharray, buildSvgGradientDef, isArrowedCustomPath, buildStrokeOutline, getPresetShapeVectorGeometry, screenStrokeWidth, svgGradientFillRef, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, connectorSnapTransform, connectorNeedsPath, connectorStrandScreenWidth, buildChartViewModel, resolveChartKind, chartPreserveAspectRatio, buildNotesPdfBytes, buildTiledSlidesPdfBytes, buildPreviewAnimation, measurePreviewGeometry, buildMotionPathPreview, mediaFallbackVisual, scheduleMediaTrimAndFade, registerCrossSlideAudio, shouldShowMediaFullscreenStopButton, withInlineListDecorationDefaults, segmentStyleToCss, resolveAutoFitFontScale, applyUnderlineVariant, nestedTextDecorationStyle, textRunColor, scaleFontSizeForAutoFit, resolveFontKerning, resolveScriptFontSet, hasDistinctScriptFonts, authoredLetterSpacingPx, eastAsianBreaksForRun, pieceLetterSpacing, resolveMetricTrackingPx, hollowTextFillStyle, splitsUnderlineIntoWords, stripUnderlineDecoration, buildTabContext, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects as apply3dEffects$1, buildSubpathPaints, canDrillDown, computeSelectionRect, DEFAULT_FONT_FAMILY as DEFAULT_FONT_FAMILY$1, isCellInRect, rectToCells, tableContainerCss, resolveChartPalette, computeChartLegendLayout, resolveChartSvgDef, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, attachMediaControlBar, convertOmmlToMathMl, sanitizeMathMl, dashStartPathData, computeColumnBoundaries, computeTableMergeCrossings, columnHandleSegments, rowHandleSegments, getCellDiagonalBorders as getCellDiagonalBorders$1, tableCellCss, cellParagraphBlocks, buildRunTabLines, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, cellRunStyle, chartPartToAttrs, splitWordsForUnderline, splitRunForMetrics, splitEastAsianBreaks, splitRunByScriptFont } from 'ooxml-ui/pptx';
5
5
  export { ACTION_BUTTON_PRESETS, DEFAULT_COLOR_CHANGE_TOLERANCE, INK_REPLAY_KEYFRAMES, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, SLIDE_TRANSITION_OPTIONS, TABLE_STYLE_PRESETS, applyColorChange, applyFormatToElement, applyReroutedConnectors, buildCacheKey, buildContentPartStrokes, buildCssGradientFromShapeStyle, buildInkGroupStrokes, buildSaveSlides, canvasToJpegData, clampCropValue, cloneSlide, cloneTemplateElementsBySlideId, colorWithOpacity, comparePresentation, computeHandoutLayout, copyFormatFromElement, formatCommentTimestamp, generateNoteLineCount, getAriaLabel, getAriaRole, getAriaRoleDescription, getCachedResult, getCompoundLineOffsets, getCompoundLineWidths, getContentPartReplayStyles, getElementLabel, getElementTransform, getElementTransformWithoutRotation, getImageEffectsFilter, getImageEffectsOpacity, getInkReplayStyles, getPatternSvg, getPrintableArea, getShapeAdjustmentHandleDescriptors, getSvgStrokeDasharray, getTextCompensationOrigin, getTextCompensationTransform, hasCopyableFormat, isEditableTextElement, isImageTiled, isPpactionUrl, isTemplateElementId, isUrlSafe, makeCloneId, mergeCells, normalizeHexColor, normalizeStrokeDashType, openNativeEyeDropper, parsePpactionUrl, partitionTemplateElements, rerouteConnectorsForMovedElements, safeOpenUrl, sanitizeGradientStops, setCachedResult, splitCell, stopAllPersistentAudio, substituteFieldText } from 'ooxml-ui/pptx';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import { LuTriangle, LuPlus, LuMoveRight, LuMinus, LuDiamond, LuDatabase, LuCircle, LuSquare } from 'react-icons/lu';
9
- import { hasShapeProperties, isImageLikeElement, hasTextProperties, getConnectorPathGeometry as getConnectorPathGeometry$1, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, getSubstituteFontFamily, parsePanoseString, customGeometryPathsToSvgSubpaths, xmlText, ooxmlGradientAngleToCssDegrees } from 'ooxml-core/pptx';
9
+ import { hasShapeProperties, isImageLikeElement, hasTextProperties, getConnectorPathGeometry as getConnectorPathGeometry$1, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, getSubstituteFontFamily, parsePanoseString, customGeometryPathsToSvgSubpaths } from 'ooxml-core/pptx';
10
10
  export { updateCellTextInRawXml, updateCellTextStyleInRawXml, updateMergeAttrsInRawXml } from 'ooxml-core/pptx';
11
11
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
12
 
@@ -56,7 +56,6 @@ function cloneHistorySnapshot(snapshot) {
56
56
  var DEFAULT_CANVAS_WIDTH = 1280;
57
57
  var DEFAULT_CANVAS_HEIGHT = 720;
58
58
  var MIN_ELEMENT_SIZE = 12;
59
- var EMU_PER_PX = 9525;
60
59
  var DEFAULT_BODY_INSET_TB_PX = 45720 / 9525;
61
60
  var DEFAULT_TEXT_COLOR = "#111827";
62
61
  var DEFAULT_FILL_COLOR = "#3b82f6";
@@ -326,12 +325,6 @@ function shouldRenderFallbackLabel(element, isTextElement) {
326
325
  }
327
326
  return element.type === "chart" || element.type === "smartArt" || element.type === "unknown";
328
327
  }
329
- function ensureArrayValue(value) {
330
- if (!value) {
331
- return [];
332
- }
333
- return Array.isArray(value) ? value : [value];
334
- }
335
328
  function buildTrimFragment(element) {
336
329
  const start = element.trimStartMs;
337
330
  if (start === void 0 || start <= 0) {
@@ -467,6 +460,31 @@ function AudioWithMetadata({
467
460
  }
468
461
  ) });
469
462
  }
463
+ function useMediaControlBar(mediaRef, enabled, selected) {
464
+ const { t } = useTranslation();
465
+ const barRef = useRef(null);
466
+ const selectedRef = useRef(selected);
467
+ selectedRef.current = selected;
468
+ useEffect(() => {
469
+ const media = mediaRef.current;
470
+ if (!enabled || !media) {
471
+ return void 0;
472
+ }
473
+ const host = media.closest("[data-pptx-element]") ?? media.parentElement ?? void 0;
474
+ if (!host) {
475
+ return void 0;
476
+ }
477
+ const bar = attachMediaControlBar(host, media, { t, selected: selectedRef.current });
478
+ barRef.current = bar;
479
+ return () => {
480
+ bar.dispose();
481
+ barRef.current = null;
482
+ };
483
+ }, [mediaRef, enabled, t]);
484
+ useEffect(() => {
485
+ barRef.current?.setSelected(selected);
486
+ }, [selected]);
487
+ }
470
488
  function PresentationMediaController({
471
489
  element,
472
490
  isPresentationMode,
@@ -474,11 +492,13 @@ function PresentationMediaController({
474
492
  resolvedDataUrl,
475
493
  isFullScreen,
476
494
  onPlayStateChange,
495
+ controlBar,
477
496
  children
478
497
  }) {
479
498
  const { t } = useTranslation();
480
499
  const mediaRef = useRef(null);
481
500
  const [isMediaPlaying, setIsMediaPlaying] = useState(false);
501
+ useMediaControlBar(mediaRef, controlBar !== void 0, controlBar?.selected === true);
482
502
  const trimStartSec = element.trimStartMs !== void 0 ? element.trimStartMs / 1e3 : 0;
483
503
  const hideWhenNotPlaying = isPresentationMode && element.hideWhenNotPlaying === true;
484
504
  const { volume: playbackVolume, playbackRate } = mediaPlaybackAttributes({
@@ -750,6 +770,7 @@ function renderMediaElement(element, mediaDataUrls, options) {
750
770
  resolvedDataUrl: dataUrl,
751
771
  isFullScreen,
752
772
  onPlayStateChange: options?.onPlayStateChange,
773
+ controlBar: options?.controlBar,
753
774
  children: ({ mediaRef, onPlay }) => /* @__PURE__ */ jsx(
754
775
  VideoWithMetadata,
755
776
  {
@@ -783,6 +804,7 @@ function renderMediaElement(element, mediaDataUrls, options) {
783
804
  resolvedDataUrl: dataUrl,
784
805
  isFullScreen: false,
785
806
  onPlayStateChange: options?.onPlayStateChange,
807
+ controlBar: options?.controlBar,
786
808
  children: ({ mediaRef, onPlay }) => /* @__PURE__ */ jsx(
787
809
  AudioWithMetadata,
788
810
  {
@@ -1391,6 +1413,9 @@ function renderParagraphRun(run, segment, ctx, keySuffix = "") {
1391
1413
  typeof run.style.fontSize === "string" ? run.style.fontSize : void 0
1392
1414
  );
1393
1415
  }
1416
+ if (run.text === "\n" && !run.hyperlink && !run.ruby && !findHighlights?.get(segmentIndex)) {
1417
+ return /* @__PURE__ */ jsx("br", { "data-seg-idx": segmentIndex }, key);
1418
+ }
1394
1419
  const segmentStyle = segment?.style ?? {};
1395
1420
  const textValue = run.text;
1396
1421
  const lines = textValue.split("\n");
@@ -1959,7 +1984,17 @@ function renderSvgGradientDefs(gradient) {
1959
1984
  return null;
1960
1985
  }
1961
1986
  if (gradient.kind === "rectPath") {
1962
- return /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("pattern", { id: gradient.id, patternUnits: "objectBoundingBox", width: 1, height: 1, children: /* @__PURE__ */ jsx("image", { href: gradient.href, x: 0, y: 0, width: 1, height: 1, preserveAspectRatio: "none" }) }) });
1987
+ return /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
1988
+ "pattern",
1989
+ {
1990
+ id: gradient.id,
1991
+ patternUnits: "objectBoundingBox",
1992
+ patternContentUnits: "objectBoundingBox",
1993
+ width: 1,
1994
+ height: 1,
1995
+ children: /* @__PURE__ */ jsx("image", { href: gradient.href, x: 0, y: 0, width: 1, height: 1, preserveAspectRatio: "none" })
1996
+ }
1997
+ ) });
1963
1998
  }
1964
1999
  const stops = gradient.stops.map((stop, index) => /* @__PURE__ */ jsx(
1965
2000
  "stop",
@@ -1993,7 +2028,7 @@ function strokeContext(shapeStyle, strokePaint, strokeWidth, dashArray) {
1993
2028
  strokePaint,
1994
2029
  strokeWidth,
1995
2030
  dashArray,
1996
- lineCap: svgLineCap(shapeStyle?.lineCap),
2031
+ lineCap: svgLineCap(shapeStyle?.lineCap, dashArray !== void 0),
1997
2032
  lineJoin,
1998
2033
  miterLimit,
1999
2034
  offsets: getCompoundLineOffsets(shapeStyle?.compoundLine, strokeWidth),
@@ -2001,10 +2036,11 @@ function strokeContext(shapeStyle, strokePaint, strokeWidth, dashArray) {
2001
2036
  };
2002
2037
  }
2003
2038
  function strokeStrands(d, keyBase, ctx) {
2039
+ const strokeD = ctx.dashArray === void 0 ? d : dashStartPathData(d);
2004
2040
  return ctx.offsets.map((offset, idx) => /* @__PURE__ */ jsx(
2005
2041
  "path",
2006
2042
  {
2007
- d,
2043
+ d: strokeD,
2008
2044
  fill: "none",
2009
2045
  stroke: ctx.strokePaint,
2010
2046
  strokeWidth: Math.max(ctx.widths[idx] ?? ctx.strokeWidth, 1),
@@ -2095,70 +2131,9 @@ function renderVectorShape(element, hasFill, fillColor, strokeWidth, strokeColor
2095
2131
  const dashArray = getSvgStrokeDasharray(
2096
2132
  dashType,
2097
2133
  Math.max(strokeWidth, 1),
2098
- element.shapeStyle?.customDashSegments
2134
+ element.shapeStyle?.customDashSegments,
2135
+ element.shapeStyle?.lineCap
2099
2136
  );
2100
- if (normalizedType === "can" || normalizedType === "cylinder") {
2101
- const width = Math.max(element.width, 1);
2102
- const height = Math.max(element.height, 1);
2103
- const rim = Math.max(Math.min(height * 0.16, 28), 6);
2104
- const stroke = Math.max(strokeWidth, 1);
2105
- const screenStroke = { strokeWidth: screenStrokeWidth(stroke) };
2106
- return /* @__PURE__ */ jsxs(
2107
- "svg",
2108
- {
2109
- viewBox: `0 0 ${width} ${height}`,
2110
- className: "w-full h-full pointer-events-none",
2111
- preserveAspectRatio: "none",
2112
- children: [
2113
- /* @__PURE__ */ jsx(
2114
- "ellipse",
2115
- {
2116
- cx: width / 2,
2117
- cy: rim / 2,
2118
- rx: width / 2,
2119
- ry: rim / 2,
2120
- fill: hasFill ? fillPaint : "none",
2121
- stroke: strokeWidth > 0 ? strokePaint : "none",
2122
- strokeWidth: stroke,
2123
- strokeDasharray: dashArray,
2124
- vectorEffect: "non-scaling-stroke",
2125
- style: screenStroke
2126
- }
2127
- ),
2128
- /* @__PURE__ */ jsx(
2129
- "rect",
2130
- {
2131
- x: 0,
2132
- y: rim / 2,
2133
- width,
2134
- height: Math.max(height - rim, 1),
2135
- fill: hasFill ? fillPaint : "none",
2136
- stroke: strokeWidth > 0 ? strokePaint : "none",
2137
- strokeWidth: stroke,
2138
- strokeDasharray: dashArray,
2139
- vectorEffect: "non-scaling-stroke",
2140
- style: screenStroke
2141
- }
2142
- ),
2143
- /* @__PURE__ */ jsx(
2144
- "ellipse",
2145
- {
2146
- cx: width / 2,
2147
- cy: height - rim / 2,
2148
- rx: width / 2,
2149
- ry: rim / 2,
2150
- fill: hasFill ? fillPaint : "none",
2151
- stroke: strokeWidth > 0 ? strokePaint : "none",
2152
- strokeWidth: stroke,
2153
- strokeDasharray: dashArray,
2154
- vectorEffect: "non-scaling-stroke",
2155
- style: screenStroke
2156
- }
2157
- )
2158
- ]
2159
- }
2160
- );
2161
- }
2162
2137
  if ((element.type === "shape" || element.type === "image" || element.type === "picture") && element.pathData && element.pathWidth && element.pathHeight && element.pathWidth > 0 && element.pathHeight > 0) {
2163
2138
  return renderCustomGeometryVector(
2164
2139
  element.pathData,
@@ -2177,7 +2152,10 @@ function renderVectorShape(element, hasFill, fillColor, strokeWidth, strokeColor
2177
2152
  // container's `background-image` is suppressed for custom geometry, so
2178
2153
  // without this the shape fell back to the parser's representative solid
2179
2154
  // and lost every fade (issue #132).
2180
- buildSvgGradientDef(element.shapeStyle, element.id)
2155
+ buildSvgGradientDef(element.shapeStyle, element.id, {
2156
+ width: element.width,
2157
+ height: element.height
2158
+ })
2181
2159
  );
2182
2160
  }
2183
2161
  if ((element.type === "image" || element.type === "picture") && strokeWidth > 0 && !buildStrokeOutline(element)) {
@@ -2333,10 +2311,16 @@ function renderVectorShape(element, hasFill, fillColor, strokeWidth, strokeColor
2333
2311
  const endArrowW = element.shapeStyle?.connectorEndArrowWidth;
2334
2312
  const endArrowL = element.shapeStyle?.connectorEndArrowLength;
2335
2313
  const compoundLine = element.shapeStyle?.compoundLine;
2336
- const connectorLineCap = svgLineCap(element.shapeStyle?.lineCap);
2314
+ const connectorLineCap = svgLineCap(element.shapeStyle?.lineCap, dashArray !== void 0);
2337
2315
  const hitTargetWidth = Math.max(strokeWidth * 3, 12);
2338
2316
  const offsets = getCompoundLineOffsets(compoundLine, strokeWidth);
2339
2317
  const widths = getCompoundLineWidths(compoundLine, strokeWidth);
2318
+ const snapTransform = connectorSnapTransform(
2319
+ element,
2320
+ !connectorNeedsPath(element.shapeType),
2321
+ offsets.length,
2322
+ strokeWidth
2323
+ );
2340
2324
  return /* @__PURE__ */ jsxs(
2341
2325
  "svg",
2342
2326
  {
@@ -2376,8 +2360,8 @@ function renderVectorShape(element, hasFill, fillColor, strokeWidth, strokeColor
2376
2360
  vectorEffect: "non-scaling-stroke",
2377
2361
  style: {
2378
2362
  pointerEvents: "none",
2379
- strokeWidth: screenBorderWidth(Math.max(widths[idx] ?? strokeWidth, 1)),
2380
- ...offset !== 0 ? { transform: `translate(0, ${offset}px)` } : {}
2363
+ strokeWidth: connectorStrandScreenWidth(widths, strokeWidth, idx),
2364
+ ...offset !== 0 ? { transform: `translate(0, ${offset}px)` } : snapTransform ? { transform: snapTransform } : {}
2381
2365
  }
2382
2366
  },
2383
2367
  idx
@@ -2388,466 +2372,8 @@ function renderVectorShape(element, hasFill, fillColor, strokeWidth, strokeColor
2388
2372
  }
2389
2373
  return null;
2390
2374
  }
2391
- function parseGradientFillCss(gradFill) {
2392
- if (!gradFill) {
2393
- return void 0;
2394
- }
2395
- const gsLstRaw = gradFill["a:gsLst"];
2396
- if (!gsLstRaw) {
2397
- return void 0;
2398
- }
2399
- const stops = ensureArrayValue(gsLstRaw["a:gs"]);
2400
- if (stops.length === 0) {
2401
- return void 0;
2402
- }
2403
- const rawStops = stops.map((gs) => {
2404
- const pos = Number.parseInt(String(gs["@_pos"] || "0"), 10) / 1e3;
2405
- const color = parseDrawingColor(gs) ?? "#888888";
2406
- const opacity = parseDrawingColorOpacity(gs);
2407
- return { position: pos, color, opacity };
2408
- }).sort((a, b) => a.position - b.position);
2409
- const stopStrings = rawStops.map((s) => `${colorWithOpacity(s.color, s.opacity)} ${s.position.toFixed(1)}%`).join(", ");
2410
- const lin = gradFill["a:lin"];
2411
- if (lin) {
2412
- const angRaw = Number.parseInt(String(lin["@_ang"] || "0"), 10);
2413
- const angleDeg = Math.round(ooxmlGradientAngleToCssDegrees(angRaw / 6e4));
2414
- return `linear-gradient(${angleDeg}deg, ${stopStrings})`;
2415
- }
2416
- const path = gradFill["a:path"];
2417
- if (path) {
2418
- const pathType = String(path["@_path"] || "circle");
2419
- const fillToRectXml = path["a:fillToRect"];
2420
- const fillToRect = fillToRectXml ? {
2421
- l: Number.parseInt(String(fillToRectXml["@_l"] || "0"), 10) / 1e5,
2422
- t: Number.parseInt(String(fillToRectXml["@_t"] || "0"), 10) / 1e5,
2423
- r: Number.parseInt(String(fillToRectXml["@_r"] || "0"), 10) / 1e5,
2424
- b: Number.parseInt(String(fillToRectXml["@_b"] || "0"), 10) / 1e5
2425
- } : void 0;
2426
- if (pathType === "rect") {
2427
- return buildRectPathGradient(rawStops, void 0, fillToRect);
2428
- }
2429
- let cx = 50;
2430
- let cy = 50;
2431
- if (fillToRect) {
2432
- const { l, t, r, b } = fillToRect;
2433
- cx = (l + (1 - r)) / 2 * 100;
2434
- cy = (t + (1 - b)) / 2 * 100;
2435
- }
2436
- const posX = `${Math.round(cx)}%`;
2437
- const posY = `${Math.round(cy)}%`;
2438
- if (pathType === "shape") {
2439
- return `radial-gradient(farthest-side at ${posX} ${posY}, ${stopStrings})`;
2440
- }
2441
- return `radial-gradient(circle at ${posX} ${posY}, ${stopStrings})`;
2442
- }
2443
- return `linear-gradient(180deg, ${stopStrings})`;
2444
- }
2445
- function parsePatternFillCss(pattFill) {
2446
- if (!pattFill) {
2447
- return void 0;
2448
- }
2449
- const fgColor = parseDrawingColor(pattFill["a:fgClr"]) ?? "#000000";
2450
- const bgColor = parseDrawingColor(pattFill["a:bgClr"]) ?? "#ffffff";
2451
- const preset = String(pattFill["@_prst"] || "ltDnDiag");
2452
- switch (preset) {
2453
- case "ltHorz":
2454
- case "horz":
2455
- case "narHorz":
2456
- case "dkHorz":
2457
- case "wdUpDiag":
2458
- return `repeating-linear-gradient(0deg, ${bgColor}, ${bgColor} 3px, ${fgColor} 3px, ${fgColor} 4px)`;
2459
- case "ltVert":
2460
- case "vert":
2461
- case "narVert":
2462
- case "dkVert":
2463
- case "wdDnDiag":
2464
- return `repeating-linear-gradient(90deg, ${bgColor}, ${bgColor} 3px, ${fgColor} 3px, ${fgColor} 4px)`;
2465
- case "ltDnDiag":
2466
- case "dnDiag":
2467
- case "dkDnDiag":
2468
- return `repeating-linear-gradient(135deg, ${bgColor}, ${bgColor} 3px, ${fgColor} 3px, ${fgColor} 4px)`;
2469
- case "ltUpDiag":
2470
- case "upDiag":
2471
- case "dkUpDiag":
2472
- return `repeating-linear-gradient(45deg, ${bgColor}, ${bgColor} 3px, ${fgColor} 3px, ${fgColor} 4px)`;
2473
- case "dashHorz":
2474
- case "dashVert":
2475
- case "dashDnDiag":
2476
- case "dashUpDiag":
2477
- return `repeating-linear-gradient(135deg, ${bgColor}, ${bgColor} 4px, ${fgColor} 4px, ${fgColor} 6px, ${bgColor} 6px, ${bgColor} 10px)`;
2478
- case "smCheck":
2479
- case "lgCheck":
2480
- return `repeating-conic-gradient(${fgColor} 0% 25%, ${bgColor} 0% 50%) 0 0 / 8px 8px`;
2481
- case "smGrid":
2482
- case "lgGrid":
2483
- return `repeating-linear-gradient(0deg, ${fgColor} 0px, ${fgColor} 1px, transparent 1px, transparent 6px), repeating-linear-gradient(90deg, ${fgColor} 0px, ${fgColor} 1px, transparent 1px, transparent 6px), ${bgColor}`;
2484
- case "dotGrid":
2485
- case "pct5":
2486
- case "pct10":
2487
- case "pct20":
2488
- case "pct25":
2489
- case "pct30":
2490
- case "pct40":
2491
- case "pct50":
2492
- case "pct60":
2493
- case "pct70":
2494
- case "pct75":
2495
- case "pct80":
2496
- case "pct90":
2497
- return `radial-gradient(${fgColor} 1px, ${bgColor} 1px) 0 0 / 4px 4px`;
2498
- case "smConfetti":
2499
- case "lgConfetti":
2500
- case "zigZag":
2501
- case "wave":
2502
- case "sphere":
2503
- case "divot":
2504
- case "shingle":
2505
- case "weave":
2506
- case "plaid":
2507
- case "trellis":
2508
- return `repeating-linear-gradient(45deg, ${bgColor}, ${bgColor} 2px, ${fgColor} 2px, ${fgColor} 3px)`;
2509
- case "solidDmnd":
2510
- case "openDmnd":
2511
- return `repeating-conic-gradient(${fgColor} 0% 25%, ${bgColor} 0% 50%) 0 0 / 10px 10px`;
2512
- default:
2513
- return `repeating-linear-gradient(135deg, ${bgColor}, ${bgColor} 3px, ${fgColor} 3px, ${fgColor} 4px)`;
2514
- }
2515
- }
2516
- function ooxmlDashToCss(dashVal) {
2517
- if (!dashVal) {
2518
- return "solid";
2519
- }
2520
- switch (dashVal) {
2521
- case "dot":
2522
- case "sysDot":
2523
- return "dotted";
2524
- case "dash":
2525
- case "sysDash":
2526
- case "lgDash":
2527
- return "dashed";
2528
- case "dashDot":
2529
- case "lgDashDot":
2530
- case "sysDashDot":
2531
- case "lgDashDotDot":
2532
- case "sysDashDotDot":
2533
- return "dashed";
2534
- case "solid":
2535
- return "solid";
2536
- default:
2537
- return "solid";
2538
- }
2539
- }
2540
- function parseCellBorders(cellProperties) {
2541
- if (!cellProperties) {
2542
- return {};
2543
- }
2544
- const borderStyle = {};
2545
- const edges = [
2546
- { xml: "a:lnL", prefix: "borderLeft" },
2547
- { xml: "a:lnR", prefix: "borderRight" },
2548
- { xml: "a:lnT", prefix: "borderTop" },
2549
- { xml: "a:lnB", prefix: "borderBottom" }
2550
- ];
2551
- for (const edge of edges) {
2552
- const ln = cellProperties[edge.xml];
2553
- if (!ln) {
2554
- continue;
2555
- }
2556
- const widthEmu = Number.parseInt(String(ln["@_w"] || "0"), 10);
2557
- const widthPx = Math.max(1, Math.round(widthEmu / 12700));
2558
- const prstDash = ln["a:prstDash"];
2559
- const dashVal = prstDash ? String(prstDash["@_val"] || "") : void 0;
2560
- const cssBorderStyle = ooxmlDashToCss(dashVal);
2561
- const color = parseDrawingColor(ln["a:solidFill"]);
2562
- if (color) {
2563
- const opacity = parseDrawingColorOpacity(ln["a:solidFill"]);
2564
- const key = `${edge.prefix}`;
2565
- borderStyle[key] = screenBorder(
2566
- widthPx,
2567
- cssBorderStyle,
2568
- colorWithOpacity(color, opacity)
2569
- );
2570
- }
2571
- }
2572
- return borderStyle;
2573
- }
2574
- function parseCellTextEffects(runProps) {
2575
- const effectLst = runProps?.["a:effectLst"];
2576
- if (!effectLst) {
2577
- return void 0;
2578
- }
2579
- const textShadowParts = [];
2580
- const outerShdw = effectLst["a:outerShdw"];
2581
- if (outerShdw) {
2582
- const shdwColor = parseDrawingColor(outerShdw);
2583
- if (shdwColor) {
2584
- const blurRad = Number.parseInt(String(outerShdw["@_blurRad"] || "0"), 10);
2585
- const blurPx = blurRad > 0 ? Math.round(blurRad / 12700) : 0;
2586
- const distVal = Number.parseInt(String(outerShdw["@_dist"] || "0"), 10);
2587
- const dirVal = Number.parseInt(String(outerShdw["@_dir"] || "0"), 10);
2588
- let offX = 0;
2589
- let offY = 0;
2590
- if (distVal > 0) {
2591
- const angleRad = dirVal / 6e4 * (Math.PI / 180);
2592
- offX = Math.round(distVal * Math.cos(angleRad) / 12700);
2593
- offY = Math.round(distVal * Math.sin(angleRad) / 12700);
2594
- }
2595
- textShadowParts.push(`${offX}px ${offY}px ${blurPx}px ${shdwColor}`);
2596
- }
2597
- }
2598
- const glow = effectLst["a:glow"];
2599
- if (glow) {
2600
- const glowColor = parseDrawingColor(glow);
2601
- if (glowColor) {
2602
- const glowRad = Number.parseInt(String(glow["@_rad"] || "0"), 10);
2603
- const glowPx = glowRad > 0 ? Math.round(glowRad / 12700) : 2;
2604
- textShadowParts.push(`0px 0px ${glowPx}px ${glowColor}`);
2605
- }
2606
- }
2607
- return textShadowParts.length > 0 ? textShadowParts.join(", ") : void 0;
2608
- }
2609
- function extractCellText(cellXml) {
2610
- if (!cellXml) {
2611
- return "";
2612
- }
2613
- const txBody = cellXml["a:txBody"];
2614
- const paragraphs = ensureArrayValue(txBody?.["a:p"]);
2615
- const paragraphTexts = [];
2616
- paragraphs.forEach((paragraph) => {
2617
- const textParts = [];
2618
- const runs = ensureArrayValue(paragraph["a:r"]);
2619
- runs.forEach((run) => {
2620
- textParts.push(xmlText(run["a:t"]) ?? "");
2621
- });
2622
- const fields = ensureArrayValue(paragraph["a:fld"]);
2623
- fields.forEach((field) => {
2624
- textParts.push(xmlText(field["a:t"]) ?? "");
2625
- });
2626
- paragraphTexts.push(textParts.join(""));
2627
- });
2628
- return paragraphTexts.join("\n");
2629
- }
2630
- function parseParagraphAlignment(value) {
2631
- const alignment = String(value || "").toLowerCase();
2632
- if (alignment === "ctr") {
2633
- return "center";
2634
- }
2635
- if (alignment === "r") {
2636
- return "right";
2637
- }
2638
- if (alignment === "just" || alignment === "justify") {
2639
- return "justify";
2640
- }
2641
- return "left";
2642
- }
2643
- function extractTableCellStyle(cellXml, fallbackStyle, schemeColorOverrides) {
2644
- const { color: _fallbackColor, ...fallbackWithoutColor } = fallbackStyle;
2645
- const cellStyle = { ...fallbackWithoutColor };
2646
- const txBody = cellXml["a:txBody"];
2647
- const paragraphs = ensureArrayValue(txBody?.["a:p"]);
2648
- const firstParagraph = paragraphs[0];
2649
- const paragraphProperties = firstParagraph?.["a:pPr"];
2650
- const runs = ensureArrayValue(firstParagraph?.["a:r"]);
2651
- const firstRun = runs[0];
2652
- const runProps = firstRun?.["a:rPr"] || paragraphProperties?.["a:defRPr"];
2653
- if (runProps?.["@_sz"]) {
2654
- const pointSize = Number.parseInt(String(runProps["@_sz"]), 10) / 100;
2655
- if (Number.isFinite(pointSize) && pointSize > 0) {
2656
- cellStyle.fontSize = pointSize * (96 / 72);
2657
- }
2658
- }
2659
- if (runProps?.["@_b"] !== void 0) {
2660
- cellStyle.fontWeight = runProps["@_b"] === "1" ? 700 : 400;
2661
- }
2662
- if (runProps?.["@_i"] !== void 0) {
2663
- cellStyle.fontStyle = runProps["@_i"] === "1" ? "italic" : "normal";
2664
- }
2665
- if (runProps?.["@_u"] !== void 0) {
2666
- cellStyle.textDecorationLine = runProps["@_u"] === "sng" ? "underline" : "none";
2667
- }
2668
- const runColor = parseDrawingColor(runProps?.["a:solidFill"], schemeColorOverrides) || parseDrawingColor(runProps?.["a:highlight"], schemeColorOverrides);
2669
- if (runColor) {
2670
- const opacity = parseDrawingColorOpacity(runProps?.["a:solidFill"]);
2671
- cellStyle.color = colorWithOpacity(runColor, opacity);
2672
- }
2673
- const fontFamily = runProps?.["a:latin"]?.["@_typeface"] || runProps?.["a:ea"]?.["@_typeface"] || runProps?.["a:cs"]?.["@_typeface"];
2674
- if (fontFamily) {
2675
- cellStyle.fontFamily = fontFamily;
2676
- }
2677
- if (paragraphProperties?.["@_algn"]) {
2678
- cellStyle.textAlign = parseParagraphAlignment(paragraphProperties["@_algn"]);
2679
- }
2680
- const cellProperties = cellXml["a:tcPr"];
2681
- const cellFill = parseDrawingColor(
2682
- cellProperties?.["a:solidFill"],
2683
- schemeColorOverrides
2684
- );
2685
- if (cellFill) {
2686
- const opacity = parseDrawingColorOpacity(
2687
- cellProperties?.["a:solidFill"]
2688
- );
2689
- cellStyle.backgroundColor = colorWithOpacity(cellFill, opacity);
2690
- } else {
2691
- const gradCss = parseGradientFillCss(cellProperties?.["a:gradFill"]);
2692
- if (gradCss) {
2693
- cellStyle.background = gradCss;
2694
- } else {
2695
- const pattCss = parsePatternFillCss(cellProperties?.["a:pattFill"]);
2696
- if (pattCss) {
2697
- cellStyle.background = pattCss;
2698
- }
2699
- }
2700
- }
2701
- const edgeBorders = parseCellBorders(cellProperties);
2702
- Object.assign(cellStyle, edgeBorders);
2703
- if (!cellStyle.borderLeftColor && !cellStyle.borderRightColor && !cellStyle.borderTopColor && !cellStyle.borderBottomColor) {
2704
- const borderColor = parseDrawingColor(
2705
- cellProperties?.["a:lnL"]?.["a:solidFill"],
2706
- schemeColorOverrides
2707
- ) || parseDrawingColor(
2708
- cellProperties?.["a:lnR"]?.["a:solidFill"],
2709
- schemeColorOverrides
2710
- ) || parseDrawingColor(
2711
- cellProperties?.["a:lnT"]?.["a:solidFill"],
2712
- schemeColorOverrides
2713
- ) || parseDrawingColor(
2714
- cellProperties?.["a:lnB"]?.["a:solidFill"],
2715
- schemeColorOverrides
2716
- );
2717
- if (borderColor) {
2718
- cellStyle.borderColor = borderColor;
2719
- }
2720
- }
2721
- if (cellProperties) {
2722
- const margin = (key) => Number.parseInt(String(cellProperties[key] ?? ""), 10) / EMU_PER_PX;
2723
- const marL = margin("@_marL");
2724
- const marR = margin("@_marR");
2725
- const marT = margin("@_marT");
2726
- const marB = margin("@_marB");
2727
- if (marL >= 0) {
2728
- cellStyle.paddingLeft = marL;
2729
- }
2730
- if (marR >= 0) {
2731
- cellStyle.paddingRight = marR;
2732
- }
2733
- if (marT >= 0) {
2734
- cellStyle.paddingTop = marT;
2735
- }
2736
- if (marB >= 0) {
2737
- cellStyle.paddingBottom = marB;
2738
- }
2739
- }
2740
- if (cellProperties?.["@_anchor"]) {
2741
- const anchor = String(cellProperties["@_anchor"]);
2742
- if (anchor === "ctr") {
2743
- cellStyle.verticalAlign = "middle";
2744
- } else if (anchor === "b") {
2745
- cellStyle.verticalAlign = "bottom";
2746
- } else {
2747
- cellStyle.verticalAlign = "top";
2748
- }
2749
- }
2750
- if (cellProperties?.["@_vert"]) {
2751
- const vert = String(cellProperties["@_vert"]);
2752
- switch (vert) {
2753
- case "vert":
2754
- case "eaVert":
2755
- case "wordArtVert":
2756
- case "wordArtVertRtl":
2757
- cellStyle.writingMode = "vertical-rl";
2758
- break;
2759
- case "vert270":
2760
- case "mongolianVert":
2761
- cellStyle.writingMode = "vertical-lr";
2762
- break;
2763
- }
2764
- if (vert === "wordArtVert") {
2765
- cellStyle.textOrientation = "upright";
2766
- } else if (cellStyle.writingMode) {
2767
- cellStyle.textOrientation = "mixed";
2768
- }
2769
- if (vert === "wordArtVertRtl") {
2770
- cellStyle.direction = "rtl";
2771
- }
2772
- }
2773
- const textShadow = parseCellTextEffects(runProps);
2774
- if (textShadow) {
2775
- cellStyle.textShadow = textShadow;
2776
- }
2777
- return cellStyle;
2778
- }
2779
- function getTableCellBandStyle(element, rowIndex, cellIndex, rowCount, columnCount, styleCtx) {
2780
- if (element.type !== "table") {
2781
- return void 0;
2782
- }
2783
- return getTableCellBandStyle$1(element.tableData, rowIndex, cellIndex, rowCount, columnCount, {
2784
- tableStyleMap: styleCtx?.tableStyleMap,
2785
- colorScheme: styleCtx?.theme?.colorScheme,
2786
- fontScheme: styleCtx?.theme?.fontScheme,
2787
- formatScheme: styleCtx?.theme?.formatScheme
2788
- });
2789
- }
2790
-
2791
- // src/viewer/utils/table-data-parse.tsx
2792
- function getGraphicDataFromElement(element) {
2793
- return element.rawXml?.["a:graphic"]?.["a:graphicData"];
2794
- }
2795
- function getTableXmlFromElement(element) {
2796
- return getGraphicDataFromElement(element)?.["a:tbl"];
2797
- }
2798
- function parseTableElementData(element, fallbackTextStyle) {
2799
- const table = getTableXmlFromElement(element);
2800
- if (!table) {
2801
- return null;
2802
- }
2803
- const rows = ensureArrayValue(table["a:tr"]);
2804
- if (rows.length === 0) {
2805
- return null;
2806
- }
2807
- const tableGrid = table["a:tblGrid"];
2808
- const gridColumns = ensureArrayValue(
2809
- tableGrid?.["a:gridCol"]
2810
- );
2811
- const columnWidths = gridColumns.map((column) => {
2812
- const width = Number.parseInt(String(column?.["@_w"] || ""), 10);
2813
- return Number.isFinite(width) && width > 0 ? width : 0;
2814
- });
2815
- const totalColumnWidth = columnWidths.reduce((sum, width) => sum + width, 0);
2816
- let columnPercentages = totalColumnWidth > 0 ? columnWidths.map((width) => width / totalColumnWidth * 100) : [];
2817
- const modelWidths = element.type === "table" ? element.tableData?.columnWidths : void 0;
2818
- if (modelWidths?.length && modelWidths.length === gridColumns.length && modelWidths.every((width) => Number.isFinite(width) && width >= 0) && Math.abs(modelWidths.reduce((sum, width) => sum + width, 0) - 1) <= Number.EPSILON * modelWidths.length * 4) {
2819
- columnPercentages = modelWidths.map((width) => width * 100);
2820
- }
2821
- const cells = [];
2822
- rows.forEach((row, rowIndex) => {
2823
- const rowCells = ensureArrayValue(row["a:tc"]);
2824
- rowCells.forEach((cell, columnIndex) => {
2825
- cells.push({
2826
- rowIndex,
2827
- columnIndex,
2828
- text: extractCellText(cell),
2829
- style: extractTableCellStyle(cell, fallbackTextStyle),
2830
- rawCell: cell
2831
- });
2832
- });
2833
- });
2834
- const columnCount = Math.max(
2835
- columnPercentages.length,
2836
- rows.reduce((maxCount, row) => {
2837
- const rowCells = ensureArrayValue(row["a:tc"]);
2838
- return Math.max(maxCount, rowCells.length);
2839
- }, 0)
2840
- );
2841
- return {
2842
- rowCount: rows.length,
2843
- columnCount,
2844
- rows,
2845
- columnPercentages,
2846
- cells
2847
- };
2848
- }
2849
- function renderTableCellContent(cell, fallbackText, cellCss) {
2850
- const blocks = cell ? cellParagraphBlocks(cell) : void 0;
2375
+ function renderTableCellContent(cell, fallbackText, cellCss, defaultFontPt) {
2376
+ const blocks = cell ? cellParagraphBlocks(cell, { cellCss, defaultFontPt }) : void 0;
2851
2377
  if (blocks) {
2852
2378
  return blocks.map((block, index) => /* @__PURE__ */ jsx("div", { style: { display: "block", ...block.css }, children: block.runs.map((run, runIndex) => renderRun(run, runIndex, cellCss)) }, `p-${index}`));
2853
2379
  }
@@ -3308,7 +2834,8 @@ function renderTableFromTableData(element, textStyle, options) {
3308
2834
  ) : renderTableCellContent(
3309
2835
  cell,
3310
2836
  cell.text || "\xA0",
3311
- cellCss(cell, rowIndex, cellIndex)
2837
+ cellCss(cell, rowIndex, cellIndex),
2838
+ tableData.defaultCellFontSize
3312
2839
  )
3313
2840
  ]
3314
2841
  },
@@ -3327,204 +2854,11 @@ function renderTableFromTableData(element, textStyle, options) {
3327
2854
  );
3328
2855
  }
3329
2856
  function renderTableElement(element, textStyle, options) {
3330
- const parsedTable = parseTableElementData(element, textStyle);
3331
- if (!parsedTable) {
3332
- const tableEl2 = element;
3333
- if (tableEl2.tableData && tableEl2.tableData.rows.length > 0) {
3334
- return renderTableFromTableData(tableEl2, textStyle, options);
3335
- }
3336
- return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.table.title"] });
3337
- }
3338
- const selectedCell = options?.selectedCell || null;
3339
- const isEditable = Boolean(options?.editable) && canDrillDown(element);
3340
- const hasCellSelectionHandler = typeof options?.onSelectCell === "function";
3341
2857
  const tableEl = element;
3342
- const xmlSelectionRect = (() => {
3343
- if (!selectedCell?.selectedCells || selectedCell.selectedCells.length < 2) {
3344
- return void 0;
3345
- }
3346
- if (!tableEl.tableData) {
3347
- return void 0;
3348
- }
3349
- const first = selectedCell.selectedCells[0];
3350
- const last = selectedCell.selectedCells[selectedCell.selectedCells.length - 1];
3351
- return computeSelectionRect(first.row, first.col, last.row, last.col, tableEl.tableData);
3352
- })();
3353
- const schemeOverrides = options?.styleCtx?.theme?.colorScheme ? options.styleCtx.theme.colorScheme : void 0;
3354
- return /* @__PURE__ */ jsx(
3355
- TableResizeOverlay,
3356
- {
3357
- columnWidths: parsedTable.columnPercentages.map((p) => p / 100),
3358
- rows: tableEl.tableData?.rows,
3359
- editable: isEditable,
3360
- onResizeColumns: options?.onResizeColumns,
3361
- onResizeRow: options?.onResizeRow,
3362
- children: /* @__PURE__ */ jsx(
3363
- "div",
3364
- {
3365
- className: cn(
3366
- "w-full h-full overflow-hidden",
3367
- isEditable && hasCellSelectionHandler ? "pointer-events-auto" : "pointer-events-none"
3368
- ),
3369
- children: /* @__PURE__ */ jsxs(
3370
- "table",
3371
- {
3372
- className: "w-full h-full border-collapse table-fixed",
3373
- style: {
3374
- fontFamily: DEFAULT_FONT_FAMILY$1,
3375
- // `a:tblPr@rtl` mirrors the column order for RTL decks.
3376
- ...tableContainerCss(tableEl.tableData)
3377
- },
3378
- children: [
3379
- parsedTable.columnPercentages.length > 0 ? /* @__PURE__ */ jsx("colgroup", { children: parsedTable.columnPercentages.map((percentage, columnIndex) => /* @__PURE__ */ jsx(
3380
- "col",
3381
- {
3382
- style: { width: `${percentage.toFixed(2)}%` }
3383
- },
3384
- `${element.id}-col-${columnIndex}`
3385
- )) }) : null,
3386
- /* @__PURE__ */ jsx("tbody", { children: parsedTable.rows.map((row, rowIndex) => {
3387
- const cells = ensureArrayValue(row["a:tc"]);
3388
- const rowHeightRaw = Number.parseInt(String(row["@_h"] || ""), 10);
3389
- const rowHeight = Number.isFinite(rowHeightRaw) && rowHeightRaw > 0 ? Math.max(16, rowHeightRaw / EMU_PER_PX) : void 0;
3390
- return /* @__PURE__ */ jsx(
3391
- "tr",
3392
- {
3393
- style: rowHeight ? { height: rowHeight } : void 0,
3394
- children: cells.map((cell, cellIndex) => {
3395
- const isHMerged = cell["@_hMerge"] === "1";
3396
- const isVMerged = cell["@_vMerge"] === "1";
3397
- if (isHMerged || isVMerged) {
3398
- return null;
3399
- }
3400
- const gridSpanRaw = Number.parseInt(String(cell["@_gridSpan"] || ""), 10);
3401
- const colSpan = Number.isFinite(gridSpanRaw) && gridSpanRaw > 1 ? gridSpanRaw : void 0;
3402
- const rowSpanRaw = Number.parseInt(String(cell["@_rowSpan"] || ""), 10);
3403
- const rSpan = Number.isFinite(rowSpanRaw) && rowSpanRaw > 1 ? rowSpanRaw : void 0;
3404
- const bandStyle = getTableCellBandStyle(
3405
- element,
3406
- rowIndex,
3407
- cellIndex,
3408
- parsedTable.rowCount,
3409
- parsedTable.columnCount,
3410
- options?.styleCtx
3411
- );
3412
- const xmlCellStyle = extractTableCellStyle(cell, textStyle, schemeOverrides);
3413
- const tdCellOverride = tableEl.tableData?.rows[rowIndex]?.cells[cellIndex]?.style;
3414
- const diag = getCellDiagonalBorders(
3415
- tdCellOverride,
3416
- tableEl.tableData,
3417
- {
3418
- rowIndex,
3419
- cellIndex,
3420
- rowCount: parsedTable.rowCount,
3421
- columnCount: parsedTable.columnCount
3422
- },
3423
- options?.styleCtx
3424
- );
3425
- const mergedStyle = {
3426
- // Lowest-priority fallback: `xmlCellStyle` never carries a
3427
- // `color` of its own (see `extractTableCellStyle`), so this
3428
- // is the only source when neither the table style band nor
3429
- // an explicit run/cell colour applies.
3430
- color: textStyle.color,
3431
- // PowerPoint's line spacing and default margins, as
3432
- // `tableCellCss` gives the structured-model path.
3433
- ...TABLE_CELL_TEXT_DEFAULTS,
3434
- ...bandStyle,
3435
- ...xmlCellStyle,
3436
- ...tdCellOverride ? cellStyleToCss(tdCellOverride) : void 0,
3437
- ...diag ? { position: "relative" } : void 0
3438
- };
3439
- applyTableCellFontWeight(mergedStyle);
3440
- return /* @__PURE__ */ jsxs(
3441
- "td",
3442
- {
3443
- className: cn(
3444
- "px-1 py-0.5 align-top",
3445
- // No border of its own: a side the deck gives no border renders
3446
- // with none, as PowerPoint does. Editing keeps a faint grid.
3447
- isEditable && hasCellSelectionHandler ? "border border-blue-200/70 cursor-cell" : null,
3448
- selectedCell?.rowIndex === rowIndex && selectedCell?.columnIndex === cellIndex ? "ring-1 ring-inset ring-blue-500" : null,
3449
- isCellInRect(rowIndex, cellIndex, xmlSelectionRect) && !(selectedCell?.rowIndex === rowIndex && selectedCell?.columnIndex === cellIndex) ? "bg-blue-500/15 ring-1 ring-inset ring-blue-400/50" : null
3450
- ),
3451
- colSpan,
3452
- rowSpan: rSpan,
3453
- style: mergedStyle,
3454
- onClick: (event) => {
3455
- if (!isEditable || !hasCellSelectionHandler) {
3456
- return;
3457
- }
3458
- event.stopPropagation();
3459
- if (event.shiftKey && selectedCell && tableEl.tableData) {
3460
- const rect = computeSelectionRect(
3461
- selectedCell.rowIndex,
3462
- selectedCell.columnIndex,
3463
- rowIndex,
3464
- cellIndex,
3465
- tableEl.tableData
3466
- );
3467
- options?.onSelectCell?.({
3468
- rowIndex: selectedCell.rowIndex,
3469
- columnIndex: selectedCell.columnIndex,
3470
- selectedCells: rectToCells(rect)
3471
- });
3472
- } else {
3473
- options?.onSelectCell?.({
3474
- rowIndex,
3475
- columnIndex: cellIndex
3476
- });
3477
- }
3478
- },
3479
- onDoubleClick: (event) => {
3480
- if (!isEditable || !hasCellSelectionHandler) {
3481
- return;
3482
- }
3483
- event.stopPropagation();
3484
- options?.onSelectCell?.({
3485
- rowIndex,
3486
- columnIndex: cellIndex,
3487
- isEditing: true
3488
- });
3489
- },
3490
- children: [
3491
- diag ? /* @__PURE__ */ jsx(TableCellDiagonalBorders, { diag }) : null,
3492
- selectedCell?.rowIndex === rowIndex && selectedCell?.columnIndex === cellIndex && selectedCell?.isEditing ? /* @__PURE__ */ jsx(
3493
- TableCellInput,
3494
- {
3495
- initialText: extractCellText(cell) ?? "",
3496
- style: mergedStyle,
3497
- onCommit: (text) => {
3498
- options?.onCommitCellEdit?.(rowIndex, cellIndex, text);
3499
- },
3500
- onCancel: () => {
3501
- options?.onSelectCell?.({
3502
- rowIndex,
3503
- columnIndex: cellIndex
3504
- });
3505
- }
3506
- }
3507
- ) : renderTableCellContent(
3508
- tableEl.tableData?.rows[rowIndex]?.cells[cellIndex],
3509
- extractCellText(cell) || "\xA0",
3510
- mergedStyle
3511
- )
3512
- ]
3513
- },
3514
- `${element.id}-cell-${rowIndex}-${cellIndex}`
3515
- );
3516
- })
3517
- },
3518
- `${element.id}-row-${rowIndex}`
3519
- );
3520
- }) })
3521
- ]
3522
- }
3523
- )
3524
- }
3525
- )
3526
- }
3527
- );
2858
+ if (tableEl.tableData && tableEl.tableData.rows.length > 0) {
2859
+ return renderTableFromTableData(tableEl, textStyle, options);
2860
+ }
2861
+ return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.table.title"] });
3528
2862
  }
3529
2863
  function renderGradientStops(stops) {
3530
2864
  return stops.map((stop, i) => /* @__PURE__ */ jsx("stop", { offset: stop.offset, stopColor: stop.color, stopOpacity: stop.opacity }, i));
@@ -3963,4 +3297,4 @@ function stopPreviewAnimation() {
3963
3297
  activePreview = null;
3964
3298
  }
3965
3299
 
3966
- export { ANIMATION_PRESET_OPTIONS, ARROW_SIZE_OPTIONS, CONNECTOR_ARROW_OPTIONS, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_SECTION_GROUP_ID, DEFAULT_STROKE_COLOR, DEFAULT_TABLE_COLUMNS, DEFAULT_TABLE_ROWS, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, GRID_SIZE, HYPERLINK_COLOR, MIN_ELEMENT_SIZE, PptxI18nContext, SHAPE_PRESETS, SHORTCUT_REFERENCE_ITEMS, SLIDE_NAV_THUMBNAIL_WIDTH, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, ViewerI18nContext, ViewerLocaleControlsContext, ZOOM_TO_SELECTION_PADDING, build3DExtrusionData, buildLineGlowFilter, buildLineShadowCss, buildNotesPdf, buildPdfFromTiledImageData, buildReactChartViewModel, buildTextBody3DSceneStyle, cloneHistorySnapshot, cn, getAnimationInitialStyle, getConnectorPathGeometry, getCropShapeClipPath, getDuotoneColors, getImageRenderStyle, getImageSurfaceMaskStyle, getImageSurfaceStyle, getImageTilingStyle, getShapeVisualStyle, getTextLayoutStyle, getTextStyleForElement, getTextWarpStyle, hasDagDuotoneEffect, isConnectorOrLineElement, renderChartElement, renderConnectorMarker, renderDagDuotoneSvgFilter, renderMediaElement, renderTableElement, renderTextSegments, renderVectorShape, shouldRenderFallbackLabel, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, useHostI18next, useTranslation };
3300
+ export { ANIMATION_PRESET_OPTIONS, ARROW_SIZE_OPTIONS, CONNECTOR_ARROW_OPTIONS, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_SECTION_GROUP_ID, DEFAULT_STROKE_COLOR, DEFAULT_TABLE_COLUMNS, DEFAULT_TABLE_ROWS, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, GRID_SIZE, MIN_ELEMENT_SIZE, PptxI18nContext, SHAPE_PRESETS, SHORTCUT_REFERENCE_ITEMS, SLIDE_NAV_THUMBNAIL_WIDTH, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, ViewerI18nContext, ViewerLocaleControlsContext, ZOOM_TO_SELECTION_PADDING, build3DExtrusionData, buildLineGlowFilter, buildLineShadowCss, buildNotesPdf, buildPdfFromTiledImageData, buildReactChartViewModel, buildTextBody3DSceneStyle, cloneHistorySnapshot, cn, getAnimationInitialStyle, getConnectorPathGeometry, getCropShapeClipPath, getDuotoneColors, getImageRenderStyle, getImageSurfaceMaskStyle, getImageSurfaceStyle, getImageTilingStyle, getShapeVisualStyle, getTextLayoutStyle, getTextStyleForElement, getTextWarpStyle, hasDagDuotoneEffect, isConnectorOrLineElement, renderChartElement, renderConnectorMarker, renderDagDuotoneSvgFilter, renderMediaElement, renderTableElement, renderTextSegments, renderVectorShape, rendersCustomVectorPath, rendersWedgeCalloutVector, shouldRenderFallbackLabel, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, useHostI18next, useTranslation };