pptx-react-viewer 2.22.0 → 3.0.1

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 (107) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/{AiChatPanel-KDHDYBMP.mjs → AiChatPanel-DMBQPAGB.mjs} +3 -3
  3. package/dist/AiChatPanel-DMBQPAGB.mjs.br +0 -0
  4. package/dist/AiChatPanel-DMBQPAGB.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-WVRT4OLF.js → AiChatPanel-NLIUZ5RI.js} +23 -23
  6. package/dist/AiChatPanel-NLIUZ5RI.js.br +0 -0
  7. package/dist/AiChatPanel-NLIUZ5RI.js.gz +0 -0
  8. package/dist/{Model3DScene-COI2CG35.js → Model3DScene-JNZN42TU.js} +2 -2
  9. package/dist/Model3DScene-JNZN42TU.js.br +0 -0
  10. package/dist/Model3DScene-JNZN42TU.js.gz +0 -0
  11. package/dist/{Model3DScene-I5SQKIZC.mjs → Model3DScene-ZO6U7YVU.mjs} +1 -1
  12. package/dist/Model3DScene-ZO6U7YVU.mjs.br +0 -0
  13. package/dist/Model3DScene-ZO6U7YVU.mjs.gz +0 -0
  14. package/dist/{SurfaceChart3DScene-6LTF5QPW.mjs → SurfaceChart3DScene-P6CVRWDQ.mjs} +1 -1
  15. package/dist/SurfaceChart3DScene-P6CVRWDQ.mjs.br +0 -0
  16. package/dist/SurfaceChart3DScene-P6CVRWDQ.mjs.gz +0 -0
  17. package/dist/{SurfaceChart3DScene-2N4TPYPU.js → SurfaceChart3DScene-PGD4ZCLI.js} +2 -2
  18. package/dist/SurfaceChart3DScene-PGD4ZCLI.js.br +0 -0
  19. package/dist/SurfaceChart3DScene-PGD4ZCLI.js.gz +0 -0
  20. package/dist/{chunk-YNHWNFE3.js → chunk-3MW6F3K7.js} +451 -399
  21. package/dist/chunk-3MW6F3K7.js.br +0 -0
  22. package/dist/chunk-3MW6F3K7.js.gz +0 -0
  23. package/dist/{chunk-KK6DOUES.js → chunk-54SDLPJY.js} +1275 -1248
  24. package/dist/chunk-54SDLPJY.js.br +0 -0
  25. package/dist/chunk-54SDLPJY.js.gz +0 -0
  26. package/dist/{chunk-TWU72BY4.mjs → chunk-BGAJLL4N.mjs} +70 -18
  27. package/dist/chunk-BGAJLL4N.mjs.br +0 -0
  28. package/dist/chunk-BGAJLL4N.mjs.gz +0 -0
  29. package/dist/{chunk-RJFKXPMU.mjs → chunk-OB4PKKIN.mjs} +1 -1
  30. package/dist/chunk-OB4PKKIN.mjs.br +0 -0
  31. package/dist/chunk-OB4PKKIN.mjs.gz +0 -0
  32. package/dist/{chunk-57TM4MV4.mjs → chunk-OXPD2UYI.mjs} +13085 -6709
  33. package/dist/chunk-OXPD2UYI.mjs.br +0 -0
  34. package/dist/chunk-OXPD2UYI.mjs.gz +0 -0
  35. package/dist/{chunk-7BZYDUNM.mjs → chunk-S6PFSR7I.mjs} +108 -255
  36. package/dist/chunk-S6PFSR7I.mjs.br +0 -0
  37. package/dist/chunk-S6PFSR7I.mjs.gz +0 -0
  38. package/dist/{chunk-34UAGEJM.js → chunk-SDOQKSKI.js} +13103 -6715
  39. package/dist/chunk-SDOQKSKI.js.br +0 -0
  40. package/dist/chunk-SDOQKSKI.js.gz +0 -0
  41. package/dist/{chunk-XIBTR7KJ.mjs → chunk-VGHEHM66.mjs} +254 -227
  42. package/dist/chunk-VGHEHM66.mjs.br +0 -0
  43. package/dist/chunk-VGHEHM66.mjs.gz +0 -0
  44. package/dist/{chunk-POP5IWYB.js → chunk-WFMSDYVQ.js} +3 -3
  45. package/dist/chunk-WFMSDYVQ.js.br +0 -0
  46. package/dist/chunk-WFMSDYVQ.js.gz +0 -0
  47. package/dist/{chunk-K7TFZ5MW.js → chunk-XMLPTDPM.js} +248 -396
  48. package/dist/chunk-XMLPTDPM.js.br +0 -0
  49. package/dist/chunk-XMLPTDPM.js.gz +0 -0
  50. package/dist/index.d.ts +475 -19
  51. package/dist/index.js +45 -45
  52. package/dist/index.js.br +0 -0
  53. package/dist/index.js.gz +0 -0
  54. package/dist/index.mjs +5 -5
  55. package/dist/index.mjs.br +0 -0
  56. package/dist/index.mjs.gz +0 -0
  57. package/dist/internals.d.ts +492 -21
  58. package/dist/internals.d.ts.map +1 -1
  59. package/dist/internals.js +78 -78
  60. package/dist/internals.js.br +0 -0
  61. package/dist/internals.js.gz +0 -0
  62. package/dist/internals.mjs +3 -3
  63. package/dist/internals.mjs.br +0 -0
  64. package/dist/internals.mjs.gz +0 -0
  65. package/dist/pptx-viewer.css +1 -1
  66. package/dist/pptx-viewer.css.br +0 -0
  67. package/dist/pptx-viewer.css.gz +0 -0
  68. package/dist/viewer/index.d.ts +472 -17
  69. package/dist/viewer/index.js +26 -26
  70. package/dist/viewer/index.js.br +0 -0
  71. package/dist/viewer/index.js.gz +0 -0
  72. package/dist/viewer/index.mjs +5 -5
  73. package/dist/viewer/index.mjs.br +0 -0
  74. package/dist/viewer/index.mjs.gz +0 -0
  75. package/package.json +2 -2
  76. package/dist/AiChatPanel-KDHDYBMP.mjs.br +0 -0
  77. package/dist/AiChatPanel-KDHDYBMP.mjs.gz +0 -0
  78. package/dist/AiChatPanel-WVRT4OLF.js.br +0 -0
  79. package/dist/AiChatPanel-WVRT4OLF.js.gz +0 -0
  80. package/dist/Model3DScene-COI2CG35.js.br +0 -0
  81. package/dist/Model3DScene-COI2CG35.js.gz +0 -0
  82. package/dist/Model3DScene-I5SQKIZC.mjs.br +0 -0
  83. package/dist/Model3DScene-I5SQKIZC.mjs.gz +0 -0
  84. package/dist/SurfaceChart3DScene-2N4TPYPU.js.br +0 -0
  85. package/dist/SurfaceChart3DScene-2N4TPYPU.js.gz +0 -0
  86. package/dist/SurfaceChart3DScene-6LTF5QPW.mjs.br +0 -0
  87. package/dist/SurfaceChart3DScene-6LTF5QPW.mjs.gz +0 -0
  88. package/dist/chunk-34UAGEJM.js.br +0 -0
  89. package/dist/chunk-34UAGEJM.js.gz +0 -0
  90. package/dist/chunk-57TM4MV4.mjs.br +0 -0
  91. package/dist/chunk-57TM4MV4.mjs.gz +0 -0
  92. package/dist/chunk-7BZYDUNM.mjs.br +0 -0
  93. package/dist/chunk-7BZYDUNM.mjs.gz +0 -0
  94. package/dist/chunk-K7TFZ5MW.js.br +0 -0
  95. package/dist/chunk-K7TFZ5MW.js.gz +0 -0
  96. package/dist/chunk-KK6DOUES.js.br +0 -0
  97. package/dist/chunk-KK6DOUES.js.gz +0 -0
  98. package/dist/chunk-POP5IWYB.js.br +0 -0
  99. package/dist/chunk-POP5IWYB.js.gz +0 -0
  100. package/dist/chunk-RJFKXPMU.mjs.br +0 -0
  101. package/dist/chunk-RJFKXPMU.mjs.gz +0 -0
  102. package/dist/chunk-TWU72BY4.mjs.br +0 -0
  103. package/dist/chunk-TWU72BY4.mjs.gz +0 -0
  104. package/dist/chunk-XIBTR7KJ.mjs.br +0 -0
  105. package/dist/chunk-XIBTR7KJ.mjs.gz +0 -0
  106. package/dist/chunk-YNHWNFE3.js.br +0 -0
  107. package/dist/chunk-YNHWNFE3.js.gz +0 -0
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  import { translationsEn } from './chunk-L5MNLIQF.mjs';
2
- import { SHAPE_PRESET_DEFS, VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle, cloneHistorySnapshot, hasShapeProperties, getImageFitStyle, isImageLikeElement, getImageTilingStyle, runMediaCommand, findMediaElementByElementId, mediaPlaybackAttributes, buildTextBlockStyle, hasTextProperties, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle, buildParagraphs, colorWithOpacity, normalizeHexColor, build3DExtrusionData, getComputedFillStyle, getComputedEffectStyle, getComputedStrokeStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, normalizeStrokeDashType, getSvgStrokeDasharray, buildSvgGradientDef, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, computeSelectionRect, DEFAULT_FONT_FAMILY, cellStyleToCss, rectToCells, isCellInRect, tableContainerCss, buildChartViewModel, resolveChartKind, chartPreserveAspectRatio, buildNotesPdfBytes, buildSlidesPdfBytes, buildPreviewAnimation, buildMotionPathPreview, getRoundRectRadiusPx2, getResolvedShapeClipPath, mediaFallbackVisual, registerPersistentAudio, resolveAutoFitFontScale, getSubstituteFontFamily, parsePanoseString, hasDistinctScriptFonts, nestedTextDecorationStyle, pieceLetterSpacing, resolveMetricTrackingPx, hollowTextFillStyle, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects, clampUnitInterval, customGeometryPathsToSvgSubpaths, svgGradientFillRef, computeColumnBoundaries, getTableCellBandStyle, parseDrawingColor, parseDrawingColorOpacity, getCellDiagonalBorders, cellRunStyle, getChartStylePalette, computeChartLegendLayout, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, convertOmmlToMathMl, sanitizeMathMl, tableCellCss, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, ooxmlGradientAngleToCssDegrees, chartPartToAttrs, splitRunForMetrics, hexToRgbChannels, segmentByScript, resolveFontForScript } from './chunk-57TM4MV4.mjs';
2
+ import { SHAPE_PRESET_DEFS, VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle, cloneHistorySnapshot, hasShapeProperties, getImageFitStyle, isImageLikeElement, getImageTilingStyle, runMediaCommand, findMediaElementByElementId, mediaPlaybackAttributes, buildTextBlockStyle, hasTextProperties, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle, buildParagraphs, colorWithOpacity, normalizeHexColor, build3DExtrusionData, getComputedFillStyle, getComputedEffectStyle, getComputedStrokeStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, normalizeStrokeDashType, getSvgStrokeDasharray, buildSvgGradientDef, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, computeSelectionRect, DEFAULT_FONT_FAMILY, cellStyleToCss, rectToCells, isCellInRect, tableContainerCss, buildChartViewModel, resolveChartKind, chartPreserveAspectRatio, buildNotesPdfBytes, buildSlidesPdfBytes, buildPreviewAnimation, buildMotionPathPreview, getRoundRectRadiusPx2, getResolvedShapeClipPath, mediaFallbackVisual, registerPersistentAudio, resolveAutoFitFontScale, resolveFontKerning, getSubstituteFontFamily, parsePanoseString, resolveScriptFontSet, hasDistinctScriptFonts, nestedTextDecorationStyle, pieceLetterSpacing, resolveMetricTrackingPx, hollowTextFillStyle, buildTabContext, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects, clampUnitInterval, customGeometryPathsToSvgSubpaths, svgGradientFillRef, buildSubpathPaints, computeColumnBoundaries, getTableCellBandStyle, parseDrawingColor, parseDrawingColorOpacity, getCellDiagonalBorders, cellRunStyle, getChartStylePalette, computeChartLegendLayout, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, convertOmmlToMathMl, sanitizeMathMl, tableCellCss, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, ooxmlGradientAngleToCssDegrees, buildRunTabLines, chartPartToAttrs, splitRunForMetrics, splitRunByScriptFont } from './chunk-OXPD2UYI.mjs';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import React6, { useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect } from 'react';
@@ -1215,136 +1215,13 @@ function wrapWithTextBuildAnimation(elementId, paraIndex, renderedSegments, para
1215
1215
  );
1216
1216
  });
1217
1217
  }
1218
- var EPS = 0.01;
1219
- var FALLBACK_STEP_PX = 48;
1220
- function buildTabContext(tabStops, defaultTabSize, fontSizePx, fontFamily, bold, italic) {
1221
- if (!tabStops || tabStops.length === 0) {
1222
- return void 0;
1223
- }
1224
- const font = `${italic ? "italic " : ""}${bold ? "700" : "400"} ${fontSizePx}px ${fontFamily}`;
1225
- return {
1226
- tabStops,
1227
- defaultTabSize: typeof defaultTabSize === "number" && defaultTabSize > 0 ? defaultTabSize : 0,
1228
- font
1229
- };
1230
- }
1231
- function leaderGlyph(leader) {
1232
- switch (leader) {
1233
- case "dot":
1234
- return ".";
1235
- case "hyphen":
1236
- return "-";
1237
- case "underscore":
1238
- return "_";
1239
- default:
1240
- return "";
1241
- }
1242
- }
1243
- function decimalIndex(text) {
1244
- return text.indexOf(".");
1245
- }
1246
- function computeTabbedLayout(segments, tabStops, measure, defaultTabSize) {
1247
- const stops = tabStops.filter((s) => Number.isFinite(s.position) && s.position > 0).sort((a, b) => a.position - b.position);
1248
- const step = Number.isFinite(defaultTabSize) && defaultTabSize > 0 ? defaultTabSize : FALLBACK_STEP_PX;
1249
- const pieces = [];
1250
- let cursor = 0;
1251
- segments.forEach((text, i) => {
1252
- if (i === 0) {
1253
- pieces.push({ text, left: 0, leaderWidth: 0, leaderChar: "" });
1254
- cursor = measure(text);
1255
- return;
1256
- }
1257
- const stop = stops.find((s) => s.position > cursor + EPS);
1258
- const width = measure(text);
1259
- let tabX;
1260
- let align;
1261
- let leader;
1262
- if (stop) {
1263
- tabX = stop.position;
1264
- align = stop.align;
1265
- leader = stop.leader;
1266
- } else {
1267
- tabX = Math.floor(cursor / step + 1 + EPS) * step;
1268
- align = "l";
1269
- leader = void 0;
1270
- }
1271
- let left;
1272
- if (align === "ctr") {
1273
- left = tabX - width / 2;
1274
- } else if (align === "r") {
1275
- left = tabX - width;
1276
- } else if (align === "dec") {
1277
- const decIdx = decimalIndex(text);
1278
- const beforeWidth = decIdx >= 0 ? measure(text.slice(0, decIdx)) : width;
1279
- left = tabX - beforeWidth;
1280
- } else {
1281
- left = tabX;
1282
- }
1283
- if (left < cursor) {
1284
- left = cursor;
1285
- }
1286
- const leaderWidth = left - cursor;
1287
- const leaderChar = leaderWidth > 0.5 ? leaderGlyph(leader) : "";
1288
- pieces.push({ text, left, leaderWidth, leaderChar });
1289
- cursor = left + width;
1290
- });
1291
- return pieces;
1292
- }
1293
- var cachedCtx;
1294
- function getMeasureCtx() {
1295
- if (cachedCtx !== void 0) {
1296
- return cachedCtx;
1297
- }
1298
- if (typeof document === "undefined") {
1299
- cachedCtx = null;
1300
- return null;
1301
- }
1302
- cachedCtx = document.createElement("canvas").getContext("2d");
1303
- return cachedCtx;
1304
- }
1305
- function estimateWidth(text) {
1306
- return text.length * 8;
1307
- }
1308
- function measureTextWidth(text, font) {
1309
- const ctx = getMeasureCtx();
1310
- if (!ctx) {
1311
- return estimateWidth(text);
1312
- }
1313
- ctx.font = font;
1314
- return ctx.measureText(text).width;
1315
- }
1316
- function fillLeader(glyph, width, font) {
1317
- const glyphWidth = Math.max(1, measureTextWidth(glyph, font));
1318
- const count = Math.ceil(width / glyphWidth) + 1;
1319
- return glyph.repeat(count);
1320
- }
1321
1218
  function renderTabbedLine(line, ctx, keyPrefix, renderPiece, nestedStyle) {
1322
- const segments = line.split(" ");
1323
- const pieces = computeTabbedLayout(
1324
- segments,
1325
- ctx.tabStops,
1326
- (t) => measureTextWidth(t, ctx.font),
1327
- ctx.defaultTabSize
1328
- );
1329
- return /* @__PURE__ */ jsx("span", { style: { display: "inline-block", whiteSpace: "nowrap" }, children: pieces.map((piece, i) => {
1219
+ const [lineLayout] = buildRunTabLines(line, ctx, nestedStyle);
1220
+ return /* @__PURE__ */ jsx("span", { style: { display: "inline-block", whiteSpace: "nowrap" }, children: lineLayout.pieces.map((piece, i) => {
1330
1221
  const key = `${keyPrefix}-tab-${i}`;
1331
1222
  return /* @__PURE__ */ jsxs(React6.Fragment, { children: [
1332
- piece.leaderWidth > 0 ? /* @__PURE__ */ jsx(
1333
- "span",
1334
- {
1335
- "aria-hidden": "true",
1336
- style: {
1337
- display: "inline-block",
1338
- width: piece.leaderWidth,
1339
- overflow: "hidden",
1340
- whiteSpace: "nowrap",
1341
- textAlign: "right",
1342
- verticalAlign: "baseline"
1343
- },
1344
- children: piece.leaderChar ? fillLeader(piece.leaderChar, piece.leaderWidth, ctx.font) : ""
1345
- }
1346
- ) : null,
1347
- /* @__PURE__ */ jsx("span", { style: { ...nestedStyle, display: "inline-block", whiteSpace: "pre" }, children: renderPiece(piece.text, key) })
1223
+ piece.leaderStyle ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: piece.leaderStyle, children: piece.leaderText }) : null,
1224
+ /* @__PURE__ */ jsx("span", { style: piece.style, children: renderPiece(piece.text, key) })
1348
1225
  ] }, key);
1349
1226
  }) });
1350
1227
  }
@@ -1352,23 +1229,18 @@ function renderScriptAwareText(text, needsScriptFonts, scriptFonts, baseFontFami
1352
1229
  if (!needsScriptFonts || !text) {
1353
1230
  return text;
1354
1231
  }
1355
- const runs = segmentByScript(text);
1356
- if (runs.length <= 1) {
1357
- if (runs.length === 1) {
1358
- const font = resolveFontForScript(runs[0].script, scriptFonts);
1359
- if (font && font !== baseFontFamily) {
1360
- return /* @__PURE__ */ jsx("span", { style: { ...nestedStyle, fontFamily: font }, children: text });
1361
- }
1362
- }
1232
+ const pieces = splitRunByScriptFont(
1233
+ text,
1234
+ scriptFonts,
1235
+ baseFontFamily,
1236
+ nestedStyle
1237
+ );
1238
+ if (!pieces) {
1363
1239
  return text;
1364
1240
  }
1365
- return runs.map((run, i) => {
1366
- const font = resolveFontForScript(run.script, scriptFonts);
1367
- if (!font || font === baseFontFamily) {
1368
- return /* @__PURE__ */ jsx(React6.Fragment, { children: run.text }, `${keyPrefix}-r${i}`);
1369
- }
1370
- return /* @__PURE__ */ jsx("span", { style: { ...nestedStyle, fontFamily: font }, children: run.text }, `${keyPrefix}-r${i}`);
1371
- });
1241
+ return pieces.map(
1242
+ (piece, i) => piece.style ? /* @__PURE__ */ jsx("span", { style: piece.style, children: piece.text }, `${keyPrefix}-r${i}`) : /* @__PURE__ */ jsx(React6.Fragment, { children: piece.text }, `${keyPrefix}-r${i}`)
1243
+ );
1372
1244
  }
1373
1245
  function renderMetricPieces(text, metric, keyPrefix, inner) {
1374
1246
  if (!metric || !text) {
@@ -1520,6 +1392,74 @@ function renderEquationSegment(elementId, segmentIndex, equationXml, equationNum
1520
1392
  }
1521
1393
  return /* @__PURE__ */ jsx("span", { children: equationContent }, `${elementId}-seg-${segmentIndex}`);
1522
1394
  }
1395
+ function renderHyperlink(run, spanNode, key, ctx) {
1396
+ const url = run.hyperlink?.url;
1397
+ const onHyperlinkClick = ctx.onHyperlinkClick;
1398
+ if (!url || !onHyperlinkClick) {
1399
+ return spanNode;
1400
+ }
1401
+ const requireCtrlClick = ctx.requireCtrlClick;
1402
+ const displayUrl = url.startsWith("ppaction://") ? url.replace(/^ppaction:\/\//u, "").split("?")[0] : url;
1403
+ const follow = (modified) => {
1404
+ if (requireCtrlClick && !modified) {
1405
+ return false;
1406
+ }
1407
+ onHyperlinkClick(url);
1408
+ return true;
1409
+ };
1410
+ return /* @__PURE__ */ jsxs(
1411
+ "span",
1412
+ {
1413
+ role: "link",
1414
+ tabIndex: 0,
1415
+ className: requireCtrlClick ? "group/link relative" : void 0,
1416
+ style: { cursor: requireCtrlClick ? void 0 : "pointer", pointerEvents: "auto" },
1417
+ title: run.hyperlink?.tooltip,
1418
+ onClick: (e) => {
1419
+ if (!follow(e.ctrlKey || e.metaKey)) {
1420
+ return;
1421
+ }
1422
+ e.stopPropagation();
1423
+ e.preventDefault();
1424
+ },
1425
+ onKeyDown: (e) => {
1426
+ if (e.key !== "Enter" && e.key !== " ") {
1427
+ return;
1428
+ }
1429
+ if (!follow(e.ctrlKey || e.metaKey)) {
1430
+ return;
1431
+ }
1432
+ e.preventDefault();
1433
+ e.stopPropagation();
1434
+ },
1435
+ children: [
1436
+ spanNode,
1437
+ requireCtrlClick && /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-0 top-full z-[9999] mt-1 max-w-64 opacity-0 transition-opacity duration-150 group-hover/link:opacity-100", children: /* @__PURE__ */ jsxs("span", { className: "flex flex-col rounded border border-border bg-popover px-2.5 py-1.5 shadow-lg", children: [
1438
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: displayUrl }),
1439
+ /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-[10px] text-muted-foreground", children: "Ctrl+Click to follow link" })
1440
+ ] }) })
1441
+ ]
1442
+ },
1443
+ `${key}-link`
1444
+ );
1445
+ }
1446
+ function wrapWithTextReflection(run, key, spanNode, spanStyle, baseContent) {
1447
+ if (!run.reflection) {
1448
+ return spanNode;
1449
+ }
1450
+ return /* @__PURE__ */ jsxs("span", { style: { position: "relative", display: "inline-block" }, children: [
1451
+ spanNode,
1452
+ /* @__PURE__ */ jsx(
1453
+ "span",
1454
+ {
1455
+ "aria-hidden": "true",
1456
+ className: "pptx-react-text-reflection",
1457
+ style: run.reflection,
1458
+ children: /* @__PURE__ */ jsx("span", { style: spanStyle, children: baseContent })
1459
+ }
1460
+ )
1461
+ ] }, `${key}-reflwrap`);
1462
+ }
1523
1463
  var BASELINE_FONT_SCALE = 0.65;
1524
1464
  function renderParagraphRun(run, segment, ctx, keySuffix = "") {
1525
1465
  const { element, fallbackColor, findHighlights, onHyperlinkClick } = ctx;
@@ -1541,29 +1481,13 @@ function renderParagraphRun(run, segment, ctx, keySuffix = "") {
1541
1481
  const rawFontSize = segmentStyle.fontSize || element.textStyle?.fontSize || DEFAULT_TEXT_FONT_SIZE;
1542
1482
  const baseFontSize = rawFontSize * resolveAutoFitFontScale(element.textStyle);
1543
1483
  const baselineShift = baselineFraction !== 0 ? `${baselineFraction * baseFontSize}px` : void 0;
1544
- const baseFontSizePt = baseFontSize * (72 / 96);
1545
- const fontKerning = typeof segmentStyle.kerning === "number" ? segmentStyle.kerning === 0 ? "none" : baseFontSizePt >= segmentStyle.kerning / 100 ? "normal" : "none" : void 0;
1484
+ const fontKerning = resolveFontKerning(segmentStyle.kerning, baseFontSize);
1546
1485
  const rawFontFamily = segmentStyle.fontFamily || element.textStyle?.fontFamily;
1547
1486
  const baseFontFamily = rawFontFamily ? getSubstituteFontFamily(
1548
1487
  rawFontFamily,
1549
1488
  parsePanoseString(segmentStyle.latinFontPanose ?? element.textStyle?.latinFontPanose)
1550
1489
  ) : DEFAULT_FONT_FAMILY2;
1551
- const scriptFont = (name, panose) => name ? getSubstituteFontFamily(name, parsePanoseString(panose)) : baseFontFamily;
1552
- const scriptFonts = {
1553
- latin: baseFontFamily,
1554
- eastAsia: scriptFont(
1555
- segmentStyle.eastAsiaFont || element.textStyle?.eastAsiaFont,
1556
- segmentStyle.eastAsiaFontPanose ?? element.textStyle?.eastAsiaFontPanose
1557
- ),
1558
- complexScript: scriptFont(
1559
- segmentStyle.complexScriptFont || element.textStyle?.complexScriptFont,
1560
- segmentStyle.complexScriptFontPanose ?? element.textStyle?.complexScriptFontPanose
1561
- ),
1562
- symbol: scriptFont(
1563
- segmentStyle.symbolFont || element.textStyle?.symbolFont,
1564
- segmentStyle.symbolFontPanose ?? element.textStyle?.symbolFontPanose
1565
- )
1566
- };
1490
+ const scriptFonts = resolveScriptFontSet(segmentStyle, element.textStyle, baseFontFamily);
1567
1491
  const needsScriptFonts = hasDistinctScriptFonts(scriptFonts);
1568
1492
  const authoredLetterSpacing = typeof segmentStyle.characterSpacing === "number" && segmentStyle.characterSpacing !== 0 ? segmentStyle.characterSpacing / 100 * (96 / 72) : 0;
1569
1493
  const metricFont = {
@@ -1616,7 +1540,8 @@ function renderParagraphRun(run, segment, ctx, keySuffix = "") {
1616
1540
  metricContext
1617
1541
  );
1618
1542
  const spanNode = /* @__PURE__ */ jsx("span", { "data-seg-idx": segmentIndex, style: spanStyle, children: renderRubyOrText(run, baseContent) }, key);
1619
- return run.hyperlink && onHyperlinkClick ? renderHyperlink(run, spanNode, key, ctx) : spanNode;
1543
+ const reflectedNode = wrapWithTextReflection(run, key, spanNode, spanStyle, baseContent);
1544
+ return run.hyperlink && onHyperlinkClick ? renderHyperlink(run, reflectedNode, key, ctx) : reflectedNode;
1620
1545
  }
1621
1546
  function renderRubyOrText(run, baseContent) {
1622
1547
  if (!run.ruby) {
@@ -1629,57 +1554,6 @@ function renderRubyOrText(run, baseContent) {
1629
1554
  /* @__PURE__ */ jsx("rp", { children: ")" })
1630
1555
  ] });
1631
1556
  }
1632
- function renderHyperlink(run, spanNode, key, ctx) {
1633
- const url = run.hyperlink?.url;
1634
- const onHyperlinkClick = ctx.onHyperlinkClick;
1635
- if (!url || !onHyperlinkClick) {
1636
- return spanNode;
1637
- }
1638
- const requireCtrlClick = ctx.requireCtrlClick;
1639
- const displayUrl = url.startsWith("ppaction://") ? url.replace(/^ppaction:\/\//u, "").split("?")[0] : url;
1640
- const follow = (modified) => {
1641
- if (requireCtrlClick && !modified) {
1642
- return false;
1643
- }
1644
- onHyperlinkClick(url);
1645
- return true;
1646
- };
1647
- return /* @__PURE__ */ jsxs(
1648
- "span",
1649
- {
1650
- role: "link",
1651
- tabIndex: 0,
1652
- className: requireCtrlClick ? "group/link relative" : void 0,
1653
- style: { cursor: requireCtrlClick ? void 0 : "pointer", pointerEvents: "auto" },
1654
- title: run.hyperlink?.tooltip,
1655
- onClick: (e) => {
1656
- if (!follow(e.ctrlKey || e.metaKey)) {
1657
- return;
1658
- }
1659
- e.stopPropagation();
1660
- e.preventDefault();
1661
- },
1662
- onKeyDown: (e) => {
1663
- if (e.key !== "Enter" && e.key !== " ") {
1664
- return;
1665
- }
1666
- if (!follow(e.ctrlKey || e.metaKey)) {
1667
- return;
1668
- }
1669
- e.preventDefault();
1670
- e.stopPropagation();
1671
- },
1672
- children: [
1673
- spanNode,
1674
- requireCtrlClick && /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-0 top-full z-[9999] mt-1 max-w-64 opacity-0 transition-opacity duration-150 group-hover/link:opacity-100", children: /* @__PURE__ */ jsxs("span", { className: "flex flex-col rounded border border-border bg-popover px-2.5 py-1.5 shadow-lg", children: [
1675
- /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: displayUrl }),
1676
- /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-[10px] text-muted-foreground", children: "Ctrl+Click to follow link" })
1677
- ] }) })
1678
- ]
1679
- },
1680
- `${key}-link`
1681
- );
1682
- }
1683
1557
  function renderTextSegments(element, fallbackColor, emptyFallback, findHighlights, onHyperlinkClick, fieldContext, subElementAnimStates, segmentOverrides, requireCtrlClick) {
1684
1558
  if (!hasTextProperties(element)) {
1685
1559
  return emptyFallback || null;
@@ -1953,7 +1827,10 @@ function getShapeVisualStyle(element, _hasFill, fillColor, _strokeWidth, _stroke
1953
1827
  // opposite end along the edge. Paint from the border box instead.
1954
1828
  backgroundOrigin: "border-box",
1955
1829
  boxShadow: fx.boxShadow,
1956
- WebkitBoxReflect: fx.webkitBoxReflect,
1830
+ // Reflection is no longer a single CSS property (`-webkit-box-reflect`
1831
+ // never worked in Firefox): `ElementRenderer` renders a mirrored sibling
1832
+ // node instead, using shared's `getReflectionWrapperStyle` directly (see
1833
+ // `ReflectionOverlay`).
1957
1834
  filter: fx.filter,
1958
1835
  opacity: fx.opacity,
1959
1836
  // Only proxy the DAG blend onto the whole element for the blend-only case:
@@ -2142,44 +2019,6 @@ function renderConnectorMarker(markerId, arrowType, color, arrowWidth, arrowLeng
2142
2019
  }
2143
2020
  );
2144
2021
  }
2145
-
2146
- // src/viewer/utils/vector-subpath-paint.ts
2147
- function toHexByte(value) {
2148
- const clamped = Math.max(0, Math.min(255, Math.round(value)));
2149
- return clamped.toString(16).padStart(2, "0");
2150
- }
2151
- function shiftHex(hex, factor, towardsWhite) {
2152
- const channels = hexToRgbChannels(hex);
2153
- if (!channels) {
2154
- return hex;
2155
- }
2156
- const shift = (c) => towardsWhite ? c + (255 - c) * factor : c * (1 - factor);
2157
- return `#${toHexByte(shift(channels.r))}${toHexByte(shift(channels.g))}${toHexByte(shift(channels.b))}`;
2158
- }
2159
- function adjustFillForMode(fillHex, mode) {
2160
- switch (mode) {
2161
- case "lighten":
2162
- return shiftHex(fillHex, 0.4, true);
2163
- case "lightenLess":
2164
- return shiftHex(fillHex, 0.2, true);
2165
- case "darken":
2166
- return shiftHex(fillHex, 0.4, false);
2167
- case "darkenLess":
2168
- return shiftHex(fillHex, 0.2, false);
2169
- default:
2170
- return fillHex;
2171
- }
2172
- }
2173
- function buildCustomSubpathPaints(subpaths, hasFill, fillColor, fillOpacity) {
2174
- return subpaths.map((subpath) => {
2175
- const fillOff = subpath.fillMode === "none" || !hasFill;
2176
- return {
2177
- d: subpath.d,
2178
- fill: fillOff ? "none" : colorWithOpacity(adjustFillForMode(fillColor, subpath.fillMode), fillOpacity),
2179
- stroked: subpath.stroke !== false
2180
- };
2181
- });
2182
- }
2183
2022
  function joinStyle(shapeStyle) {
2184
2023
  const lineJoin = shapeStyle?.lineJoin === "bevel" ? "bevel" : shapeStyle?.lineJoin === "miter" ? "miter" : "round";
2185
2024
  const miterLimit = lineJoin === "miter" && typeof shapeStyle?.miterLimit === "number" ? Math.max(shapeStyle.miterLimit / 1e5, 1) : void 0;
@@ -2248,7 +2087,7 @@ function renderCustomGeometryVector(pathData, pathWidth, pathHeight, structuredP
2248
2087
  const gradientPaint = gradient ? svgGradientFillRef(gradient) : void 0;
2249
2088
  const nodes = [];
2250
2089
  if (subpaths && needsPerSubpath) {
2251
- const paints = buildCustomSubpathPaints(subpaths, hasFill, fillColor, fillOpacity);
2090
+ const paints = buildSubpathPaints(subpaths, hasFill, fillColor, fillOpacity);
2252
2091
  paints.forEach((paint, idx) => {
2253
2092
  if (paint.fill !== "none") {
2254
2093
  const mode = subpaths[idx]?.fillMode;
@@ -3773,6 +3612,8 @@ function renderText(t, key) {
3773
3612
  fontSize: t.fontSize,
3774
3613
  fill: t.fill,
3775
3614
  fontWeight: t.fontWeight ?? "normal",
3615
+ fontStyle: t.fontStyle ?? "normal",
3616
+ fontFamily: t.fontFamily,
3776
3617
  dominantBaseline: t.dominantBaseline,
3777
3618
  opacity: t.opacity ?? 1,
3778
3619
  transform: t.transform,
@@ -3852,7 +3693,19 @@ function renderChartViewModel(elementId, vm, preserveAspectRatio = "none") {
3852
3693
  transform: `translate(${item.x.toFixed(1)},${item.y.toFixed(1)})`,
3853
3694
  children: [
3854
3695
  /* @__PURE__ */ jsx("rect", { x: 0, y: -7, width: 10, height: 10, rx: 2, fill: item.color }),
3855
- /* @__PURE__ */ jsx("text", { x: 13, y: 3, fontSize: 9, fill: "#475569", children: item.label })
3696
+ /* @__PURE__ */ jsx(
3697
+ "text",
3698
+ {
3699
+ x: 13,
3700
+ y: 3,
3701
+ fontSize: item.fontSize,
3702
+ fill: item.fill,
3703
+ fontWeight: item.fontWeight,
3704
+ fontStyle: item.fontStyle,
3705
+ fontFamily: item.fontFamily,
3706
+ children: item.label
3707
+ }
3708
+ )
3856
3709
  ]
3857
3710
  },
3858
3711
  `${elementId}-lg-${i}`
@@ -3981,4 +3834,4 @@ function stopPreviewAnimation() {
3981
3834
  activePreview = null;
3982
3835
  }
3983
3836
 
3984
- export { ANIMATION_PRESET_OPTIONS, ARROW_SIZE_OPTIONS, CONNECTOR_ARROW_OPTIONS, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY2 as DEFAULT_FONT_FAMILY, DEFAULT_SECTION_GROUP_ID, DEFAULT_STROKE_COLOR, DEFAULT_TABLE_COLUMNS, DEFAULT_TABLE_ROWS, DEFAULT_TEXT_COLOR, DEFAULT_TEXT_FONT_SIZE, EMU_PER_PX, GRID_SIZE, HYPERLINK_COLOR, MIN_ELEMENT_SIZE, SHAPE_PRESETS, SHORTCUT_REFERENCE_ITEMS, SLIDE_NAV_THUMBNAIL_WIDTH, STROKE_DASH_OPTIONS, THEME_COLOR_SWATCHES, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, ZOOM_TO_SELECTION_PADDING, build3DExtrusionData2 as build3DExtrusionData, buildLineGlowFilter, buildLineShadowCss, buildNotesPdf, buildPdfFromImageData, buildReactChartViewModel, buildTextBody3DSceneStyle2 as buildTextBody3DSceneStyle, cloneHistorySnapshot2 as cloneHistorySnapshot, cn, executeMediaCommand, getAnimationInitialStyle2 as getAnimationInitialStyle, getConnectorPathGeometry, getCropShapeClipPath, getDuotoneColors, getImageRenderStyle, getImageTilingStyle2 as getImageTilingStyle, getShapeVisualStyle, getTextLayoutStyle, getTextStyleForElement, getTextWarpStyle, hasDagDuotoneEffect, isConnectorOrLineElement, renderChartElement, renderConnectorMarker, renderDagDuotoneSvgFilter, renderMediaElement, renderTableElement, renderTextSegments, renderVectorShape, shouldRenderFallbackLabel, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation };
3837
+ export { ANIMATION_PRESET_OPTIONS, ARROW_SIZE_OPTIONS, CONNECTOR_ARROW_OPTIONS, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_FONT_FAMILY2 as 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, SHAPE_PRESETS, SHORTCUT_REFERENCE_ITEMS, SLIDE_NAV_THUMBNAIL_WIDTH, STROKE_DASH_OPTIONS, THEME_COLOR_SWATCHES, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, ZOOM_TO_SELECTION_PADDING, build3DExtrusionData2 as build3DExtrusionData, buildLineGlowFilter, buildLineShadowCss, buildNotesPdf, buildPdfFromImageData, buildReactChartViewModel, buildTextBody3DSceneStyle2 as buildTextBody3DSceneStyle, cloneHistorySnapshot2 as cloneHistorySnapshot, cn, executeMediaCommand, getAnimationInitialStyle2 as getAnimationInitialStyle, getConnectorPathGeometry, getCropShapeClipPath, getDuotoneColors, getImageRenderStyle, getImageTilingStyle2 as getImageTilingStyle, getShapeVisualStyle, getTextLayoutStyle, getTextStyleForElement, getTextWarpStyle, hasDagDuotoneEffect, isConnectorOrLineElement, renderChartElement, renderConnectorMarker, renderDagDuotoneSvgFilter, renderMediaElement, renderTableElement, renderTextSegments, renderVectorShape, shouldRenderFallbackLabel, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation };
Binary file
Binary file