@office-kit/pptx 0.16.1 → 0.17.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.
@@ -27,6 +27,9 @@ const STORE_BY_EXTENSION = new Set([
27
27
  "wmv",
28
28
  "mov",
29
29
  "avi",
30
+ "webm",
31
+ "ogg",
32
+ "wma",
30
33
  "pdf",
31
34
  "zip",
32
35
  "gz",
@@ -825,7 +828,7 @@ const emptyContentTypes = () => ({
825
828
  const REL_NS = NS.relationships;
826
829
  const NAME_RELATIONSHIPS = qname("", "Relationships", REL_NS);
827
830
  const NAME_RELATIONSHIP = qname("", "Relationship", REL_NS);
828
- const ATTR_ID$14 = qname("", "Id", "");
831
+ const ATTR_ID$16 = qname("", "Id", "");
829
832
  const ATTR_TYPE$7 = qname("", "Type", "");
830
833
  const ATTR_TARGET = qname("", "Target", "");
831
834
  const ATTR_TARGET_MODE = qname("", "TargetMode", "");
@@ -863,7 +866,7 @@ const serializeRels = (rels) => {
863
866
  const children = rels.items.map((r) => {
864
867
  const attrs = [
865
868
  {
866
- name: ATTR_ID$14,
869
+ name: ATTR_ID$16,
867
870
  value: r.id
868
871
  },
869
872
  {
@@ -1060,6 +1063,79 @@ const contentTypeForFormat = (format) => {
1060
1063
  }
1061
1064
  };
1062
1065
  //#endregion
1066
+ //#region src/internal/opc/media-format.ts
1067
+ const VIDEO_CONTENT_TYPES = {
1068
+ mp4: "video/mp4",
1069
+ m4v: "video/mp4",
1070
+ mov: "video/quicktime",
1071
+ webm: "video/webm",
1072
+ avi: "video/x-msvideo",
1073
+ wmv: "video/x-ms-wmv"
1074
+ };
1075
+ const AUDIO_CONTENT_TYPES = {
1076
+ mp3: "audio/mpeg",
1077
+ wav: "audio/x-wav",
1078
+ m4a: "audio/mp4",
1079
+ ogg: "audio/ogg",
1080
+ wma: "audio/x-ms-wma"
1081
+ };
1082
+ const contentTypeForVideoFormat = (format) => VIDEO_CONTENT_TYPES[format];
1083
+ const contentTypeForAudioFormat = (format) => AUDIO_CONTENT_TYPES[format];
1084
+ const hasBytesAt = (bytes, at, signature) => {
1085
+ if (bytes.length < at + signature.length) return false;
1086
+ for (let i = 0; i < signature.length; i++) if (bytes[at + i] !== signature[i]) return false;
1087
+ return true;
1088
+ };
1089
+ const hasAsciiAt = (bytes, at, text) => hasBytesAt(bytes, at, Array.from(text, (ch) => ch.charCodeAt(0)));
1090
+ const isoBrand = (bytes) => hasAsciiAt(bytes, 4, "ftyp") && bytes.length >= 12 ? String.fromCharCode(bytes[8], bytes[9], bytes[10], bytes[11]) : null;
1091
+ const isRiff = (bytes, form) => hasAsciiAt(bytes, 0, "RIFF") && hasAsciiAt(bytes, 8, form);
1092
+ const ASF_HEADER = [
1093
+ 48,
1094
+ 38,
1095
+ 178,
1096
+ 117,
1097
+ 142,
1098
+ 102,
1099
+ 207,
1100
+ 17
1101
+ ];
1102
+ const EBML_HEADER = [
1103
+ 26,
1104
+ 69,
1105
+ 223,
1106
+ 163
1107
+ ];
1108
+ const EBML_DOCTYPE_WINDOW = 64;
1109
+ const isWebm = (bytes) => {
1110
+ if (!hasBytesAt(bytes, 0, EBML_HEADER)) return false;
1111
+ const limit = Math.min(bytes.length, EBML_DOCTYPE_WINDOW) - 4;
1112
+ for (let i = 4; i <= limit; i++) if (hasAsciiAt(bytes, i, "webm")) return true;
1113
+ return false;
1114
+ };
1115
+ /** Detects a video container, or `null` when no known signature matches. */
1116
+ const detectVideoFormat = (bytes) => {
1117
+ const brand = isoBrand(bytes);
1118
+ if (brand !== null) {
1119
+ if (brand === "qt ") return "mov";
1120
+ if (brand === "M4V ") return "m4v";
1121
+ return "mp4";
1122
+ }
1123
+ if (isWebm(bytes)) return "webm";
1124
+ if (isRiff(bytes, "AVI ")) return "avi";
1125
+ if (hasBytesAt(bytes, 0, ASF_HEADER)) return "wmv";
1126
+ return null;
1127
+ };
1128
+ /** Detects an audio container, or `null` when no known signature matches. */
1129
+ const detectAudioFormat = (bytes) => {
1130
+ if (isoBrand(bytes) !== null) return "m4a";
1131
+ if (isRiff(bytes, "WAVE")) return "wav";
1132
+ if (hasAsciiAt(bytes, 0, "OggS")) return "ogg";
1133
+ if (hasBytesAt(bytes, 0, ASF_HEADER)) return "wma";
1134
+ if (hasAsciiAt(bytes, 0, "ID3")) return "mp3";
1135
+ if (bytes.length >= 2 && bytes[0] === 255 && (bytes[1] & 224) === 224) return "mp3";
1136
+ return null;
1137
+ };
1138
+ //#endregion
1063
1139
  //#region src/internal/parts/package.ts
1064
1140
  const TEXT_DECODER$1 = new TextDecoder();
1065
1141
  const TEXT_ENCODER$3 = new TextEncoder();
@@ -1382,7 +1458,7 @@ const savePresentation = (pres) => {
1382
1458
  //#region src/internal/presentationml/relationship-types.ts
1383
1459
  const OFFICE_DOC = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
1384
1460
  const PACKAGE = "http://schemas.openxmlformats.org/package/2006/relationships";
1385
- const MS_2010 = "http://schemas.microsoft.com/office/2010/relationships";
1461
+ const MS_2007 = "http://schemas.microsoft.com/office/2007/relationships";
1386
1462
  const MS_2015 = "http://schemas.microsoft.com/office/2015/relationships";
1387
1463
  const REL_TYPES = {
1388
1464
  officeDocument: `${OFFICE_DOC}/officeDocument`,
@@ -1411,10 +1487,10 @@ const REL_TYPES = {
1411
1487
  diagramLayout: `${OFFICE_DOC}/diagramLayout`,
1412
1488
  diagramQuickStyle: `${OFFICE_DOC}/diagramQuickStyle`,
1413
1489
  diagramColors: `${OFFICE_DOC}/diagramColors`,
1414
- media: `${MS_2010}/media`,
1415
- video: `${MS_2010}/video`,
1416
- audio: `${MS_2010}/audio`,
1417
- font: `${MS_2010}/font`,
1490
+ media: `${MS_2007}/media`,
1491
+ video: `${OFFICE_DOC}/video`,
1492
+ audio: `${OFFICE_DOC}/audio`,
1493
+ font: `${OFFICE_DOC}/font`,
1418
1494
  authors: `${MS_2015}/authors`,
1419
1495
  modernComment: `${MS_2015}/comments`,
1420
1496
  comments: `${OFFICE_DOC}/comments`,
@@ -1431,13 +1507,13 @@ const NAME_NOTES_MASTER_ID_LST = qname("p", "notesMasterIdLst", NS.pml);
1431
1507
  const NAME_NOTES_MASTER_ID = qname("p", "notesMasterId", NS.pml);
1432
1508
  const NAME_SLD_SZ = qname("p", "sldSz", NS.pml);
1433
1509
  const NAME_NOTES_SZ = qname("p", "notesSz", NS.pml);
1434
- const ATTR_ID$13 = qname("", "id", "");
1435
- const ATTR_R_ID$3 = qname("r", "id", NS.officeDocRels);
1510
+ const ATTR_ID$15 = qname("", "id", "");
1511
+ const ATTR_R_ID$4 = qname("r", "id", NS.officeDocRels);
1436
1512
  const ATTR_CX$9 = qname("", "cx", "");
1437
1513
  const ATTR_CY$9 = qname("", "cy", "");
1438
1514
  const ATTR_TYPE$6 = qname("", "type", "");
1439
1515
  const requireRId = (element, context) => {
1440
- const value = getAttrValue(element, ATTR_R_ID$3);
1516
+ const value = getAttrValue(element, ATTR_R_ID$4);
1441
1517
  if (value === null) throw new Error(`${context}: missing r:id attribute`);
1442
1518
  return value;
1443
1519
  };
@@ -1463,7 +1539,7 @@ const readPresentationPart = (root) => {
1463
1539
  const sldMasters = [];
1464
1540
  const sldMasterLst = firstChildElement(root, NAME_SLD_MASTER_ID_LST$1);
1465
1541
  if (sldMasterLst !== null) for (const item of allChildElements(sldMasterLst, NAME_SLD_MASTER_ID)) {
1466
- const idRaw = getAttrValue(item, ATTR_ID$13);
1542
+ const idRaw = getAttrValue(item, ATTR_ID$15);
1467
1543
  if (idRaw === null) throw new Error("<p:sldMasterId>: missing id attribute");
1468
1544
  sldMasters.push({
1469
1545
  id: Number.parseInt(idRaw, 10),
@@ -1473,7 +1549,7 @@ const readPresentationPart = (root) => {
1473
1549
  const slides = [];
1474
1550
  const sldLst = firstChildElement(root, NAME_SLD_ID_LST$2);
1475
1551
  if (sldLst !== null) for (const item of allChildElements(sldLst, NAME_SLD_ID$2)) {
1476
- const idRaw = getAttrValue(item, ATTR_ID$13);
1552
+ const idRaw = getAttrValue(item, ATTR_ID$15);
1477
1553
  if (idRaw === null) throw new Error("<p:sldId>: missing id attribute");
1478
1554
  slides.push({
1479
1555
  id: Number.parseInt(idRaw, 10),
@@ -1551,7 +1627,15 @@ const RANGES = {
1551
1627
  overlap: [-100, 100],
1552
1628
  gapAmount: [0, 500],
1553
1629
  holeSize: [1, 90],
1554
- firstSliceAng: [0, 360]
1630
+ firstSliceAng: [0, 360],
1631
+ rotX: [-90, 90],
1632
+ rotY: [0, 360],
1633
+ perspective: [0, 240],
1634
+ depthPercent: [20, 2e3],
1635
+ heightPercent: [5, 500],
1636
+ secondPieSize: [5, 200],
1637
+ bubbleScale: [0, 300],
1638
+ percent100000: [0, 1e5]
1555
1639
  };
1556
1640
  const boundedInt = (value, key, field) => {
1557
1641
  if (!Number.isFinite(value)) throw new RangeError(`${field}: expected a finite number, got ${value}`);
@@ -2518,7 +2602,7 @@ const ATTR_WR = qname("", "wR", "");
2518
2602
  const ATTR_HR = qname("", "hR", "");
2519
2603
  const ATTR_ST_ANG = qname("", "stAng", "");
2520
2604
  const ATTR_SW_ANG = qname("", "swAng", "");
2521
- const ATTR_FILL$1 = qname("", "fill", "");
2605
+ const ATTR_FILL$2 = qname("", "fill", "");
2522
2606
  const ATTR_STROKE = qname("", "stroke", "");
2523
2607
  const NAME_AV_LST$5 = qname("a", "avLst", NS.dml);
2524
2608
  const NAME_GD_LST = qname("a", "gdLst", NS.dml);
@@ -2667,7 +2751,7 @@ const isPathFillMode = (s) => FILL_MODES.has(s);
2667
2751
  const parsePath = (pathEl, guides) => {
2668
2752
  const w = parseIntOrNull(getAttrValue(pathEl, ATTR_W$2));
2669
2753
  const h = parseIntOrNull(getAttrValue(pathEl, ATTR_H$1));
2670
- const fillRaw = getAttrValue(pathEl, ATTR_FILL$1);
2754
+ const fillRaw = getAttrValue(pathEl, ATTR_FILL$2);
2671
2755
  const fill = fillRaw !== null && isPathFillMode(fillRaw) ? fillRaw : "norm";
2672
2756
  const strokeRaw = getAttrValue(pathEl, ATTR_STROKE);
2673
2757
  const stroke = !(strokeRaw === "0" || strokeRaw === "false");
@@ -2760,8 +2844,8 @@ const parseCustomGeometry = (custGeom, shapeW, shapeH) => {
2760
2844
  //#region src/internal/drawingml/hyperlink.ts
2761
2845
  NS.dml;
2762
2846
  const NAME_RPR$4 = qname("a", "rPr", NS.dml);
2763
- const NAME_HLINK_CLICK = qname("a", "hlinkClick", NS.dml);
2764
- const ATTR_R_ID$2 = qname("r", "id", NS.officeDocRels);
2847
+ const NAME_HLINK_CLICK$1 = qname("a", "hlinkClick", NS.dml);
2848
+ const ATTR_R_ID$3 = qname("r", "id", NS.officeDocRels);
2765
2849
  /**
2766
2850
  * Sets `<a:hlinkClick r:id="rIdN" [tooltip="…"]/>` inside the `<a:rPr>`
2767
2851
  * of every run in `txBody`. Pass `null` for `rId` to remove an existing
@@ -2781,9 +2865,9 @@ const applyHyperlinkToAllRuns = (txBody, rId, tooltip) => {
2781
2865
  }
2782
2866
  rPr.children = rPr.children.filter((c) => !(c.kind === "element" && c.name.namespaceURI === NS.dml && c.name.localName === "hlinkClick"));
2783
2867
  if (rId !== null) {
2784
- const attrs = [attr(ATTR_R_ID$2, rId)];
2868
+ const attrs = [attr(ATTR_R_ID$3, rId)];
2785
2869
  if (tooltip !== void 0) attrs.push(attr(qname("", "tooltip", ""), tooltip));
2786
- rPr.children.push(elem(NAME_HLINK_CLICK, { attrs }));
2870
+ rPr.children.push(elem(NAME_HLINK_CLICK$1, { attrs }));
2787
2871
  }
2788
2872
  }
2789
2873
  }
@@ -2792,7 +2876,7 @@ const applyHyperlinkToAllRuns = (txBody, rId, tooltip) => {
2792
2876
  //#region src/internal/drawingml/picture-mutation.ts
2793
2877
  const NAME_BLIP_FILL$1 = qname("p", "blipFill", NS.pml);
2794
2878
  const NAME_BLIP$1 = qname("a", "blip", NS.dml);
2795
- const ATTR_R_EMBED$1 = qname("r", "embed", NS.officeDocRels);
2879
+ const ATTR_R_EMBED$2 = qname("r", "embed", NS.officeDocRels);
2796
2880
  /**
2797
2881
  * Returns the `r:embed` rId on this picture shape's `a:blip`. Returns null
2798
2882
  * if the shape has no blip fill, no blip, or no embed attribute (which
@@ -2803,7 +2887,7 @@ const getPictureEmbedRId = (picElement) => {
2803
2887
  if (blipFill === null) return null;
2804
2888
  const blip = firstChildElement(blipFill, NAME_BLIP$1);
2805
2889
  if (blip === null) return null;
2806
- return getAttrValue(blip, ATTR_R_EMBED$1);
2890
+ return getAttrValue(blip, ATTR_R_EMBED$2);
2807
2891
  };
2808
2892
  //#endregion
2809
2893
  //#region src/internal/drawingml/geometry.ts
@@ -2812,7 +2896,7 @@ const NAME_GRP_SP_PR$4 = qname("p", "grpSpPr", NS.pml);
2812
2896
  const NAME_A_XFRM$6 = qname("a", "xfrm", NS.dml);
2813
2897
  const NAME_P_XFRM$2 = qname("p", "xfrm", NS.pml);
2814
2898
  const NAME_OFF$8 = qname("a", "off", NS.dml);
2815
- const NAME_EXT$8 = qname("a", "ext", NS.dml);
2899
+ const NAME_EXT$9 = qname("a", "ext", NS.dml);
2816
2900
  const ATTR_X$8 = qname("", "x", "");
2817
2901
  const ATTR_Y$8 = qname("", "y", "");
2818
2902
  const ATTR_CX$8 = qname("", "cx", "");
@@ -2853,7 +2937,7 @@ const readPosition = (shape, kind) => {
2853
2937
  const readSize = (shape, kind) => {
2854
2938
  const xfrm = findTransform(shape, kind);
2855
2939
  if (xfrm === null) return null;
2856
- const ext = firstChildElement(xfrm, NAME_EXT$8);
2940
+ const ext = firstChildElement(xfrm, NAME_EXT$9);
2857
2941
  if (ext === null) return null;
2858
2942
  const w = parseIntOr(getAttrValue(ext, ATTR_CX$8));
2859
2943
  const h = parseIntOr(getAttrValue(ext, ATTR_CY$8));
@@ -2893,7 +2977,7 @@ const NAME_GRP_SP_PR$3 = qname("p", "grpSpPr", NS.pml);
2893
2977
  const NAME_A_XFRM$5 = qname("a", "xfrm", NS.dml);
2894
2978
  const NAME_P_XFRM$1 = qname("p", "xfrm", NS.pml);
2895
2979
  const NAME_OFF$7 = qname("a", "off", NS.dml);
2896
- const NAME_EXT$7 = qname("a", "ext", NS.dml);
2980
+ const NAME_EXT$8 = qname("a", "ext", NS.dml);
2897
2981
  const ATTR_X$7 = qname("", "x", "");
2898
2982
  const ATTR_Y$7 = qname("", "y", "");
2899
2983
  const ATTR_CX$7 = qname("", "cx", "");
@@ -2939,9 +3023,9 @@ const setPosition = (shape, kind, x, y) => {
2939
3023
  /** Sets the shape's `<a:ext>` to `(w, h)` in EMU. */
2940
3024
  const setSize = (shape, kind, w, h) => {
2941
3025
  const xfrm = ensureTransform(shape, kind);
2942
- let ext = firstChildElement(xfrm, NAME_EXT$7);
3026
+ let ext = firstChildElement(xfrm, NAME_EXT$8);
2943
3027
  if (ext === null) {
2944
- ext = elem(NAME_EXT$7);
3028
+ ext = elem(NAME_EXT$8);
2945
3029
  const offIdx = xfrm.children.findIndex((c) => c.kind === "element" && c.name.localName === "off" && c.name.namespaceURI === NS.dml);
2946
3030
  if (offIdx >= 0) xfrm.children.splice(offIdx + 1, 0, ext);
2947
3031
  else xfrm.children.push(ext);
@@ -3013,21 +3097,21 @@ const setAdjustValues = (shape, values) => {
3013
3097
  const NAME_CSLD$4 = qname("p", "cSld", NS.pml);
3014
3098
  const NAME_SP_TREE$3 = qname("p", "spTree", NS.pml);
3015
3099
  const NAME_NV_SP_PR$4 = qname("p", "nvSpPr", NS.pml);
3016
- const NAME_NV_PIC_PR$1 = qname("p", "nvPicPr", NS.pml);
3100
+ const NAME_NV_PIC_PR$2 = qname("p", "nvPicPr", NS.pml);
3017
3101
  const NAME_NV_GRP_SP_PR$3 = qname("p", "nvGrpSpPr", NS.pml);
3018
3102
  const NAME_NV_GRAPHIC_FRAME_PR$2 = qname("p", "nvGraphicFramePr", NS.pml);
3019
3103
  const NAME_NV_CXN_SP_PR$1 = qname("p", "nvCxnSpPr", NS.pml);
3020
- const NAME_C_NV_PR$8 = qname("p", "cNvPr", NS.pml);
3021
- const NAME_NV_PR$9 = qname("p", "nvPr", NS.pml);
3104
+ const NAME_C_NV_PR$9 = qname("p", "cNvPr", NS.pml);
3105
+ const NAME_NV_PR$10 = qname("p", "nvPr", NS.pml);
3022
3106
  const NAME_PH$2 = qname("p", "ph", NS.pml);
3023
3107
  const NAME_TX_BODY$9 = qname("p", "txBody", NS.pml);
3024
- const ATTR_ID$12 = qname("", "id", "");
3108
+ const ATTR_ID$14 = qname("", "id", "");
3025
3109
  const ATTR_NAME$11 = qname("", "name", "");
3026
3110
  const ATTR_TYPE$4 = qname("", "type", "");
3027
3111
  const ATTR_IDX$6 = qname("", "idx", "");
3028
3112
  const NV_BY_KIND = {
3029
3113
  shape: NAME_NV_SP_PR$4,
3030
- picture: NAME_NV_PIC_PR$1,
3114
+ picture: NAME_NV_PIC_PR$2,
3031
3115
  group: NAME_NV_GRP_SP_PR$3,
3032
3116
  graphicFrame: NAME_NV_GRAPHIC_FRAME_PR$2,
3033
3117
  connector: NAME_NV_CXN_SP_PR$1
@@ -3050,14 +3134,14 @@ const extractShape = (element, kind) => {
3050
3134
  let placeholderType = null;
3051
3135
  let placeholderIdx = null;
3052
3136
  if (nvContainer !== null) {
3053
- const cNvPr = firstChildElement(nvContainer, NAME_C_NV_PR$8);
3137
+ const cNvPr = firstChildElement(nvContainer, NAME_C_NV_PR$9);
3054
3138
  if (cNvPr !== null) {
3055
- const idRaw = getAttrValue(cNvPr, ATTR_ID$12);
3139
+ const idRaw = getAttrValue(cNvPr, ATTR_ID$14);
3056
3140
  if (idRaw !== null) id = Number.parseInt(idRaw, 10);
3057
3141
  const nameRaw = getAttrValue(cNvPr, ATTR_NAME$11);
3058
3142
  if (nameRaw !== null) name = nameRaw;
3059
3143
  }
3060
- const nvPr = firstChildElement(nvContainer, NAME_NV_PR$9);
3144
+ const nvPr = firstChildElement(nvContainer, NAME_NV_PR$10);
3061
3145
  if (nvPr !== null) {
3062
3146
  const ph = firstChildElement(nvPr, NAME_PH$2);
3063
3147
  if (ph !== null) {
@@ -3165,9 +3249,9 @@ const NAME_SLD = qname("p", "sld", NS.pml);
3165
3249
  const NAME_CSLD$2 = qname("p", "cSld", NS.pml);
3166
3250
  const NAME_SP_TREE$2 = qname("p", "spTree", NS.pml);
3167
3251
  const NAME_NV_GRP_SP_PR$2 = qname("p", "nvGrpSpPr", NS.pml);
3168
- const NAME_C_NV_PR$7 = qname("p", "cNvPr", NS.pml);
3252
+ const NAME_C_NV_PR$8 = qname("p", "cNvPr", NS.pml);
3169
3253
  const NAME_C_NV_GRP_SP_PR$2 = qname("p", "cNvGrpSpPr", NS.pml);
3170
- const NAME_NV_PR$8 = qname("p", "nvPr", NS.pml);
3254
+ const NAME_NV_PR$9 = qname("p", "nvPr", NS.pml);
3171
3255
  const NAME_GRP_SP_PR$2 = qname("p", "grpSpPr", NS.pml);
3172
3256
  const NAME_SP$3 = qname("p", "sp", NS.pml);
3173
3257
  const NAME_NV_SP_PR$3 = qname("p", "nvSpPr", NS.pml);
@@ -3179,7 +3263,7 @@ const NAME_BODY_PR$4 = qname("a", "bodyPr", NS.dml);
3179
3263
  const NAME_LST_STYLE$4 = qname("a", "lstStyle", NS.dml);
3180
3264
  const NAME_P$4 = qname("a", "p", NS.dml);
3181
3265
  const NAME_SP_LOCKS$1 = qname("a", "spLocks", NS.dml);
3182
- const ATTR_ID$11 = qname("", "id", "");
3266
+ const ATTR_ID$13 = qname("", "id", "");
3183
3267
  const ATTR_NAME$9 = qname("", "name", "");
3184
3268
  const ATTR_TYPE$2 = qname("", "type", "");
3185
3269
  const ATTR_IDX$5 = qname("", "idx", "");
@@ -3200,7 +3284,7 @@ const buildSlideFromLayout = (layoutSpTree) => {
3200
3284
  if (child.name.namespaceURI !== NS.pml || child.name.localName !== "sp") continue;
3201
3285
  const nvSpPr = firstChildElement(child, NAME_NV_SP_PR$3);
3202
3286
  if (nvSpPr === null) continue;
3203
- const nvPr = firstChildElement(nvSpPr, NAME_NV_PR$8);
3287
+ const nvPr = firstChildElement(nvSpPr, NAME_NV_PR$9);
3204
3288
  if (nvPr === null) continue;
3205
3289
  const ph = firstChildElement(nvPr, NAME_PH$1);
3206
3290
  if (ph === null) continue;
@@ -3240,21 +3324,21 @@ const buildSlideFromLayout = (layoutSpTree) => {
3240
3324
  };
3241
3325
  };
3242
3326
  const buildNvGrpSpPr = (id) => elem(NAME_NV_GRP_SP_PR$2, { children: [
3243
- elem(NAME_C_NV_PR$7, { attrs: [attr(ATTR_ID$11, String(id)), attr(ATTR_NAME$9, "")] }),
3327
+ elem(NAME_C_NV_PR$8, { attrs: [attr(ATTR_ID$13, String(id)), attr(ATTR_NAME$9, "")] }),
3244
3328
  elem(NAME_C_NV_GRP_SP_PR$2),
3245
- elem(NAME_NV_PR$8)
3329
+ elem(NAME_NV_PR$9)
3246
3330
  ] });
3247
3331
  const buildGrpSpPr = () => elem(NAME_GRP_SP_PR$2);
3248
3332
  const buildPlaceholderStub = (id, phType, phIdx) => {
3249
3333
  const phAttrs = [];
3250
3334
  if (phType !== null) phAttrs.push(attr(ATTR_TYPE$2, phType));
3251
3335
  if (phIdx !== null) phAttrs.push(attr(ATTR_IDX$5, phIdx));
3252
- const nvPr = elem(NAME_NV_PR$8, { children: [elem(NAME_PH$1, { attrs: phAttrs })] });
3336
+ const nvPr = elem(NAME_NV_PR$9, { children: [elem(NAME_PH$1, { attrs: phAttrs })] });
3253
3337
  const cNvSpPr = elem(NAME_C_NV_SP_PR$3, { children: [elem(NAME_SP_LOCKS$1, { attrs: [attr(ATTR_NO_GRP$2, "1")] })] });
3254
3338
  const name = inferPlaceholderName(id, phType);
3255
3339
  return elem(NAME_SP$3, { children: [
3256
3340
  elem(NAME_NV_SP_PR$3, { children: [
3257
- elem(NAME_C_NV_PR$7, { attrs: [attr(ATTR_ID$11, String(id)), attr(ATTR_NAME$9, name)] }),
3341
+ elem(NAME_C_NV_PR$8, { attrs: [attr(ATTR_ID$13, String(id)), attr(ATTR_NAME$9, name)] }),
3258
3342
  cNvSpPr,
3259
3343
  nvPr
3260
3344
  ] }),
@@ -3290,14 +3374,14 @@ const inferPlaceholderName = (id, phType) => {
3290
3374
  //#region src/internal/presentationml/text-box-builder.ts
3291
3375
  const NAME_SP$2 = qname("p", "sp", NS.pml);
3292
3376
  const NAME_NV_SP_PR$2 = qname("p", "nvSpPr", NS.pml);
3293
- const NAME_C_NV_PR$6 = qname("p", "cNvPr", NS.pml);
3377
+ const NAME_C_NV_PR$7 = qname("p", "cNvPr", NS.pml);
3294
3378
  const NAME_C_NV_SP_PR$2 = qname("p", "cNvSpPr", NS.pml);
3295
- const NAME_NV_PR$7 = qname("p", "nvPr", NS.pml);
3379
+ const NAME_NV_PR$8 = qname("p", "nvPr", NS.pml);
3296
3380
  const NAME_SP_PR$4 = qname("p", "spPr", NS.pml);
3297
3381
  const NAME_TX_BODY$7 = qname("p", "txBody", NS.pml);
3298
3382
  const NAME_A_XFRM$4 = qname("a", "xfrm", NS.dml);
3299
3383
  const NAME_OFF$6 = qname("a", "off", NS.dml);
3300
- const NAME_EXT$6 = qname("a", "ext", NS.dml);
3384
+ const NAME_EXT$7 = qname("a", "ext", NS.dml);
3301
3385
  const NAME_PRST_GEOM$3 = qname("a", "prstGeom", NS.dml);
3302
3386
  const NAME_AV_LST$3 = qname("a", "avLst", NS.dml);
3303
3387
  const NAME_NO_FILL = qname("a", "noFill", NS.dml);
@@ -3307,7 +3391,7 @@ const NAME_P$3 = qname("a", "p", NS.dml);
3307
3391
  const NAME_R$3 = qname("a", "r", NS.dml);
3308
3392
  const NAME_RPR$3 = qname("a", "rPr", NS.dml);
3309
3393
  const NAME_T$4 = qname("a", "t", NS.dml);
3310
- const ATTR_ID$10 = qname("", "id", "");
3394
+ const ATTR_ID$12 = qname("", "id", "");
3311
3395
  const ATTR_NAME$8 = qname("", "name", "");
3312
3396
  const ATTR_TX_BOX$1 = qname("", "txBox", "");
3313
3397
  const ATTR_X$6 = qname("", "x", "");
@@ -3328,12 +3412,12 @@ NS.xml;
3328
3412
  const buildTextBox = (opts) => {
3329
3413
  const name = opts.name ?? `TextBox ${opts.id}`;
3330
3414
  const nvSpPr = elem(NAME_NV_SP_PR$2, { children: [
3331
- elem(NAME_C_NV_PR$6, { attrs: [attr(ATTR_ID$10, String(opts.id)), attr(ATTR_NAME$8, name)] }),
3415
+ elem(NAME_C_NV_PR$7, { attrs: [attr(ATTR_ID$12, String(opts.id)), attr(ATTR_NAME$8, name)] }),
3332
3416
  elem(NAME_C_NV_SP_PR$2, { attrs: [attr(ATTR_TX_BOX$1, "1")] }),
3333
- elem(NAME_NV_PR$7)
3417
+ elem(NAME_NV_PR$8)
3334
3418
  ] });
3335
3419
  const spPr = elem(NAME_SP_PR$4, { children: [
3336
- elem(NAME_A_XFRM$4, { children: [elem(NAME_OFF$6, { attrs: [attr(ATTR_X$6, String(emuCoordinate(opts.x, "addSlideTextBox: x"))), attr(ATTR_Y$6, String(emuCoordinate(opts.y, "addSlideTextBox: y")))] }), elem(NAME_EXT$6, { attrs: [attr(ATTR_CX$6, String(emuExtent(opts.w, "addSlideTextBox: w"))), attr(ATTR_CY$6, String(emuExtent(opts.h, "addSlideTextBox: h")))] })] }),
3420
+ elem(NAME_A_XFRM$4, { children: [elem(NAME_OFF$6, { attrs: [attr(ATTR_X$6, String(emuCoordinate(opts.x, "addSlideTextBox: x"))), attr(ATTR_Y$6, String(emuCoordinate(opts.y, "addSlideTextBox: y")))] }), elem(NAME_EXT$7, { attrs: [attr(ATTR_CX$6, String(emuExtent(opts.w, "addSlideTextBox: w"))), attr(ATTR_CY$6, String(emuExtent(opts.h, "addSlideTextBox: h")))] })] }),
3337
3421
  elem(NAME_PRST_GEOM$3, {
3338
3422
  attrs: [attr(ATTR_PRST$3, "rect")],
3339
3423
  children: [elem(NAME_AV_LST$3)]
@@ -3358,14 +3442,14 @@ const buildTextBox = (opts) => {
3358
3442
  //#region src/internal/presentationml/shape-builder.ts
3359
3443
  const NAME_SP$1 = qname("p", "sp", NS.pml);
3360
3444
  const NAME_NV_SP_PR$1 = qname("p", "nvSpPr", NS.pml);
3361
- const NAME_C_NV_PR$5 = qname("p", "cNvPr", NS.pml);
3445
+ const NAME_C_NV_PR$6 = qname("p", "cNvPr", NS.pml);
3362
3446
  const NAME_C_NV_SP_PR$1 = qname("p", "cNvSpPr", NS.pml);
3363
- const NAME_NV_PR$6 = qname("p", "nvPr", NS.pml);
3447
+ const NAME_NV_PR$7 = qname("p", "nvPr", NS.pml);
3364
3448
  const NAME_SP_PR$3 = qname("p", "spPr", NS.pml);
3365
3449
  const NAME_TX_BODY$6 = qname("p", "txBody", NS.pml);
3366
3450
  const NAME_A_XFRM$3 = qname("a", "xfrm", NS.dml);
3367
3451
  const NAME_OFF$5 = qname("a", "off", NS.dml);
3368
- const NAME_EXT$5 = qname("a", "ext", NS.dml);
3452
+ const NAME_EXT$6 = qname("a", "ext", NS.dml);
3369
3453
  const NAME_PRST_GEOM$2 = qname("a", "prstGeom", NS.dml);
3370
3454
  const NAME_AV_LST$2 = qname("a", "avLst", NS.dml);
3371
3455
  const NAME_BODY_PR$2 = qname("a", "bodyPr", NS.dml);
@@ -3374,7 +3458,7 @@ const NAME_P$2 = qname("a", "p", NS.dml);
3374
3458
  const NAME_R$2 = qname("a", "r", NS.dml);
3375
3459
  const NAME_RPR$2 = qname("a", "rPr", NS.dml);
3376
3460
  const NAME_T$3 = qname("a", "t", NS.dml);
3377
- const ATTR_ID$9 = qname("", "id", "");
3461
+ const ATTR_ID$11 = qname("", "id", "");
3378
3462
  const ATTR_NAME$7 = qname("", "name", "");
3379
3463
  const ATTR_X$5 = qname("", "x", "");
3380
3464
  const ATTR_Y$5 = qname("", "y", "");
@@ -3406,10 +3490,10 @@ const buildShape = (opts) => {
3406
3490
  const name = opts.name ?? `${opts.preset} ${opts.id}`;
3407
3491
  const anchor = opts.textAnchor ?? "ctr";
3408
3492
  const children = [elem(NAME_NV_SP_PR$1, { children: [
3409
- elem(NAME_C_NV_PR$5, { attrs: [attr(ATTR_ID$9, String(opts.id)), attr(ATTR_NAME$7, name)] }),
3493
+ elem(NAME_C_NV_PR$6, { attrs: [attr(ATTR_ID$11, String(opts.id)), attr(ATTR_NAME$7, name)] }),
3410
3494
  elem(NAME_C_NV_SP_PR$1),
3411
- elem(NAME_NV_PR$6)
3412
- ] }), elem(NAME_SP_PR$3, { children: [elem(NAME_A_XFRM$3, { children: [elem(NAME_OFF$5, { attrs: [attr(ATTR_X$5, String(emuCoordinate(opts.x, "addSlideShape: x"))), attr(ATTR_Y$5, String(emuCoordinate(opts.y, "addSlideShape: y")))] }), elem(NAME_EXT$5, { attrs: [attr(ATTR_CX$5, String(emuExtent(opts.w, "addSlideShape: w"))), attr(ATTR_CY$5, String(emuExtent(opts.h, "addSlideShape: h")))] })] }), elem(NAME_PRST_GEOM$2, {
3495
+ elem(NAME_NV_PR$7)
3496
+ ] }), elem(NAME_SP_PR$3, { children: [elem(NAME_A_XFRM$3, { children: [elem(NAME_OFF$5, { attrs: [attr(ATTR_X$5, String(emuCoordinate(opts.x, "addSlideShape: x"))), attr(ATTR_Y$5, String(emuCoordinate(opts.y, "addSlideShape: y")))] }), elem(NAME_EXT$6, { attrs: [attr(ATTR_CX$5, String(emuExtent(opts.w, "addSlideShape: w"))), attr(ATTR_CY$5, String(emuExtent(opts.h, "addSlideShape: h")))] })] }), elem(NAME_PRST_GEOM$2, {
3413
3497
  attrs: [attr(ATTR_PRST$2, opts.preset)],
3414
3498
  children: [elem(NAME_AV_LST$2)]
3415
3499
  })] })];
@@ -3421,13 +3505,13 @@ const buildShape = (opts) => {
3421
3505
  //#region src/internal/presentationml/connector-builder.ts
3422
3506
  const NAME_CXN_SP = qname("p", "cxnSp", NS.pml);
3423
3507
  const NAME_NV_CXN_SP_PR = qname("p", "nvCxnSpPr", NS.pml);
3424
- const NAME_C_NV_PR$4 = qname("p", "cNvPr", NS.pml);
3508
+ const NAME_C_NV_PR$5 = qname("p", "cNvPr", NS.pml);
3425
3509
  const NAME_C_NV_CXN_SP_PR = qname("p", "cNvCxnSpPr", NS.pml);
3426
- const NAME_NV_PR$5 = qname("p", "nvPr", NS.pml);
3510
+ const NAME_NV_PR$6 = qname("p", "nvPr", NS.pml);
3427
3511
  const NAME_SP_PR$2 = qname("p", "spPr", NS.pml);
3428
3512
  const NAME_A_XFRM$2 = qname("a", "xfrm", NS.dml);
3429
3513
  const NAME_OFF$4 = qname("a", "off", NS.dml);
3430
- const NAME_EXT$4 = qname("a", "ext", NS.dml);
3514
+ const NAME_EXT$5 = qname("a", "ext", NS.dml);
3431
3515
  const NAME_PRST_GEOM$1 = qname("a", "prstGeom", NS.dml);
3432
3516
  const NAME_AV_LST$1 = qname("a", "avLst", NS.dml);
3433
3517
  const NAME_LN = qname("a", "ln", NS.dml);
@@ -3440,7 +3524,7 @@ const NAME_FONT_REF = qname("a", "fontRef", NS.dml);
3440
3524
  const NAME_SCHEME_CLR = qname("a", "schemeClr", NS.dml);
3441
3525
  const ATTR_IDX$4 = qname("", "idx", "");
3442
3526
  const ATTR_VAL$5 = qname("", "val", "");
3443
- const ATTR_ID$8 = qname("", "id", "");
3527
+ const ATTR_ID$10 = qname("", "id", "");
3444
3528
  const ATTR_NAME$6 = qname("", "name", "");
3445
3529
  const ATTR_X$4 = qname("", "x", "");
3446
3530
  const ATTR_Y$4 = qname("", "y", "");
@@ -3454,9 +3538,9 @@ const ATTR_FLIP_V = qname("", "flipV", "");
3454
3538
  const buildConnector = (opts) => {
3455
3539
  const name = opts.name ?? `Straight Connector ${opts.id}`;
3456
3540
  const nvCxnSpPr = elem(NAME_NV_CXN_SP_PR, { children: [
3457
- elem(NAME_C_NV_PR$4, { attrs: [attr(ATTR_ID$8, String(opts.id)), attr(ATTR_NAME$6, name)] }),
3541
+ elem(NAME_C_NV_PR$5, { attrs: [attr(ATTR_ID$10, String(opts.id)), attr(ATTR_NAME$6, name)] }),
3458
3542
  elem(NAME_C_NV_CXN_SP_PR),
3459
- elem(NAME_NV_PR$5)
3543
+ elem(NAME_NV_PR$6)
3460
3544
  ] });
3461
3545
  const x = Math.min(opts.from.x, opts.to.x);
3462
3546
  const y = Math.min(opts.from.y, opts.to.y);
@@ -3469,7 +3553,7 @@ const buildConnector = (opts) => {
3469
3553
  if (flipV) xfrmAttrs.push(attr(ATTR_FLIP_V, "1"));
3470
3554
  const xfrm = elem(NAME_A_XFRM$2, {
3471
3555
  attrs: xfrmAttrs,
3472
- children: [elem(NAME_OFF$4, { attrs: [attr(ATTR_X$4, String(emuCoordinate(x, "addSlideLine: x"))), attr(ATTR_Y$4, String(emuCoordinate(y, "addSlideLine: y")))] }), elem(NAME_EXT$4, { attrs: [attr(ATTR_CX$4, String(emuExtent(cx, "addSlideLine: width"))), attr(ATTR_CY$4, String(emuExtent(cy, "addSlideLine: height")))] })]
3556
+ children: [elem(NAME_OFF$4, { attrs: [attr(ATTR_X$4, String(emuCoordinate(x, "addSlideLine: x"))), attr(ATTR_Y$4, String(emuCoordinate(y, "addSlideLine: y")))] }), elem(NAME_EXT$5, { attrs: [attr(ATTR_CX$4, String(emuExtent(cx, "addSlideLine: width"))), attr(ATTR_CY$4, String(emuExtent(cy, "addSlideLine: height")))] })]
3473
3557
  });
3474
3558
  const prstGeom = elem(NAME_PRST_GEOM$1, {
3475
3559
  attrs: [attr(ATTR_PRST$1, "line")],
@@ -3503,16 +3587,16 @@ const buildConnector = (opts) => {
3503
3587
  //#region src/internal/presentationml/group-builder.ts
3504
3588
  const NAME_GRP_SP = qname("p", "grpSp", NS.pml);
3505
3589
  const NAME_NV_GRP_SP_PR$1 = qname("p", "nvGrpSpPr", NS.pml);
3506
- const NAME_C_NV_PR$3 = qname("p", "cNvPr", NS.pml);
3590
+ const NAME_C_NV_PR$4 = qname("p", "cNvPr", NS.pml);
3507
3591
  const NAME_C_NV_GRP_SP_PR$1 = qname("p", "cNvGrpSpPr", NS.pml);
3508
- const NAME_NV_PR$4 = qname("p", "nvPr", NS.pml);
3592
+ const NAME_NV_PR$5 = qname("p", "nvPr", NS.pml);
3509
3593
  const NAME_GRP_SP_PR$1 = qname("p", "grpSpPr", NS.pml);
3510
3594
  const NAME_A_XFRM$1 = qname("a", "xfrm", NS.dml);
3511
3595
  const NAME_OFF$3 = qname("a", "off", NS.dml);
3512
- const NAME_EXT$3 = qname("a", "ext", NS.dml);
3596
+ const NAME_EXT$4 = qname("a", "ext", NS.dml);
3513
3597
  const NAME_CH_OFF = qname("a", "chOff", NS.dml);
3514
3598
  const NAME_CH_EXT = qname("a", "chExt", NS.dml);
3515
- const ATTR_ID$7 = qname("", "id", "");
3599
+ const ATTR_ID$9 = qname("", "id", "");
3516
3600
  const ATTR_NAME$5 = qname("", "name", "");
3517
3601
  const ATTR_X$3 = qname("", "x", "");
3518
3602
  const ATTR_Y$3 = qname("", "y", "");
@@ -3522,9 +3606,9 @@ const ATTR_CY$3 = qname("", "cy", "");
3522
3606
  const buildGroup = (opts) => {
3523
3607
  const name = opts.name ?? `Group ${opts.id}`;
3524
3608
  const nvGrpSpPr = elem(NAME_NV_GRP_SP_PR$1, { children: [
3525
- elem(NAME_C_NV_PR$3, { attrs: [attr(ATTR_ID$7, String(opts.id)), attr(ATTR_NAME$5, name)] }),
3609
+ elem(NAME_C_NV_PR$4, { attrs: [attr(ATTR_ID$9, String(opts.id)), attr(ATTR_NAME$5, name)] }),
3526
3610
  elem(NAME_C_NV_GRP_SP_PR$1),
3527
- elem(NAME_NV_PR$4)
3611
+ elem(NAME_NV_PR$5)
3528
3612
  ] });
3529
3613
  const x = emuCoordinate(opts.x, "groupShapes: x");
3530
3614
  const y = emuCoordinate(opts.y, "groupShapes: y");
@@ -3534,7 +3618,7 @@ const buildGroup = (opts) => {
3534
3618
  nvGrpSpPr,
3535
3619
  elem(NAME_GRP_SP_PR$1, { children: [elem(NAME_A_XFRM$1, { children: [
3536
3620
  elem(NAME_OFF$3, { attrs: [attr(ATTR_X$3, String(x)), attr(ATTR_Y$3, String(y))] }),
3537
- elem(NAME_EXT$3, { attrs: [attr(ATTR_CX$3, String(cx)), attr(ATTR_CY$3, String(cy))] }),
3621
+ elem(NAME_EXT$4, { attrs: [attr(ATTR_CX$3, String(cx)), attr(ATTR_CY$3, String(cy))] }),
3538
3622
  elem(NAME_CH_OFF, { attrs: [attr(ATTR_X$3, String(x)), attr(ATTR_Y$3, String(y))] }),
3539
3623
  elem(NAME_CH_EXT, { attrs: [attr(ATTR_CX$3, String(cx)), attr(ATTR_CY$3, String(cy))] })
3540
3624
  ] })] }),
@@ -3544,10 +3628,10 @@ const buildGroup = (opts) => {
3544
3628
  //#endregion
3545
3629
  //#region src/internal/presentationml/picture-builder.ts
3546
3630
  const NAME_PIC = qname("p", "pic", NS.pml);
3547
- const NAME_NV_PIC_PR = qname("p", "nvPicPr", NS.pml);
3548
- const NAME_C_NV_PR$2 = qname("p", "cNvPr", NS.pml);
3631
+ const NAME_NV_PIC_PR$1 = qname("p", "nvPicPr", NS.pml);
3632
+ const NAME_C_NV_PR$3 = qname("p", "cNvPr", NS.pml);
3549
3633
  const NAME_C_NV_PIC_PR = qname("p", "cNvPicPr", NS.pml);
3550
- const NAME_NV_PR$3 = qname("p", "nvPr", NS.pml);
3634
+ const NAME_NV_PR$4 = qname("p", "nvPr", NS.pml);
3551
3635
  const NAME_BLIP_FILL = qname("p", "blipFill", NS.pml);
3552
3636
  const NAME_BLIP = qname("a", "blip", NS.dml);
3553
3637
  const NAME_STRETCH = qname("a", "stretch", NS.dml);
@@ -3555,37 +3639,175 @@ const NAME_FILL_RECT = qname("a", "fillRect", NS.dml);
3555
3639
  const NAME_SP_PR$1 = qname("p", "spPr", NS.pml);
3556
3640
  const NAME_A_XFRM = qname("a", "xfrm", NS.dml);
3557
3641
  const NAME_OFF$2 = qname("a", "off", NS.dml);
3558
- const NAME_EXT$2 = qname("a", "ext", NS.dml);
3642
+ const NAME_EXT$3 = qname("a", "ext", NS.dml);
3559
3643
  const NAME_PRST_GEOM = qname("a", "prstGeom", NS.dml);
3560
3644
  const NAME_AV_LST = qname("a", "avLst", NS.dml);
3561
3645
  const NAME_PIC_LOCKS = qname("a", "picLocks", NS.dml);
3562
- const ATTR_ID$6 = qname("", "id", "");
3646
+ const ATTR_ID$8 = qname("", "id", "");
3563
3647
  const ATTR_NAME$4 = qname("", "name", "");
3564
3648
  const ATTR_X$2 = qname("", "x", "");
3565
3649
  const ATTR_Y$2 = qname("", "y", "");
3566
3650
  const ATTR_CX$2 = qname("", "cx", "");
3567
3651
  const ATTR_CY$2 = qname("", "cy", "");
3568
3652
  const ATTR_PRST = qname("", "prst", "");
3569
- const ATTR_R_EMBED = qname("r", "embed", NS.officeDocRels);
3653
+ const ATTR_R_EMBED$1 = qname("r", "embed", NS.officeDocRels);
3570
3654
  const ATTR_NO_CHANGE_ASPECT$1 = qname("", "noChangeAspect", "");
3571
3655
  /** Returns a `<p:pic>` element ready to be appended to a slide's `<p:spTree>`. */
3572
3656
  const buildPicture = (opts) => {
3573
3657
  const name = opts.name ?? `Picture ${opts.id}`;
3574
3658
  const cNvPicPr = elem(NAME_C_NV_PIC_PR, { children: [elem(NAME_PIC_LOCKS, { attrs: opts.lockAspect ?? true ? [attr(ATTR_NO_CHANGE_ASPECT$1, "1")] : [] })] });
3575
3659
  return elem(NAME_PIC, { children: [
3576
- elem(NAME_NV_PIC_PR, { children: [
3577
- elem(NAME_C_NV_PR$2, { attrs: [attr(ATTR_ID$6, String(opts.id)), attr(ATTR_NAME$4, name)] }),
3660
+ elem(NAME_NV_PIC_PR$1, { children: [
3661
+ elem(NAME_C_NV_PR$3, { attrs: [attr(ATTR_ID$8, String(opts.id)), attr(ATTR_NAME$4, name)] }),
3578
3662
  cNvPicPr,
3579
- elem(NAME_NV_PR$3)
3663
+ elem(NAME_NV_PR$4)
3580
3664
  ] }),
3581
- elem(NAME_BLIP_FILL, { children: [elem(NAME_BLIP, { attrs: [attr(ATTR_R_EMBED, opts.rEmbed)] }), elem(NAME_STRETCH, { children: [elem(NAME_FILL_RECT)] })] }),
3582
- elem(NAME_SP_PR$1, { children: [elem(NAME_A_XFRM, { children: [elem(NAME_OFF$2, { attrs: [attr(ATTR_X$2, String(emuCoordinate(opts.x, "addSlideImage: x"))), attr(ATTR_Y$2, String(emuCoordinate(opts.y, "addSlideImage: y")))] }), elem(NAME_EXT$2, { attrs: [attr(ATTR_CX$2, String(emuExtent(opts.w, "addSlideImage: w"))), attr(ATTR_CY$2, String(emuExtent(opts.h, "addSlideImage: h")))] })] }), elem(NAME_PRST_GEOM, {
3665
+ elem(NAME_BLIP_FILL, { children: [elem(NAME_BLIP, { attrs: [attr(ATTR_R_EMBED$1, opts.rEmbed)] }), elem(NAME_STRETCH, { children: [elem(NAME_FILL_RECT)] })] }),
3666
+ elem(NAME_SP_PR$1, { children: [elem(NAME_A_XFRM, { children: [elem(NAME_OFF$2, { attrs: [attr(ATTR_X$2, String(emuCoordinate(opts.x, "addSlideImage: x"))), attr(ATTR_Y$2, String(emuCoordinate(opts.y, "addSlideImage: y")))] }), elem(NAME_EXT$3, { attrs: [attr(ATTR_CX$2, String(emuExtent(opts.w, "addSlideImage: w"))), attr(ATTR_CY$2, String(emuExtent(opts.h, "addSlideImage: h")))] })] }), elem(NAME_PRST_GEOM, {
3583
3667
  attrs: [attr(ATTR_PRST, "rect")],
3584
3668
  children: [elem(NAME_AV_LST)]
3585
3669
  })] })
3586
3670
  ] });
3587
3671
  };
3588
3672
  //#endregion
3673
+ //#region src/internal/presentationml/media-builder.ts
3674
+ const NAME_NV_PIC_PR = qname("p", "nvPicPr", NS.pml);
3675
+ const NAME_C_NV_PR$2 = qname("p", "cNvPr", NS.pml);
3676
+ const NAME_NV_PR$3 = qname("p", "nvPr", NS.pml);
3677
+ const NAME_HLINK_CLICK = qname("a", "hlinkClick", NS.dml);
3678
+ const NAME_VIDEO_FILE = qname("a", "videoFile", NS.dml);
3679
+ const NAME_AUDIO_FILE = qname("a", "audioFile", NS.dml);
3680
+ const NAME_EXT_LST$2 = qname("p", "extLst", NS.pml);
3681
+ const NAME_EXT$2 = qname("p", "ext", NS.pml);
3682
+ const NAME_P14_MEDIA = qname("p14", "media", NS.p14);
3683
+ const NAME_TIMING$2 = qname("p", "timing", NS.pml);
3684
+ const NAME_TN_LST$2 = qname("p", "tnLst", NS.pml);
3685
+ const NAME_PAR$2 = qname("p", "par", NS.pml);
3686
+ const NAME_C_TN$2 = qname("p", "cTn", NS.pml);
3687
+ const NAME_CHILD_TN_LST$2 = qname("p", "childTnLst", NS.pml);
3688
+ const NAME_VIDEO = qname("p", "video", NS.pml);
3689
+ const NAME_AUDIO = qname("p", "audio", NS.pml);
3690
+ const NAME_C_MEDIA_NODE = qname("p", "cMediaNode", NS.pml);
3691
+ const NAME_ST_COND_LST$1 = qname("p", "stCondLst", NS.pml);
3692
+ const NAME_COND$1 = qname("p", "cond", NS.pml);
3693
+ const NAME_TGT_EL$1 = qname("p", "tgtEl", NS.pml);
3694
+ const NAME_SP_TGT$1 = qname("p", "spTgt", NS.pml);
3695
+ const ATTR_R_ID$2 = qname("r", "id", NS.officeDocRels);
3696
+ const ATTR_R_LINK = qname("r", "link", NS.officeDocRels);
3697
+ const ATTR_R_EMBED = qname("r", "embed", NS.officeDocRels);
3698
+ const ATTR_ACTION = qname("", "action", "");
3699
+ const ATTR_URI$2 = qname("", "uri", "");
3700
+ const ATTR_ID$7 = qname("", "id", "");
3701
+ const ATTR_DUR$1 = qname("", "dur", "");
3702
+ const ATTR_RESTART$1 = qname("", "restart", "");
3703
+ const ATTR_NODE_TYPE$1 = qname("", "nodeType", "");
3704
+ const ATTR_VOL = qname("", "vol", "");
3705
+ const ATTR_FILL$1 = qname("", "fill", "");
3706
+ const ATTR_DISPLAY = qname("", "display", "");
3707
+ const ATTR_DELAY$1 = qname("", "delay", "");
3708
+ const ATTR_SPID$1 = qname("", "spid", "");
3709
+ const MEDIA_ACTION = "ppaction://media";
3710
+ const P14_MEDIA_EXT_URI = "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}";
3711
+ const DEFAULT_MEDIA_VOLUME = "80000";
3712
+ /** Returns a media `<p:pic>`; `opts.rEmbed` is the poster image relationship. */
3713
+ const buildMediaPicture = (opts) => {
3714
+ const pic = buildPicture(opts);
3715
+ const nvPicPr = firstChildElement(pic, NAME_NV_PIC_PR);
3716
+ const cNvPr = firstChildElement(nvPicPr, NAME_C_NV_PR$2);
3717
+ const nvPr = firstChildElement(nvPicPr, NAME_NV_PR$3);
3718
+ cNvPr.children.push(elem(NAME_HLINK_CLICK, { attrs: [attr(ATTR_R_ID$2, ""), attr(ATTR_ACTION, MEDIA_ACTION)] }));
3719
+ nvPr.children.push(elem(opts.kind === "video" ? NAME_VIDEO_FILE : NAME_AUDIO_FILE, { attrs: [attr(ATTR_R_LINK, opts.rLink)] }));
3720
+ if (opts.rMedia !== void 0) {
3721
+ const media = elem(NAME_P14_MEDIA, {
3722
+ attrs: [attr(ATTR_R_EMBED, opts.rMedia)],
3723
+ prefixDecls: new Map([["p14", NS.p14]])
3724
+ });
3725
+ const ext = elem(NAME_EXT$2, {
3726
+ attrs: [attr(ATTR_URI$2, P14_MEDIA_EXT_URI)],
3727
+ children: [media]
3728
+ });
3729
+ nvPr.children.push(elem(NAME_EXT_LST$2, { children: [ext] }));
3730
+ }
3731
+ return pic;
3732
+ };
3733
+ /** Returns the `<p:video>` / `<p:audio>` time node that targets shape `spid`. */
3734
+ const buildMediaTimingNode = (kind, spid, cTnId) => {
3735
+ const cTn = elem(NAME_C_TN$2, {
3736
+ attrs: [
3737
+ attr(ATTR_ID$7, String(cTnId)),
3738
+ attr(ATTR_FILL$1, "hold"),
3739
+ attr(ATTR_DISPLAY, "0")
3740
+ ],
3741
+ children: [elem(NAME_ST_COND_LST$1, { children: [elem(NAME_COND$1, { attrs: [attr(ATTR_DELAY$1, "indefinite")] })] })]
3742
+ });
3743
+ const tgtEl = elem(NAME_TGT_EL$1, { children: [elem(NAME_SP_TGT$1, { attrs: [attr(ATTR_SPID$1, String(spid))] })] });
3744
+ const cMediaNode = elem(NAME_C_MEDIA_NODE, {
3745
+ attrs: [attr(ATTR_VOL, DEFAULT_MEDIA_VOLUME)],
3746
+ children: [cTn, tgtEl]
3747
+ });
3748
+ return elem(kind === "video" ? NAME_VIDEO : NAME_AUDIO, { children: [cMediaNode] });
3749
+ };
3750
+ /**
3751
+ * Returns a `<p:timing>` holding only the root time node, with `nodes` as its
3752
+ * children. `nodes` must be non-empty (`<p:childTnLst>` requires a child).
3753
+ */
3754
+ const buildTimingRoot = (nodes) => {
3755
+ return elem(NAME_TIMING$2, { children: [elem(NAME_TN_LST$2, { children: [elem(NAME_PAR$2, { children: [elem(NAME_C_TN$2, {
3756
+ attrs: [
3757
+ attr(ATTR_ID$7, "1"),
3758
+ attr(ATTR_DUR$1, "indefinite"),
3759
+ attr(ATTR_RESTART$1, "never"),
3760
+ attr(ATTR_NODE_TYPE$1, "tmRoot")
3761
+ ],
3762
+ children: [elem(NAME_CHILD_TN_LST$2, { children: [...nodes] })]
3763
+ })] })] })] });
3764
+ };
3765
+ /** `true` for a `<p:video>` / `<p:audio>` time node. */
3766
+ const isMediaTimingNode = (el) => el.name.namespaceURI === NS.pml && (el.name.localName === "video" || el.name.localName === "audio");
3767
+ /** Shape id a media time node targets, or `null` when it has no `<p:spTgt>`. */
3768
+ const mediaTimingNodeTarget = (node) => {
3769
+ const cMediaNode = firstChildElement(node, NAME_C_MEDIA_NODE);
3770
+ const tgtEl = cMediaNode ? firstChildElement(cMediaNode, NAME_TGT_EL$1) : null;
3771
+ const spTgt = tgtEl ? firstChildElement(tgtEl, NAME_SP_TGT$1) : null;
3772
+ const raw = spTgt ? getAttrValue(spTgt, ATTR_SPID$1) : null;
3773
+ if (raw === null) return null;
3774
+ const spid = Number.parseInt(raw, 10);
3775
+ return Number.isFinite(spid) ? spid : null;
3776
+ };
3777
+ const MEDIA_FILE_ELEMENTS = {
3778
+ videoFile: "video",
3779
+ quickTimeFile: "video",
3780
+ audioFile: "audio",
3781
+ wavAudioFile: "audio"
3782
+ };
3783
+ /** Reads the media reference off a `<p:pic>`, or `null` for a plain picture. */
3784
+ const readPictureMediaRef = (pic) => {
3785
+ const nvPicPr = firstChildElement(pic, NAME_NV_PIC_PR);
3786
+ const nvPr = nvPicPr ? firstChildElement(nvPicPr, NAME_NV_PR$3) : null;
3787
+ if (!nvPr) return null;
3788
+ for (const child of nvPr.children) {
3789
+ if (child.kind !== "element" || child.name.namespaceURI !== NS.dml) continue;
3790
+ const kind = MEDIA_FILE_ELEMENTS[child.name.localName];
3791
+ if (kind === void 0) continue;
3792
+ return {
3793
+ kind,
3794
+ fileRId: child.name.localName === "wavAudioFile" ? getAttrValue(child, ATTR_R_EMBED) : getAttrValue(child, ATTR_R_LINK),
3795
+ mediaRId: readP14MediaRId(nvPr)
3796
+ };
3797
+ }
3798
+ return null;
3799
+ };
3800
+ const readP14MediaRId = (nvPr) => {
3801
+ const extLst = firstChildElement(nvPr, NAME_EXT_LST$2);
3802
+ if (!extLst) return null;
3803
+ for (const ext of extLst.children) {
3804
+ if (ext.kind !== "element") continue;
3805
+ const media = firstChildElement(ext, NAME_P14_MEDIA);
3806
+ if (media) return getAttrValue(media, ATTR_R_EMBED);
3807
+ }
3808
+ return null;
3809
+ };
3810
+ //#endregion
3589
3811
  //#region src/internal/presentationml/table-builder.ts
3590
3812
  const TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
3591
3813
  const DEFAULT_TABLE_STYLE_ID = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
@@ -3625,7 +3847,7 @@ const ATTR_MAR_R = qname("", "marR", "");
3625
3847
  const ATTR_MAR_T = qname("", "marT", "");
3626
3848
  const ATTR_MAR_B = qname("", "marB", "");
3627
3849
  const ATTR_INDENT = qname("", "indent", "");
3628
- const ATTR_ID$5 = qname("", "id", "");
3850
+ const ATTR_ID$6 = qname("", "id", "");
3629
3851
  const ATTR_NAME$3 = qname("", "name", "");
3630
3852
  const ATTR_NO_GRP$1 = qname("", "noGrp", "");
3631
3853
  const ATTR_X$1 = qname("", "x", "");
@@ -3701,7 +3923,7 @@ const buildTable = (opts) => {
3701
3923
  if (rowHeights.length !== rows.length) throw new Error(`addSlideTable: rowHeights has ${rowHeights.length} entries; expected ${rows.length}`);
3702
3924
  const name = opts.name ?? `Table ${opts.id}`;
3703
3925
  const nvGraphicFramePr = elem(NAME_NV_GRAPHIC_FRAME_PR$1, { children: [
3704
- elem(NAME_C_NV_PR$1, { attrs: [attr(ATTR_ID$5, String(opts.id)), attr(ATTR_NAME$3, name)] }),
3926
+ elem(NAME_C_NV_PR$1, { attrs: [attr(ATTR_ID$6, String(opts.id)), attr(ATTR_NAME$3, name)] }),
3705
3927
  elem(NAME_C_NV_GRAPHIC_FRAME_PR$1, { children: [elem(NAME_GRAPHIC_FRAME_LOCKS, { attrs: [attr(ATTR_NO_GRP$1, "1")] })] }),
3706
3928
  elem(NAME_NV_PR$2)
3707
3929
  ] });
@@ -3749,7 +3971,7 @@ const NAME_R = qname("a", "r", NS.dml);
3749
3971
  const NAME_RPR = qname("a", "rPr", NS.dml);
3750
3972
  const NAME_T$1 = qname("a", "t", NS.dml);
3751
3973
  const NAME_SP_LOCKS = qname("a", "spLocks", NS.dml);
3752
- const ATTR_ID$4 = qname("", "id", "");
3974
+ const ATTR_ID$5 = qname("", "id", "");
3753
3975
  const ATTR_NAME$2 = qname("", "name", "");
3754
3976
  const ATTR_NO_GRP = qname("", "noGrp", "");
3755
3977
  const ATTR_NO_ROT = qname("", "noRot", "");
@@ -3759,14 +3981,14 @@ const ATTR_IDX$3 = qname("", "idx", "");
3759
3981
  const ATTR_LANG = qname("", "lang", "");
3760
3982
  const buildRootGroup = () => {
3761
3983
  return elem(NAME_NV_GRP_SP_PR, { children: [
3762
- elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$4, "1"), attr(ATTR_NAME$2, "")] }),
3984
+ elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$5, "1"), attr(ATTR_NAME$2, "")] }),
3763
3985
  elem(NAME_C_NV_GRP_SP_PR),
3764
3986
  elem(NAME_NV_PR$1)
3765
3987
  ] });
3766
3988
  };
3767
3989
  const buildSldImgPlaceholder = (id) => {
3768
3990
  return elem(NAME_SP, { children: [elem(NAME_NV_SP_PR, { children: [
3769
- elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$4, String(id)), attr(ATTR_NAME$2, `Slide Image Placeholder ${id - 1}`)] }),
3991
+ elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$5, String(id)), attr(ATTR_NAME$2, `Slide Image Placeholder ${id - 1}`)] }),
3770
3992
  elem(NAME_C_NV_SP_PR, { children: [elem(NAME_SP_LOCKS, { attrs: [
3771
3993
  attr(ATTR_NO_GRP, "1"),
3772
3994
  attr(ATTR_NO_ROT, "1"),
@@ -3783,7 +4005,7 @@ const buildNotesParagraphs = (notes) => {
3783
4005
  };
3784
4006
  const buildNotesBodyPlaceholder = (id, notes) => {
3785
4007
  const nvSpPr = elem(NAME_NV_SP_PR, { children: [
3786
- elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$4, String(id)), attr(ATTR_NAME$2, `Notes Placeholder ${id - 1}`)] }),
4008
+ elem(NAME_C_NV_PR, { attrs: [attr(ATTR_ID$5, String(id)), attr(ATTR_NAME$2, `Notes Placeholder ${id - 1}`)] }),
3787
4009
  elem(NAME_C_NV_SP_PR, { children: [elem(NAME_SP_LOCKS, { attrs: [attr(ATTR_NO_GRP, "1")] })] }),
3788
4010
  elem(NAME_NV_PR$1, { children: [elem(NAME_PH, { attrs: [attr(ATTR_TYPE$1, "body"), attr(ATTR_IDX$3, "1")] })] })
3789
4011
  ] });
@@ -3924,11 +4146,11 @@ const buildTransition = (opts) => {
3924
4146
  };
3925
4147
  //#endregion
3926
4148
  //#region src/internal/presentationml/animation-builder.ts
3927
- const NAME_TIMING = qname("p", "timing", NS.pml);
3928
- const NAME_TN_LST = qname("p", "tnLst", NS.pml);
3929
- const NAME_PAR = qname("p", "par", NS.pml);
3930
- const NAME_C_TN = qname("p", "cTn", NS.pml);
3931
- const NAME_CHILD_TN_LST = qname("p", "childTnLst", NS.pml);
4149
+ const NAME_TIMING$1 = qname("p", "timing", NS.pml);
4150
+ const NAME_TN_LST$1 = qname("p", "tnLst", NS.pml);
4151
+ const NAME_PAR$1 = qname("p", "par", NS.pml);
4152
+ const NAME_C_TN$1 = qname("p", "cTn", NS.pml);
4153
+ const NAME_CHILD_TN_LST$1 = qname("p", "childTnLst", NS.pml);
3932
4154
  const NAME_SEQ = qname("p", "seq", NS.pml);
3933
4155
  const NAME_ST_COND_LST = qname("p", "stCondLst", NS.pml);
3934
4156
  const NAME_PREV_COND_LST = qname("p", "prevCondLst", NS.pml);
@@ -3950,7 +4172,7 @@ const NAME_TAV_LST = qname("p", "tavLst", NS.pml);
3950
4172
  const NAME_TAV = qname("p", "tav", NS.pml);
3951
4173
  const NAME_BLD_LST = qname("p", "bldLst", NS.pml);
3952
4174
  const NAME_BLD_P = qname("p", "bldP", NS.pml);
3953
- const ATTR_ID$3 = qname("", "id", "");
4175
+ const ATTR_ID$4 = qname("", "id", "");
3954
4176
  const ATTR_DUR = qname("", "dur", "");
3955
4177
  const ATTR_RESTART = qname("", "restart", "");
3956
4178
  const ATTR_NODE_TYPE = qname("", "nodeType", "");
@@ -3998,9 +4220,9 @@ const buildSetVisibility = (spid, visible) => {
3998
4220
  data: "style.visibility"
3999
4221
  }] })] });
4000
4222
  return elem(NAME_SET, { children: [elem(NAME_C_BHVR, { children: [
4001
- elem(NAME_C_TN, {
4223
+ elem(NAME_C_TN$1, {
4002
4224
  attrs: [
4003
- attr(ATTR_ID$3, "6"),
4225
+ attr(ATTR_ID$4, "6"),
4004
4226
  attr(ATTR_DUR, "1"),
4005
4227
  attr(ATTR_FILL, "hold")
4006
4228
  ],
@@ -4016,8 +4238,8 @@ const buildOpacityAnim = (spid, durationMs, fadeIn) => {
4016
4238
  kind: "text",
4017
4239
  data: "style.opacity"
4018
4240
  }] })] });
4019
- const cTn = elem(NAME_C_TN, { attrs: [
4020
- attr(ATTR_ID$3, "7"),
4241
+ const cTn = elem(NAME_C_TN$1, { attrs: [
4242
+ attr(ATTR_ID$4, "7"),
4021
4243
  attr(ATTR_DUR, String(durationMs)),
4022
4244
  attr(ATTR_FILL, "hold")
4023
4245
  ] });
@@ -4055,9 +4277,9 @@ const buildSingleEffectTiming = (spid, opts) => {
4055
4277
  const effectChildren = [];
4056
4278
  effectChildren.push(buildSetVisibility(spid, isEntrance));
4057
4279
  if (isFade) effectChildren.push(buildOpacityAnim(spid, duration, isEntrance));
4058
- const effectPar = elem(NAME_PAR, { children: [elem(NAME_C_TN, {
4280
+ const effectPar = elem(NAME_PAR$1, { children: [elem(NAME_C_TN$1, {
4059
4281
  attrs: [
4060
- attr(ATTR_ID$3, "5"),
4282
+ attr(ATTR_ID$4, "5"),
4061
4283
  attr(ATTR_PRESET_ID, String(preset.presetId)),
4062
4284
  attr(ATTR_PRESET_CLASS, preset.presetClass),
4063
4285
  attr(ATTR_PRESET_SUBTYPE, String(preset.presetSubtype)),
@@ -4065,23 +4287,23 @@ const buildSingleEffectTiming = (spid, opts) => {
4065
4287
  attr(ATTR_GRP_ID, "0"),
4066
4288
  attr(ATTR_NODE_TYPE, "clickEffect")
4067
4289
  ],
4068
- children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "0")] })] }), elem(NAME_CHILD_TN_LST, { children: effectChildren })]
4290
+ children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "0")] })] }), elem(NAME_CHILD_TN_LST$1, { children: effectChildren })]
4069
4291
  })] });
4070
- const clickWrapperPar = elem(NAME_PAR, { children: [elem(NAME_C_TN, {
4071
- attrs: [attr(ATTR_ID$3, "4"), attr(ATTR_FILL, "hold")],
4072
- children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "0")] })] }), elem(NAME_CHILD_TN_LST, { children: [effectPar] })]
4292
+ const clickWrapperPar = elem(NAME_PAR$1, { children: [elem(NAME_C_TN$1, {
4293
+ attrs: [attr(ATTR_ID$4, "4"), attr(ATTR_FILL, "hold")],
4294
+ children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "0")] })] }), elem(NAME_CHILD_TN_LST$1, { children: [effectPar] })]
4073
4295
  })] });
4074
- const indefinitePar = elem(NAME_PAR, { children: [elem(NAME_C_TN, {
4075
- attrs: [attr(ATTR_ID$3, "3"), attr(ATTR_FILL, "hold")],
4076
- children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "indefinite")] })] }), elem(NAME_CHILD_TN_LST, { children: [clickWrapperPar] })]
4296
+ const indefinitePar = elem(NAME_PAR$1, { children: [elem(NAME_C_TN$1, {
4297
+ attrs: [attr(ATTR_ID$4, "3"), attr(ATTR_FILL, "hold")],
4298
+ children: [elem(NAME_ST_COND_LST, { children: [elem(NAME_COND, { attrs: [attr(ATTR_DELAY, "indefinite")] })] }), elem(NAME_CHILD_TN_LST$1, { children: [clickWrapperPar] })]
4077
4299
  })] });
4078
- const mainSeqCTn = elem(NAME_C_TN, {
4300
+ const mainSeqCTn = elem(NAME_C_TN$1, {
4079
4301
  attrs: [
4080
- attr(ATTR_ID$3, "2"),
4302
+ attr(ATTR_ID$4, "2"),
4081
4303
  attr(ATTR_DUR, "indefinite"),
4082
4304
  attr(ATTR_NODE_TYPE, "mainSeq")
4083
4305
  ],
4084
- children: [elem(NAME_CHILD_TN_LST, { children: [indefinitePar] })]
4306
+ children: [elem(NAME_CHILD_TN_LST$1, { children: [indefinitePar] })]
4085
4307
  });
4086
4308
  const prevCond = elem(NAME_PREV_COND_LST, { children: [elem(NAME_COND, {
4087
4309
  attrs: [attr(ATTR_EVT, "onPrev"), attr(ATTR_DELAY, "0")],
@@ -4099,14 +4321,14 @@ const buildSingleEffectTiming = (spid, opts) => {
4099
4321
  nextCond
4100
4322
  ]
4101
4323
  });
4102
- return elem(NAME_TIMING, { children: [elem(NAME_TN_LST, { children: [elem(NAME_PAR, { children: [elem(NAME_C_TN, {
4324
+ return elem(NAME_TIMING$1, { children: [elem(NAME_TN_LST$1, { children: [elem(NAME_PAR$1, { children: [elem(NAME_C_TN$1, {
4103
4325
  attrs: [
4104
- attr(ATTR_ID$3, "1"),
4326
+ attr(ATTR_ID$4, "1"),
4105
4327
  attr(ATTR_DUR, "indefinite"),
4106
4328
  attr(ATTR_RESTART, "never"),
4107
4329
  attr(ATTR_NODE_TYPE, "tmRoot")
4108
4330
  ],
4109
- children: [elem(NAME_CHILD_TN_LST, { children: [seq] })]
4331
+ children: [elem(NAME_CHILD_TN_LST$1, { children: [seq] })]
4110
4332
  })] })] }), elem(NAME_BLD_LST, { children: [elem(NAME_BLD_P, { attrs: [attr(ATTR_SPID, String(spid)), attr(ATTR_GRP_ID, "0")] })] })] });
4111
4333
  };
4112
4334
  //#endregion
@@ -4117,7 +4339,7 @@ const NAME_CM_LST = qname("p", "cmLst", NS.pml);
4117
4339
  const NAME_CM = qname("p", "cm", NS.pml);
4118
4340
  const NAME_POS = qname("p", "pos", NS.pml);
4119
4341
  const NAME_TEXT = qname("p", "text", NS.pml);
4120
- const ATTR_ID$2 = qname("", "id", "");
4342
+ const ATTR_ID$3 = qname("", "id", "");
4121
4343
  const ATTR_NAME$1 = qname("", "name", "");
4122
4344
  const ATTR_INITIALS = qname("", "initials", "");
4123
4345
  const ATTR_LAST_IDX = qname("", "lastIdx", "");
@@ -4131,7 +4353,7 @@ const readCommentAuthorList = (root) => {
4131
4353
  if (root.name.namespaceURI !== NS.pml || root.name.localName !== "cmAuthorLst") throw new Error(`expected <p:cmAuthorLst> root, got <${root.name.prefix}:${root.name.localName}>`);
4132
4354
  const authors = [];
4133
4355
  for (const el of allChildElements(root, NAME_CM_AUTHOR)) {
4134
- const idRaw = getAttrValue(el, ATTR_ID$2);
4356
+ const idRaw = getAttrValue(el, ATTR_ID$3);
4135
4357
  const nameVal = getAttrValue(el, ATTR_NAME$1);
4136
4358
  const initialsVal = getAttrValue(el, ATTR_INITIALS);
4137
4359
  const lastIdxRaw = getAttrValue(el, ATTR_LAST_IDX);
@@ -4191,7 +4413,7 @@ const readCommentList = (root) => {
4191
4413
  };
4192
4414
  const commentAuthorElement = (a) => {
4193
4415
  return elem(NAME_CM_AUTHOR, { attrs: [
4194
- attr(ATTR_ID$2, String(a.id)),
4416
+ attr(ATTR_ID$3, String(a.id)),
4195
4417
  attr(ATTR_NAME$1, a.name),
4196
4418
  attr(ATTR_INITIALS, a.initials),
4197
4419
  attr(ATTR_LAST_IDX, String(a.lastIdx)),
@@ -4255,7 +4477,7 @@ const NAME_SLD_ID_LST$1 = qname("p", "sldIdLst", NS.pml);
4255
4477
  const NAME_SLD_ID$1 = qname("p", "sldId", NS.pml);
4256
4478
  const NAME_CSLD = qname("p", "cSld", NS.pml);
4257
4479
  const NAME_SP_TREE = qname("p", "spTree", NS.pml);
4258
- const ATTR_ID$1 = qname("", "id", "");
4480
+ const ATTR_ID$2 = qname("", "id", "");
4259
4481
  const ATTR_R_ID$1 = qname("r", "id", NS.officeDocRels);
4260
4482
  const SLD_ID_MAX = 2147482623;
4261
4483
  const commitSlideData = (slide) => {
@@ -5159,6 +5381,136 @@ const setShapeClickAction = (shape, action) => {
5159
5381
  commitAndRefresh(shape);
5160
5382
  };
5161
5383
  //#endregion
5384
+ //#region src/internal/chartml/embedded-xlsx.ts
5385
+ const TEXT_ENCODER = new TextEncoder();
5386
+ const encode = (s) => TEXT_ENCODER.encode(s);
5387
+ const xmlEscape = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5388
+ const colLetter = (col) => {
5389
+ let n = col;
5390
+ let out = "";
5391
+ while (true) {
5392
+ out = String.fromCharCode(65 + n % 26) + out;
5393
+ if (n < 26) return out;
5394
+ n = Math.floor(n / 26) - 1;
5395
+ }
5396
+ };
5397
+ const cellRef = (row, col) => `${colLetter(col)}${row + 1}`;
5398
+ /**
5399
+ * Builds the bytes of a fresh xlsx whose only sheet holds `grid`, row by
5400
+ * row from A1. Which cell means what is the caller's business — see
5401
+ * `layoutChartSheet`, which also produces the `<c:f>` formulas that point
5402
+ * back into this grid.
5403
+ */
5404
+ const buildEmbeddedXlsx = (grid) => {
5405
+ const sheetXmlParts = [];
5406
+ sheetXmlParts.push("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">", "<sheetData>");
5407
+ grid.forEach((row, r) => {
5408
+ sheetXmlParts.push(`<row r="${r + 1}">`);
5409
+ row.forEach((cell, col) => {
5410
+ if (cell === null) return;
5411
+ sheetXmlParts.push(typeof cell === "number" ? `<c r="${cellRef(r, col)}"><v>${cell}</v></c>` : `<c r="${cellRef(r, col)}" t="inlineStr"><is><t>${xmlEscape(cell)}</t></is></c>`);
5412
+ });
5413
+ sheetXmlParts.push("</row>");
5414
+ });
5415
+ sheetXmlParts.push("</sheetData></worksheet>");
5416
+ const sheetXml = sheetXmlParts.join("");
5417
+ return writeZip([
5418
+ {
5419
+ name: "[Content_Types].xml",
5420
+ data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/><Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/></Types>")
5421
+ },
5422
+ {
5423
+ name: "_rels/.rels",
5424
+ data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/></Relationships>")
5425
+ },
5426
+ {
5427
+ name: "xl/workbook.xml",
5428
+ data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>")
5429
+ },
5430
+ {
5431
+ name: "xl/_rels/workbook.xml.rels",
5432
+ data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/></Relationships>")
5433
+ },
5434
+ {
5435
+ name: "xl/worksheets/sheet1.xml",
5436
+ data: encode(sheetXml)
5437
+ }
5438
+ ]);
5439
+ };
5440
+ /**
5441
+ * Returns the spreadsheet-cell reference span used by chart `<c:f>`
5442
+ * formulas. Example: `cellRange('Sheet1', 1, 0, 4)` →
5443
+ * `"Sheet1!$A$2:$A$5"` (column A, rows 2–5 inclusive, 0-indexed input).
5444
+ */
5445
+ const cellRange = (sheet, startRow, col, count, endCol = col) => `${sheet}!$${colLetter(col)}$${startRow + 1}:$${colLetter(endCol)}$${startRow + count}`;
5446
+ /** Single-cell reference, e.g. `cellAddr('Sheet1', 0, 1)` → `"Sheet1!$B$1"`. */
5447
+ const cellAddr = (sheet, row, col) => `${sheet}!$${colLetter(col)}$${row + 1}`;
5448
+ //#endregion
5449
+ //#region src/internal/chartml/sheet-layout.ts
5450
+ const SHEET = "Sheet1";
5451
+ const isXyKind = (spec) => spec.kind === "scatter" || spec.kind === "bubble";
5452
+ /** Parses a date-axis category; the caller has validated it is numeric. */
5453
+ const dateSerial = (category) => Number(category);
5454
+ const layoutCategorySheet = (spec) => {
5455
+ const outerLevels = [...spec.categoryGroupLevels ?? []].reverse();
5456
+ const levelCount = outerLevels.length + 1;
5457
+ const rowCount = spec.categories.length;
5458
+ const isDateAxis = spec.categoryAxisDate !== void 0;
5459
+ const grid = [[...Array.from({ length: levelCount }, () => ""), ...spec.series.map((s) => s.name)]];
5460
+ for (let r = 0; r < rowCount; r++) {
5461
+ const category = spec.categories[r] ?? "";
5462
+ const row = outerLevels.map((level) => {
5463
+ const label = level[r] ?? "";
5464
+ return label === "" ? null : label;
5465
+ });
5466
+ row.push(isDateAxis ? dateSerial(category) : category);
5467
+ for (const s of spec.series) row.push(s.values[r] ?? null);
5468
+ grid.push(row);
5469
+ }
5470
+ return {
5471
+ grid,
5472
+ categories: cellRange(SHEET, 1, 0, rowCount, levelCount - 1),
5473
+ series: spec.series.map((_, i) => ({
5474
+ name: cellAddr(SHEET, 0, levelCount + i),
5475
+ values: cellRange(SHEET, 1, levelCount + i, rowCount)
5476
+ }))
5477
+ };
5478
+ };
5479
+ const layoutXySheet = (spec) => {
5480
+ const isBubble = spec.kind === "bubble";
5481
+ const stride = isBubble ? 3 : 2;
5482
+ const rowCount = Math.max(0, ...spec.series.map((s) => Math.max(s.values.length, s.xValues?.length ?? 0, s.bubbleSizes?.length ?? 0)));
5483
+ const header = [];
5484
+ for (const s of spec.series) {
5485
+ header.push("X", s.name);
5486
+ if (isBubble) header.push("Size");
5487
+ }
5488
+ const grid = [header];
5489
+ for (let r = 0; r < rowCount; r++) {
5490
+ const row = [];
5491
+ for (const s of spec.series) {
5492
+ row.push(s.xValues?.[r] ?? null, s.values[r] ?? null);
5493
+ if (isBubble) row.push(s.bubbleSizes?.[r] ?? null);
5494
+ }
5495
+ grid.push(row);
5496
+ }
5497
+ return {
5498
+ grid,
5499
+ series: spec.series.map((s, i) => {
5500
+ const base = i * stride;
5501
+ const pointCount = s.values.length;
5502
+ return {
5503
+ name: cellAddr(SHEET, 0, base + 1),
5504
+ xValues: cellRange(SHEET, 1, base, pointCount),
5505
+ values: cellRange(SHEET, 1, base + 1, pointCount),
5506
+ ...isBubble ? { bubbleSizes: cellRange(SHEET, 1, base + 2, pointCount) } : {}
5507
+ };
5508
+ })
5509
+ };
5510
+ };
5511
+ /** Lays `spec` out as a sheet grid plus the formulas that address it. */
5512
+ const layoutChartSheet = (spec) => isXyKind(spec) ? layoutXySheet(spec) : layoutCategorySheet(spec);
5513
+ //#endregion
5162
5514
  //#region src/internal/chartml/chart-builder.ts
5163
5515
  const NS_C$1 = NS.chart;
5164
5516
  const NS_A$1 = NS.dml;
@@ -5177,20 +5529,21 @@ const strRef = (formula, points) => {
5177
5529
  const strCache = elem(c("strCache"), { children: [valNode(c("ptCount"), points.length), ...points.map((p, i) => ptNode(i, p))] });
5178
5530
  return elem(c("strRef"), { children: [elem(c("f"), { children: [text(formula)] }), strCache] });
5179
5531
  };
5180
- const numRef = (formula, points) => {
5181
- const numCache = elem(c("numCache"), { children: [
5182
- elem(c("formatCode"), { children: [text("General")] }),
5183
- valNode(c("ptCount"), points.length),
5184
- ...points.map((v, i) => v === null ? null : ptNode(i, String(v))).filter((n) => n !== null)
5185
- ] });
5186
- return elem(c("numRef"), { children: [elem(c("f"), { children: [text(formula)] }), numCache] });
5187
- };
5188
- const solidFillSpPr = (color) => {
5189
- const srgbClr = elem(a("srgbClr"), { attrs: [attr(qname("", "val", ""), color.replace(/^#/, "").toUpperCase())] });
5190
- const solidFill = elem(a("solidFill"), { children: [srgbClr] });
5191
- return elem(c("spPr"), { children: [solidFill] });
5192
- };
5193
- const lineSpPr = (color, widthEmu, field) => {
5532
+ const numDataChildren = (points, formatCode) => [
5533
+ elem(c("formatCode"), { children: [text(formatCode)] }),
5534
+ valNode(c("ptCount"), points.length),
5535
+ ...points.map((v, i) => v === null ? null : ptNode(i, String(v))).filter((n) => n !== null)
5536
+ ];
5537
+ const numRef = (formula, points, formatCode = "General") => elem(c("numRef"), { children: [elem(c("f"), { children: [text(formula)] }), elem(c("numCache"), { children: numDataChildren(points, formatCode) })] });
5538
+ const multiLvlStrRef = (formula, levels, pointCount) => elem(c("multiLvlStrRef"), { children: [elem(c("f"), { children: [text(formula)] }), elem(c("multiLvlStrCache"), { children: [valNode(c("ptCount"), pointCount), ...levels.map((level, depth) => elem(c("lvl"), { children: level.map((label, i) => depth > 0 && label === "" ? null : ptNode(i, label)).filter((n) => n !== null) }))] })] });
5539
+ const hexOf = (color) => color.replace(/^#/, "").toUpperCase();
5540
+ const solidFill = (color, opacity) => elem(a("solidFill"), { children: [elem(a("srgbClr"), {
5541
+ attrs: [attr(ATTR_VAL$1, hexOf(color))],
5542
+ children: opacity !== void 0 ? [valNode(a("alpha"), boundedInt(opacity * 1e5, "percent100000", "chart series: fillOpacity"))] : []
5543
+ })] });
5544
+ const solidFillSpPr = (color, opacity) => elem(c("spPr"), { children: [solidFill(color, opacity)] });
5545
+ const lineSpPr = (color, widthEmu, field, hidden = false) => {
5546
+ if (hidden) return elem(c("spPr"), { children: [elem(a("ln"), { children: [elem(a("noFill"))] })] });
5194
5547
  if (color === void 0 && widthEmu === void 0) return null;
5195
5548
  const ln = elem(a("ln"), {
5196
5549
  attrs: widthEmu !== void 0 ? [attr(qname("", "w", ""), String(lineWidthEmu(widthEmu, field)))] : [],
@@ -5216,14 +5569,14 @@ const DEFAULT_ACCENT_COLORS = [
5216
5569
  "5B9BD5",
5217
5570
  "70AD47"
5218
5571
  ];
5219
- const seriesSpPr = (color, lineColor, lineWidthEmu$1, lineDash) => {
5220
- const lnChildren = [elem(a("solidFill"), { children: [elem(a("srgbClr"), { attrs: [attr(qname("", "val", ""), lineColor)] })] })];
5221
- if (lineDash !== void 0) lnChildren.push(elem(a("prstDash"), { attrs: [attr(qname("", "val", ""), lineDash)] }));
5572
+ const seriesSpPr = (color, lineColor, lineWidthEmu$1, lineDash, fillOpacity) => {
5573
+ const lnChildren = [lineColor === null ? elem(a("noFill")) : solidFill(lineColor)];
5574
+ if (lineColor !== null && lineDash !== void 0) lnChildren.push(elem(a("prstDash"), { attrs: [attr(qname("", "val", ""), lineDash)] }));
5222
5575
  const ln = lineWidthEmu$1 !== void 0 ? elem(a("ln"), {
5223
5576
  attrs: [attr(qname("", "w", ""), String(lineWidthEmu(lineWidthEmu$1, "chart series: lineWidthEmu")))],
5224
5577
  children: lnChildren
5225
5578
  }) : elem(a("ln"), { children: lnChildren });
5226
- return elem(c("spPr"), { children: [elem(a("solidFill"), { children: [elem(a("srgbClr"), { attrs: [attr(qname("", "val", ""), color)] })] }), ln] });
5579
+ return elem(c("spPr"), { children: [solidFill(color, fillOpacity), ln] });
5227
5580
  };
5228
5581
  const markerElement = (symbol, sizePt, color, lineColor) => {
5229
5582
  const children = [];
@@ -5235,7 +5588,7 @@ const markerElement = (symbol, sizePt, color, lineColor) => {
5235
5588
  }
5236
5589
  return elem(c("marker"), { children });
5237
5590
  };
5238
- const dPtElements = (colors, explosions) => {
5591
+ const dPtElements = (colors, explosions, fillOpacity, bubble3D) => {
5239
5592
  const out = [];
5240
5593
  const colorLen = colors?.length ?? 0;
5241
5594
  const explLen = explosions?.length ?? 0;
@@ -5244,12 +5597,9 @@ const dPtElements = (colors, explosions) => {
5244
5597
  const color = colors?.[i] ?? null;
5245
5598
  const expl = explosions?.[i] ?? null;
5246
5599
  if (color === null && (expl === null || !Number.isFinite(expl))) continue;
5247
- const children = [valNode(c("idx"), i), valNode(c("bubble3D"), "0")];
5600
+ const children = [valNode(c("idx"), i), valNode(c("bubble3D"), bubble3D ? "1" : "0")];
5248
5601
  if (expl !== null) children.push(valNode(c("explosion"), Math.round(expl)));
5249
- if (color !== null) {
5250
- const hex = color.replace(/^#/, "").toUpperCase();
5251
- children.push(solidFillSpPr(hex));
5252
- }
5602
+ if (color !== null) children.push(solidFillSpPr(color, fillOpacity));
5253
5603
  out.push(elem(c("dPt"), { children }));
5254
5604
  }
5255
5605
  return out;
@@ -5271,39 +5621,121 @@ const trendlineElement = (tl) => {
5271
5621
  if (tl.displayEquation) children.push(valNode(c("dispEq"), "1"));
5272
5622
  return elem(c("trendline"), { children });
5273
5623
  };
5274
- const seriesElement = (spec, seriesIdx, sheet) => {
5624
+ const errBarsElement = (bars, direction) => {
5625
+ const children = [];
5626
+ if (direction !== null) children.push(valNode(c("errDir"), direction));
5627
+ children.push(valNode(c("errBarType"), bars.barType), valNode(c("errValType"), bars.amount.type));
5628
+ if (bars.noEndCap !== void 0) children.push(valNode(c("noEndCap"), bars.noEndCap ? "1" : "0"));
5629
+ if (bars.amount.type === "cust") {
5630
+ const literal = (name, points) => elem(c(name), { children: [elem(c("numLit"), { children: numDataChildren(points, "General") })] });
5631
+ if (bars.amount.plus !== void 0) children.push(literal("plus", bars.amount.plus));
5632
+ if (bars.amount.minus !== void 0) children.push(literal("minus", bars.amount.minus));
5633
+ } else if (bars.amount.type !== "stdErr") children.push(valNode(c("val"), bars.amount.value));
5634
+ const spPr = lineSpPr(bars.color, bars.lineWidthEmu, "chart series: errorBars.lineWidthEmu");
5635
+ if (spPr !== null) children.push(spPr);
5636
+ return elem(c("errBars"), { children });
5637
+ };
5638
+ const SERIES_SHAPE = {
5639
+ bar: "bar",
5640
+ column: "bar",
5641
+ line: "line",
5642
+ stock: "line",
5643
+ area: "area",
5644
+ pie: "pie",
5645
+ doughnut: "pie",
5646
+ scatter: "scatter",
5647
+ bubble: "bubble",
5648
+ radar: "radar",
5649
+ surface: "surface"
5650
+ };
5651
+ const SHAPES_WITH_MARKER = new Set([
5652
+ "line",
5653
+ "scatter",
5654
+ "radar"
5655
+ ]);
5656
+ const SHAPES_WITH_TRENDLINE = new Set([
5657
+ "bar",
5658
+ "line",
5659
+ "area",
5660
+ "scatter",
5661
+ "bubble"
5662
+ ]);
5663
+ const SHAPES_WITH_ERR_BARS = SHAPES_WITH_TRENDLINE;
5664
+ const SHAPES_WITH_INVERT = new Set(["bar", "bubble"]);
5665
+ const SCATTER_STYLES_WITH_LINE = new Set([
5666
+ "line",
5667
+ "lineMarker",
5668
+ "smooth",
5669
+ "smoothMarker"
5670
+ ]);
5671
+ const SCATTER_STYLES_WITH_MARKER = new Set([
5672
+ "marker",
5673
+ "lineMarker",
5674
+ "smoothMarker"
5675
+ ]);
5676
+ const categoryChannel = (spec, formula) => {
5677
+ if (spec.categoryAxisDate !== void 0) return elem(c("cat"), { children: [numRef(formula, spec.categories.map(dateSerial), spec.categoryAxisNumberFormat ?? "General")] });
5678
+ if (spec.categoryGroupLevels !== void 0 && spec.categoryGroupLevels.length > 0) return elem(c("cat"), { children: [multiLvlStrRef(formula, [spec.categories, ...spec.categoryGroupLevels], spec.categories.length)] });
5679
+ return elem(c("cat"), { children: [strRef(formula, spec.categories)] });
5680
+ };
5681
+ const padTo = (values, length) => Array.from({ length }, (_, i) => values?.[i] ?? null);
5682
+ const seriesElement = (spec, seriesIdx, layout) => {
5275
5683
  const series = spec.series[seriesIdx];
5276
- if (!series) throw new Error("seriesElement: out of range");
5277
- const headerCellFormula = `${sheet}!$${String.fromCharCode(66 + seriesIdx)}$1`;
5278
- const catRange = `${sheet}!$A$2:$A$${spec.categories.length + 1}`;
5279
- const valRange = `${sheet}!$${String.fromCharCode(66 + seriesIdx)}$2:$${String.fromCharCode(66 + seriesIdx)}$${spec.categories.length + 1}`;
5280
- const color = series.color !== void 0 ? series.color.replace(/^#/, "").toUpperCase() : DEFAULT_ACCENT_COLORS[seriesIdx % DEFAULT_ACCENT_COLORS.length] ?? "4472C4";
5281
- const paddedValues = [];
5282
- for (let i = 0; i < spec.categories.length; i++) paddedValues.push(i < series.values.length ? series.values[i] ?? null : null);
5684
+ const refs = layout.series[seriesIdx];
5685
+ if (!series || !refs) throw new Error("seriesElement: out of range");
5686
+ const color = series.color !== void 0 ? hexOf(series.color) : DEFAULT_ACCENT_COLORS[seriesIdx % DEFAULT_ACCENT_COLORS.length] ?? "4472C4";
5283
5687
  const kind = series.chartKind ?? spec.kind;
5688
+ const shape = SERIES_SHAPE[kind];
5284
5689
  const children = [
5285
5690
  valNode(c("idx"), seriesIdx),
5286
5691
  valNode(c("order"), seriesIdx),
5287
- elem(c("tx"), { children: [strRef(headerCellFormula, [series.name])] })
5692
+ elem(c("tx"), { children: [strRef(refs.name, [series.name])] })
5288
5693
  ];
5289
- if (kind === "line" || series.lineWidthEmu !== void 0 || series.lineColor !== void 0 || series.lineDash !== void 0) {
5290
- const lineColor = series.lineColor !== void 0 ? series.lineColor.replace(/^#/, "").toUpperCase() : color;
5291
- children.push(seriesSpPr(color, lineColor, series.lineWidthEmu, series.lineDash));
5292
- } else children.push(solidFillSpPr(color));
5293
- if (series.invertIfNegative === true && (kind === "bar" || kind === "column")) children.push(valNode(c("invertIfNegative"), "1"));
5294
- if (kind === "line" || kind === "scatter" || kind === "radar") {
5295
- const markerColor = series.markerColor !== void 0 ? series.markerColor.replace(/^#/, "").toUpperCase() : color;
5296
- const markerLineColor = series.markerLineColor !== void 0 ? series.markerLineColor.replace(/^#/, "").toUpperCase() : markerColor;
5297
- children.push(markerElement(series.markerSymbol, series.markerSizePt, markerColor, markerLineColor));
5298
- }
5299
- for (const dPt of dPtElements(series.pointColors, series.pointExplosions)) children.push(dPt);
5694
+ const isXy = shape === "scatter" || shape === "bubble";
5695
+ const pointCount = isXy ? series.values.length : spec.categories.length;
5696
+ const channels = [];
5697
+ if (isXy) {
5698
+ if (refs.xValues === void 0) throw new Error("seriesElement: xy series without an x range");
5699
+ channels.push(elem(c("xVal"), { children: [numRef(refs.xValues, padTo(series.xValues, pointCount))] }), elem(c("yVal"), { children: [numRef(refs.values, padTo(series.values, pointCount))] }));
5700
+ if (shape === "bubble") {
5701
+ if (refs.bubbleSizes === void 0) throw new Error("seriesElement: bubble series without a size range");
5702
+ channels.push(elem(c("bubbleSize"), { children: [numRef(refs.bubbleSizes, padTo(series.bubbleSizes, pointCount))] }), valNode(c("bubble3D"), spec.bubble3D === true ? "1" : "0"));
5703
+ }
5704
+ } else {
5705
+ if (layout.categories === void 0) throw new Error("seriesElement: category series without a category range");
5706
+ channels.push(categoryChannel(spec, layout.categories), elem(c("val"), { children: [numRef(refs.values, padTo(series.values, pointCount))] }));
5707
+ }
5708
+ if (shape === "surface") return elem(c("ser"), { children: [...children, ...channels] });
5709
+ const scatterStyle = spec.scatterStyle ?? "marker";
5710
+ const lineHidden = spec.kind === "stock" || shape === "scatter" && !SCATTER_STYLES_WITH_LINE.has(scatterStyle);
5711
+ if (lineHidden || shape === "line" || shape === "scatter" || shape === "radar" || series.lineWidthEmu !== void 0 || series.lineColor !== void 0 || series.lineDash !== void 0) {
5712
+ const lineColor = lineHidden ? null : series.lineColor !== void 0 ? hexOf(series.lineColor) : color;
5713
+ children.push(seriesSpPr(color, lineColor, series.lineWidthEmu, series.lineDash, series.fillOpacity));
5714
+ } else children.push(solidFillSpPr(color, series.fillOpacity));
5715
+ if (series.invertIfNegative === true && SHAPES_WITH_INVERT.has(shape)) children.push(valNode(c("invertIfNegative"), "1"));
5716
+ if (SHAPES_WITH_MARKER.has(shape)) {
5717
+ const markerColor = series.markerColor !== void 0 ? hexOf(series.markerColor) : color;
5718
+ const markerLineColor = series.markerLineColor !== void 0 ? hexOf(series.markerLineColor) : markerColor;
5719
+ const markersOff = spec.kind === "stock" || shape === "scatter" && !SCATTER_STYLES_WITH_MARKER.has(scatterStyle) || shape === "radar" && spec.radarStyle !== "marker";
5720
+ children.push(markerElement(series.markerSymbol ?? (markersOff ? "none" : void 0), series.markerSizePt, markerColor, markerLineColor));
5721
+ }
5722
+ for (const dPt of dPtElements(series.pointColors, series.pointExplosions, series.fillOpacity, spec.bubble3D === true)) children.push(dPt);
5300
5723
  if (series.pointDataLabels !== void 0 && series.dataLabels === void 0) throw new Error(`chart: series '${series.name}' sets pointDataLabels without dataLabels; add the series-level dataLabels the overrides fall back to`);
5301
5724
  const serDLbls = buildDLblsFromLabels(series.dataLabels, series.pointDataLabels);
5302
5725
  if (serDLbls !== null) children.push(serDLbls);
5303
- if (series.trendline && kind !== "pie" && kind !== "doughnut" && kind !== "radar") children.push(trendlineElement(series.trendline));
5304
- children.push(elem(c("cat"), { children: [strRef(catRange, spec.categories)] }));
5305
- children.push(elem(c("val"), { children: [numRef(valRange, paddedValues)] }));
5306
- if (kind === "line") children.push(valNode(c("smooth"), series.smooth === true ? "1" : "0"));
5726
+ if (series.trendline && SHAPES_WITH_TRENDLINE.has(shape) && spec.kind !== "stock") children.push(trendlineElement(series.trendline));
5727
+ if (series.errorBars !== void 0 || series.xErrorBars !== void 0) {
5728
+ if (!SHAPES_WITH_ERR_BARS.has(shape)) throw new Error(`chart: series '${series.name}' sets error bars, which a ${kind} series cannot carry (bar / column / line / area / scatter / bubble only)`);
5729
+ if (series.xErrorBars !== void 0 && !isXy) throw new Error(`chart: series '${series.name}' sets xErrorBars, which only scatter / bubble series have an x channel for`);
5730
+ if (series.xErrorBars !== void 0) children.push(errBarsElement(series.xErrorBars, "x"));
5731
+ if (series.errorBars !== void 0) children.push(errBarsElement(series.errorBars, isXy ? "y" : null));
5732
+ }
5733
+ children.push(...channels);
5734
+ if (shape === "line") children.push(valNode(c("smooth"), series.smooth === true ? "1" : "0"));
5735
+ else if (shape === "scatter") {
5736
+ const smooth = series.smooth ?? (scatterStyle === "smooth" || scatterStyle === "smoothMarker");
5737
+ children.push(valNode(c("smooth"), smooth ? "1" : "0"));
5738
+ }
5307
5739
  return elem(c("ser"), { children });
5308
5740
  };
5309
5741
  const CAT_AX_ID = 111111111;
@@ -5369,9 +5801,13 @@ const axisTxPrElement = (style, rotationDeg) => {
5369
5801
  };
5370
5802
  const catAxis = (spec) => {
5371
5803
  const catOrientation = spec.categoryAxisOrientation ?? "minMax";
5804
+ const dateAxis = spec.categoryAxisDate;
5805
+ const scalingChildren = [valNode(c("orientation"), catOrientation)];
5806
+ if (spec.categoryAxisScaling?.max !== void 0) scalingChildren.push(valNode(c("max"), spec.categoryAxisScaling.max));
5807
+ if (spec.categoryAxisScaling?.min !== void 0) scalingChildren.push(valNode(c("min"), spec.categoryAxisScaling.min));
5372
5808
  const children = [
5373
5809
  valNode(c("axId"), CAT_AX_ID),
5374
- elem(c("scaling"), { children: [valNode(c("orientation"), catOrientation)] }),
5810
+ elem(c("scaling"), { children: scalingChildren }),
5375
5811
  valNode(c("delete"), spec.categoryAxisHidden ? "1" : "0"),
5376
5812
  valNode(c("axPos"), isHorizontalBar(spec) ? "l" : "b")
5377
5813
  ];
@@ -5382,11 +5818,21 @@ const catAxis = (spec) => {
5382
5818
  if (spec.categoryAxisMajorTickMark !== void 0) children.push(valNode(c("majorTickMark"), spec.categoryAxisMajorTickMark));
5383
5819
  if (spec.categoryAxisMinorTickMark !== void 0) children.push(valNode(c("minorTickMark"), spec.categoryAxisMinorTickMark));
5384
5820
  if (spec.categoryAxisTickLabelPos !== void 0) children.push(valNode(c("tickLblPos"), spec.categoryAxisTickLabelPos));
5385
- const catLine = lineSpPr(spec.categoryAxisLineColor, spec.categoryAxisLineWidthEmu, "chart: categoryAxisLineWidthEmu");
5821
+ const catLine = lineSpPr(spec.categoryAxisLineColor, spec.categoryAxisLineWidthEmu, "chart: categoryAxisLineWidthEmu", spec.categoryAxisLineHidden === true);
5386
5822
  if (catLine !== null) children.push(catLine);
5387
5823
  const catTxPr = axisTxPrElement(spec.categoryAxisLabelStyle, spec.categoryAxisLabelRotationDeg);
5388
5824
  if (catTxPr) children.push(catTxPr);
5389
5825
  children.push(valNode(c("crossAx"), VAL_AX_ID));
5826
+ if (dateAxis !== void 0) {
5827
+ children.push(valNode(c("auto"), "0"));
5828
+ if (spec.categoryAxisLabelOffset !== void 0) children.push(valNode(c("lblOffset"), spec.categoryAxisLabelOffset));
5829
+ if (dateAxis.baseTimeUnit !== void 0) children.push(valNode(c("baseTimeUnit"), dateAxis.baseTimeUnit));
5830
+ if (dateAxis.majorUnit !== void 0) children.push(valNode(c("majorUnit"), dateAxis.majorUnit));
5831
+ if (dateAxis.majorTimeUnit !== void 0) children.push(valNode(c("majorTimeUnit"), dateAxis.majorTimeUnit));
5832
+ if (dateAxis.minorUnit !== void 0) children.push(valNode(c("minorUnit"), dateAxis.minorUnit));
5833
+ if (dateAxis.minorTimeUnit !== void 0) children.push(valNode(c("minorTimeUnit"), dateAxis.minorTimeUnit));
5834
+ return elem(c("dateAx"), { children });
5835
+ }
5390
5836
  if (spec.categoryAxisLabelAlign !== void 0) children.push(valNode(c("lblAlgn"), spec.categoryAxisLabelAlign));
5391
5837
  if (spec.categoryAxisLabelOffset !== void 0) children.push(valNode(c("lblOffset"), spec.categoryAxisLabelOffset));
5392
5838
  if (spec.categoryAxisTickLabelSkip !== void 0) children.push(valNode(c("tickLblSkip"), spec.categoryAxisTickLabelSkip));
@@ -5413,7 +5859,7 @@ const valueAxisElement = (f, ids) => {
5413
5859
  if (f.majorTickMark !== void 0) children.push(valNode(c("majorTickMark"), f.majorTickMark));
5414
5860
  if (f.minorTickMark !== void 0) children.push(valNode(c("minorTickMark"), f.minorTickMark));
5415
5861
  if (f.tickLabelPos !== void 0) children.push(valNode(c("tickLblPos"), f.tickLabelPos));
5416
- const axisLine = lineSpPr(f.lineColor, f.lineWidthEmu, `chart: ${f.widthFields.line}`);
5862
+ const axisLine = lineSpPr(f.lineColor, f.lineWidthEmu, `chart: ${f.widthFields.line}`, f.lineHidden === true);
5417
5863
  if (axisLine !== null) children.push(axisLine);
5418
5864
  const valTxPr = axisTxPrElement(f.labelStyle, f.labelRotationDeg);
5419
5865
  if (valTxPr) children.push(valTxPr);
@@ -5424,7 +5870,7 @@ const valueAxisElement = (f, ids) => {
5424
5870
  if (f.crossBetween !== void 0) children.push(valNode(c("crossBetween"), f.crossBetween));
5425
5871
  if (f.scaling?.majorUnit !== void 0) children.push(valNode(c("majorUnit"), f.scaling.majorUnit));
5426
5872
  if (f.scaling?.minorUnit !== void 0) children.push(valNode(c("minorUnit"), f.scaling.minorUnit));
5427
- if (f.scaling?.displayUnits !== void 0) children.push(elem(c("dispUnits"), { children: [valNode(c("builtInUnit"), f.scaling.displayUnits)] }));
5873
+ if (f.scaling?.displayUnits !== void 0) children.push(elem(c("dispUnits"), { children: [valNode(c("builtInUnit"), f.scaling.displayUnits), ...f.scaling.displayUnitsLabel === true ? [elem(c("dispUnitsLbl"))] : []] }));
5428
5874
  return elem(c("valAx"), { children });
5429
5875
  };
5430
5876
  const isHorizontalBar = (spec) => spec.kind === "bar";
@@ -5446,6 +5892,7 @@ const valAxis = (spec) => valueAxisElement({
5446
5892
  tickLabelPos: spec.valueAxisTickLabelPos,
5447
5893
  lineColor: spec.valueAxisLineColor,
5448
5894
  lineWidthEmu: spec.valueAxisLineWidthEmu,
5895
+ lineHidden: spec.valueAxisLineHidden,
5449
5896
  widthFields: {
5450
5897
  majorGridline: "valueAxisMajorGridlineWidthEmu",
5451
5898
  minorGridline: "valueAxisMinorGridlineWidthEmu",
@@ -5460,11 +5907,78 @@ const valAxis = (spec) => valueAxisElement({
5460
5907
  crossAxId: CAT_AX_ID,
5461
5908
  axPos: isHorizontalBar(spec) ? "b" : "l"
5462
5909
  });
5910
+ /**
5911
+ * The horizontal axis of a scatter / bubble chart. Both of their axes are
5912
+ * `<c:valAx>`; this one takes the spec's `categoryAxis*` fields, so an
5913
+ * author formats "the axis along the bottom" the same way for every kind.
5914
+ * It keeps the category axis' id, which the y axis already crosses.
5915
+ */
5916
+ const xValAxis = (spec) => valueAxisElement({
5917
+ scaling: {
5918
+ ...spec.categoryAxisScaling,
5919
+ ...spec.categoryAxisNumberFormat !== void 0 ? { numberFormat: spec.categoryAxisNumberFormat } : {}
5920
+ },
5921
+ orientation: spec.categoryAxisOrientation,
5922
+ hidden: spec.categoryAxisHidden,
5923
+ majorGridlines: spec.categoryAxisMajorGridlines,
5924
+ majorGridlineColor: spec.categoryAxisMajorGridlineColor,
5925
+ majorGridlineWidthEmu: spec.categoryAxisMajorGridlineWidthEmu,
5926
+ minorGridlines: spec.categoryAxisMinorGridlines,
5927
+ minorGridlineColor: spec.categoryAxisMinorGridlineColor,
5928
+ minorGridlineWidthEmu: spec.categoryAxisMinorGridlineWidthEmu,
5929
+ title: spec.categoryAxisTitle,
5930
+ titleStyle: spec.categoryAxisTitleStyle,
5931
+ titleRotationDeg: spec.categoryAxisTitleRotationDeg,
5932
+ majorTickMark: spec.categoryAxisMajorTickMark,
5933
+ minorTickMark: spec.categoryAxisMinorTickMark,
5934
+ tickLabelPos: spec.categoryAxisTickLabelPos,
5935
+ lineColor: spec.categoryAxisLineColor,
5936
+ lineWidthEmu: spec.categoryAxisLineWidthEmu,
5937
+ lineHidden: spec.categoryAxisLineHidden,
5938
+ widthFields: {
5939
+ majorGridline: "categoryAxisMajorGridlineWidthEmu",
5940
+ minorGridline: "categoryAxisMinorGridlineWidthEmu",
5941
+ line: "categoryAxisLineWidthEmu"
5942
+ },
5943
+ labelStyle: spec.categoryAxisLabelStyle,
5944
+ labelRotationDeg: spec.categoryAxisLabelRotationDeg,
5945
+ crosses: void 0,
5946
+ crossBetween: "midCat"
5947
+ }, {
5948
+ axId: CAT_AX_ID,
5949
+ crossAxId: VAL_AX_ID,
5950
+ axPos: "b"
5951
+ });
5952
+ const SER_AX_ID = 555555555;
5953
+ /** `<c:serAx>` — the depth axis of a 3-D or surface chart; it crosses the value axis. */
5954
+ const serAxis = (spec) => {
5955
+ const s = spec.seriesAxis ?? {};
5956
+ const children = [
5957
+ valNode(c("axId"), SER_AX_ID),
5958
+ elem(c("scaling"), { children: [valNode(c("orientation"), s.orientation ?? "minMax")] }),
5959
+ valNode(c("delete"), s.hidden ? "1" : "0"),
5960
+ valNode(c("axPos"), "b")
5961
+ ];
5962
+ if (s.majorGridlines) children.push(elem(c("majorGridlines")));
5963
+ if (s.title !== void 0) children.push(titleElement(s.title, s.titleStyle));
5964
+ if (s.tickLabelPos !== void 0) children.push(valNode(c("tickLblPos"), s.tickLabelPos));
5965
+ const line = lineSpPr(s.lineColor, void 0, "chart: seriesAxis");
5966
+ if (line !== null) children.push(line);
5967
+ const txPr = axisTxPrElement(s.labelStyle, void 0);
5968
+ if (txPr !== null) children.push(txPr);
5969
+ children.push(valNode(c("crossAx"), VAL_AX_ID));
5970
+ if (s.tickLabelSkip !== void 0) children.push(valNode(c("tickLblSkip"), s.tickLabelSkip));
5971
+ return elem(c("serAx"), { children });
5972
+ };
5463
5973
  const buildDLblsFromLabels = (dl, pointLabels = void 0) => {
5464
5974
  const children = [];
5465
5975
  pointLabels?.forEach((pl, i) => {
5466
5976
  if (pl === null) return;
5467
- children.push(elem(c("dLbl"), { children: [valNode(c("idx"), i), ...dLblGroupChildren(pl)] }));
5977
+ children.push(elem(c("dLbl"), { children: [
5978
+ valNode(c("idx"), i),
5979
+ ...pl.text !== void 0 ? [elem(c("tx"), { children: [richText(pl.text)] })] : [],
5980
+ ...dLblGroupChildren(pl)
5981
+ ] }));
5468
5982
  });
5469
5983
  if (dl) {
5470
5984
  children.push(...dLblGroupChildren(dl));
@@ -5475,93 +5989,220 @@ const buildDLblsFromLabels = (dl, pointLabels = void 0) => {
5475
5989
  const dLblGroupChildren = (dl) => {
5476
5990
  const children = [];
5477
5991
  if (dl.numberFormat !== void 0) children.push(elem(c("numFmt"), { attrs: [attr(qname("", "formatCode", ""), dl.numberFormat), attr(qname("", "sourceLinked", ""), "0")] }));
5992
+ if (dl.fillColor !== void 0) children.push(solidFillSpPr(dl.fillColor));
5478
5993
  if (dl.textStyle !== void 0) {
5479
5994
  const txPr = axisTxPrElement(dl.textStyle, void 0);
5480
5995
  if (txPr !== null) children.push(txPr);
5481
5996
  }
5482
5997
  if (dl.position !== void 0) children.push(valNode(c("dLblPos"), dl.position));
5483
- children.push(valNode(c("showLegendKey"), "0"), valNode(c("showVal"), dl.showValue ? "1" : "0"), valNode(c("showCatName"), dl.showCategory ? "1" : "0"), valNode(c("showSerName"), dl.showSeriesName ? "1" : "0"), valNode(c("showPercent"), dl.showPercent ? "1" : "0"), valNode(c("showBubbleSize"), "0"));
5998
+ children.push(valNode(c("showLegendKey"), dl.showLegendKey ? "1" : "0"), valNode(c("showVal"), dl.showValue ? "1" : "0"), valNode(c("showCatName"), dl.showCategory ? "1" : "0"), valNode(c("showSerName"), dl.showSeriesName ? "1" : "0"), valNode(c("showPercent"), dl.showPercent ? "1" : "0"), valNode(c("showBubbleSize"), dl.showBubbleSize ? "1" : "0"));
5484
5999
  if (dl.separator !== void 0) children.push(elem(c("separator"), { children: [text(dl.separator)] }));
5485
6000
  return children;
5486
6001
  };
5487
6002
  const dLblsElement = (spec) => buildDLblsFromLabels(spec.dataLabels);
5488
- const buildBarChart = (spec, sheet, direction, seriesIndices, axes) => {
5489
- const ser = seriesIndices.map((i) => seriesElement(spec, i, sheet));
5490
- const dl = dLblsElement(spec);
6003
+ const groupSeries = (g) => g.seriesIndices.map((i) => seriesElement(g.spec, i, g.layout));
6004
+ const groupDLbls = (g) => {
6005
+ const dl = dLblsElement(g.spec);
6006
+ return dl ? [dl] : [];
6007
+ };
6008
+ const isThreeD = (spec) => spec.view3D !== void 0;
6009
+ /**
6010
+ * Whether the chart carries a series (depth) axis. `<c:line3DChart>` and
6011
+ * the surface elements require three axes; 3-D bar / area charts only lay
6012
+ * their series out in depth — and so only have the axis — under the
6013
+ * `standard` grouping.
6014
+ */
6015
+ const hasSeriesAxis = (spec) => {
6016
+ if (spec.kind === "surface") return true;
6017
+ if (!isThreeD(spec)) return false;
6018
+ if (spec.kind === "line") return true;
6019
+ return (spec.kind === "bar" || spec.kind === "column" || spec.kind === "area") && spec.grouping === "standard";
6020
+ };
6021
+ const axIdNodes = (g) => [
6022
+ valNode(c("axId"), g.axes.cat),
6023
+ valNode(c("axId"), g.axes.val),
6024
+ ...hasSeriesAxis(g.spec) ? [valNode(c("axId"), SER_AX_ID)] : []
6025
+ ];
6026
+ const gapDepthNodes = (spec) => spec.gapDepthPct !== void 0 ? [valNode(c("gapDepth"), gapAmountPercent(spec.gapDepthPct, "chart: gapDepthPct"))] : [];
6027
+ const buildBarChart = (g, direction) => {
6028
+ const { spec } = g;
5491
6029
  const grouping = spec.grouping ?? "clustered";
5492
6030
  const children = [
5493
6031
  valNode(c("barDir"), direction),
5494
6032
  valNode(c("grouping"), grouping),
5495
6033
  valNode(c("varyColors"), spec.varyColors ? "1" : "0"),
5496
- ...ser,
5497
- ...dl ? [dl] : []
6034
+ ...groupSeries(g),
6035
+ ...groupDLbls(g)
5498
6036
  ];
5499
6037
  if (spec.gapWidthPct !== void 0) children.push(valNode(c("gapWidth"), gapAmountPercent(spec.gapWidthPct, "chart: gapWidthPct")));
6038
+ if (isThreeD(spec)) {
6039
+ children.push(...gapDepthNodes(spec));
6040
+ if (spec.bar3DShape !== void 0) children.push(valNode(c("shape"), spec.bar3DShape));
6041
+ children.push(...axIdNodes(g));
6042
+ return elem(c("bar3DChart"), { children });
6043
+ }
5500
6044
  const overlapPct = spec.overlapPct ?? (grouping === "stacked" || grouping === "percentStacked" ? 100 : void 0);
5501
6045
  if (overlapPct !== void 0) children.push(valNode(c("overlap"), overlapPercent(overlapPct, "chart: overlapPct")));
5502
- children.push(valNode(c("axId"), axes.cat), valNode(c("axId"), axes.val));
5503
- return elem(c(direction === "col" ? "barChart" : "barChart"), { children });
6046
+ children.push(...axIdNodes(g));
6047
+ return elem(c("barChart"), { children });
5504
6048
  };
5505
6049
  const lineAreaGrouping = (spec) => spec.grouping === "stacked" || spec.grouping === "percentStacked" ? spec.grouping : "standard";
5506
- const buildLineChart = (spec, sheet, seriesIndices, axes) => {
5507
- const ser = seriesIndices.map((i) => seriesElement(spec, i, sheet));
5508
- const dl = dLblsElement(spec);
6050
+ const upDownBarsElement = (bars) => {
6051
+ const bar = (name, color) => elem(c(name), { children: color !== void 0 ? [solidFillSpPr(color)] : [] });
6052
+ return elem(c("upDownBars"), { children: [
6053
+ ...bars.gapWidthPct !== void 0 ? [valNode(c("gapWidth"), gapAmountPercent(bars.gapWidthPct, "chart: upDownBars.gapWidthPct"))] : [],
6054
+ bar("upBars", bars.upColor),
6055
+ bar("downBars", bars.downColor)
6056
+ ] });
6057
+ };
6058
+ const buildLineChart = (g) => {
6059
+ const { spec } = g;
5509
6060
  const children = [
5510
6061
  valNode(c("grouping"), lineAreaGrouping(spec)),
5511
6062
  valNode(c("varyColors"), spec.varyColors ? "1" : "0"),
5512
- ...ser,
5513
- ...dl ? [dl] : []
6063
+ ...groupSeries(g),
6064
+ ...groupDLbls(g)
5514
6065
  ];
5515
6066
  if (spec.dropLines) children.push(elem(c("dropLines")));
6067
+ if (isThreeD(spec)) {
6068
+ if (spec.hiLowLines || spec.upDownBars !== void 0) throw new Error("chart: hiLowLines / upDownBars are not available on a 3-D line chart");
6069
+ children.push(...gapDepthNodes(spec), ...axIdNodes(g));
6070
+ return elem(c("line3DChart"), { children });
6071
+ }
5516
6072
  if (spec.hiLowLines) children.push(elem(c("hiLowLines")));
5517
- children.push(valNode(c("marker"), spec.lineMarkers === false ? "0" : "1"), valNode(c("axId"), axes.cat), valNode(c("axId"), axes.val));
6073
+ if (spec.upDownBars !== void 0) children.push(upDownBarsElement(spec.upDownBars));
6074
+ children.push(valNode(c("marker"), spec.lineMarkers === false ? "0" : "1"), ...axIdNodes(g));
5518
6075
  return elem(c("lineChart"), { children });
5519
6076
  };
5520
- const buildPieChart = (spec, sheet) => {
5521
- if (spec.series.length !== 1) throw new Error("pie chart requires exactly one series");
5522
- const ser = seriesElement(spec, 0, sheet);
5523
- const dl = dLblsElement(spec);
6077
+ const buildAreaChart = (g) => {
6078
+ const { spec } = g;
5524
6079
  const children = [
5525
- valNode(c("varyColors"), "1"),
5526
- ser,
5527
- ...dl ? [dl] : []
6080
+ valNode(c("grouping"), lineAreaGrouping(spec)),
6081
+ valNode(c("varyColors"), spec.varyColors ? "1" : "0"),
6082
+ ...groupSeries(g),
6083
+ ...groupDLbls(g)
5528
6084
  ];
5529
- if (spec.firstSliceAngleDeg !== void 0) children.push(valNode(c("firstSliceAng"), firstSliceAngle(spec.firstSliceAngleDeg, "chart: firstSliceAngleDeg")));
5530
- return elem(c("pieChart"), { children });
6085
+ if (spec.dropLines && spec.kind === "area") children.push(elem(c("dropLines")));
6086
+ if (isThreeD(spec)) {
6087
+ children.push(...gapDepthNodes(spec), ...axIdNodes(g));
6088
+ return elem(c("area3DChart"), { children });
6089
+ }
6090
+ children.push(...axIdNodes(g));
6091
+ return elem(c("areaChart"), { children });
5531
6092
  };
5532
- const buildDoughnutChart = (spec, sheet) => {
5533
- if (spec.series.length !== 1) throw new Error("doughnut chart requires exactly one series");
5534
- const ser = seriesElement(spec, 0, sheet);
5535
- const dl = dLblsElement(spec);
6093
+ const requireSingleSeries = (spec) => {
6094
+ if (spec.series.length !== 1) throw new Error(`${spec.kind} chart requires exactly one series`);
6095
+ };
6096
+ const firstSliceAngNodes = (spec) => spec.firstSliceAngleDeg !== void 0 ? [valNode(c("firstSliceAng"), firstSliceAngle(spec.firstSliceAngleDeg, "chart: firstSliceAngleDeg"))] : [];
6097
+ const buildOfPieChart = (g, ofPie) => {
5536
6098
  const children = [
6099
+ valNode(c("ofPieType"), ofPie.type),
5537
6100
  valNode(c("varyColors"), "1"),
5538
- ser,
5539
- ...dl ? [dl] : []
6101
+ ...groupSeries(g),
6102
+ ...groupDLbls(g)
5540
6103
  ];
5541
- if (spec.firstSliceAngleDeg !== void 0) children.push(valNode(c("firstSliceAng"), firstSliceAngle(spec.firstSliceAngleDeg, "chart: firstSliceAngleDeg")));
5542
- children.push(valNode(c("holeSize"), holeSizePercent(spec.holeSizePct ?? 50, "chart: holeSizePct")));
5543
- return elem(c("doughnutChart"), { children });
5544
- };
5545
- const buildAreaChart = (spec, sheet, seriesIndices, axes) => {
5546
- const ser = seriesIndices.map((i) => seriesElement(spec, i, sheet));
5547
- const dl = dLblsElement(spec);
5548
- return elem(c("areaChart"), { children: [
5549
- valNode(c("grouping"), lineAreaGrouping(spec)),
5550
- valNode(c("varyColors"), spec.varyColors ? "1" : "0"),
5551
- ...ser,
5552
- ...dl ? [dl] : [],
5553
- valNode(c("axId"), axes.cat),
5554
- valNode(c("axId"), axes.val)
6104
+ if (ofPie.gapWidthPct !== void 0) children.push(valNode(c("gapWidth"), gapAmountPercent(ofPie.gapWidthPct, "chart: ofPie.gapWidthPct")));
6105
+ if (ofPie.customSplit !== void 0 && ofPie.splitType !== "cust") throw new Error("chart: ofPie.customSplit requires ofPie.splitType 'cust'");
6106
+ if (ofPie.splitType !== void 0) children.push(valNode(c("splitType"), ofPie.splitType));
6107
+ if (ofPie.splitPos !== void 0) children.push(valNode(c("splitPos"), ofPie.splitPos));
6108
+ if (ofPie.customSplit !== void 0) children.push(elem(c("custSplit"), { children: ofPie.customSplit.map((idx) => valNode(c("secondPiePt"), idx)) }));
6109
+ if (ofPie.secondPieSizePct !== void 0) children.push(valNode(c("secondPieSize"), boundedInt(ofPie.secondPieSizePct, "secondPieSize", "chart: ofPie.secondPieSizePct")));
6110
+ if (ofPie.seriesLines) children.push(elem(c("serLines")));
6111
+ return elem(c("ofPieChart"), { children });
6112
+ };
6113
+ const buildPieChart = (g) => {
6114
+ const { spec } = g;
6115
+ requireSingleSeries(spec);
6116
+ if (spec.ofPie !== void 0) {
6117
+ if (isThreeD(spec)) throw new Error("chart: ofPie and view3D cannot be combined");
6118
+ return buildOfPieChart(g, spec.ofPie);
6119
+ }
6120
+ const children = [
6121
+ valNode(c("varyColors"), "1"),
6122
+ ...groupSeries(g),
6123
+ ...groupDLbls(g)
6124
+ ];
6125
+ if (isThreeD(spec)) {
6126
+ if (spec.firstSliceAngleDeg !== void 0) throw new Error("chart: a 3-D pie has no firstSliceAngleDeg; rotate it with view3D.rotY");
6127
+ return elem(c("pie3DChart"), { children });
6128
+ }
6129
+ children.push(...firstSliceAngNodes(spec));
6130
+ return elem(c("pieChart"), { children });
6131
+ };
6132
+ const buildDoughnutChart = (g) => {
6133
+ const { spec } = g;
6134
+ requireSingleSeries(spec);
6135
+ return elem(c("doughnutChart"), { children: [
6136
+ valNode(c("varyColors"), "1"),
6137
+ ...groupSeries(g),
6138
+ ...groupDLbls(g),
6139
+ ...firstSliceAngNodes(spec),
6140
+ valNode(c("holeSize"), holeSizePercent(spec.holeSizePct ?? 50, "chart: holeSizePct"))
5555
6141
  ] });
5556
6142
  };
5557
- /** One combo plot group, dispatched by its effective kind. */
5558
- const buildComboGroupChart = (spec, sheet, kind, seriesIndices, axes) => {
6143
+ const buildScatterChart = (g) => elem(c("scatterChart"), { children: [
6144
+ valNode(c("scatterStyle"), g.spec.scatterStyle ?? "marker"),
6145
+ valNode(c("varyColors"), g.spec.varyColors ? "1" : "0"),
6146
+ ...groupSeries(g),
6147
+ ...groupDLbls(g),
6148
+ ...axIdNodes(g)
6149
+ ] });
6150
+ const buildBubbleChart = (g) => {
6151
+ const { spec } = g;
6152
+ const children = [
6153
+ valNode(c("varyColors"), spec.varyColors ? "1" : "0"),
6154
+ ...groupSeries(g),
6155
+ ...groupDLbls(g)
6156
+ ];
6157
+ if (spec.bubbleScale !== void 0) children.push(valNode(c("bubbleScale"), boundedInt(spec.bubbleScale, "bubbleScale", "chart: bubbleScale")));
6158
+ if (spec.showNegativeBubbles !== void 0) children.push(valNode(c("showNegBubbles"), spec.showNegativeBubbles ? "1" : "0"));
6159
+ if (spec.bubbleSizeRepresents !== void 0) children.push(valNode(c("sizeRepresents"), spec.bubbleSizeRepresents === "width" ? "w" : "area"));
6160
+ children.push(...axIdNodes(g));
6161
+ return elem(c("bubbleChart"), { children });
6162
+ };
6163
+ const buildRadarChart = (g) => elem(c("radarChart"), { children: [
6164
+ valNode(c("radarStyle"), g.spec.radarStyle ?? "standard"),
6165
+ valNode(c("varyColors"), g.spec.varyColors ? "1" : "0"),
6166
+ ...groupSeries(g),
6167
+ ...groupDLbls(g),
6168
+ ...axIdNodes(g)
6169
+ ] });
6170
+ const STOCK_SERIES_WITH_OPEN = 4;
6171
+ const STOCK_SERIES_WITHOUT_OPEN = 3;
6172
+ const buildStockChart = (g) => {
6173
+ const { spec } = g;
6174
+ const count = spec.series.length;
6175
+ if (count !== STOCK_SERIES_WITHOUT_OPEN && count !== STOCK_SERIES_WITH_OPEN) throw new Error(`stock chart requires 3 series (high, low, close) or 4 (open, high, low, close); got ${count}`);
6176
+ const children = [...groupSeries(g), ...groupDLbls(g)];
6177
+ if (spec.dropLines) children.push(elem(c("dropLines")));
6178
+ if (spec.hiLowLines !== false) children.push(elem(c("hiLowLines")));
6179
+ if (spec.upDownBars !== void 0 && count !== STOCK_SERIES_WITH_OPEN) throw new Error("stock chart: upDownBars require the 4-series form (open, high, low, close)");
6180
+ if (count === STOCK_SERIES_WITH_OPEN) children.push(upDownBarsElement(spec.upDownBars ?? {}));
6181
+ children.push(...axIdNodes(g));
6182
+ return elem(c("stockChart"), { children });
6183
+ };
6184
+ const buildSurfaceChart = (g) => {
6185
+ const { spec } = g;
6186
+ const children = [];
6187
+ if (spec.surfaceWireframe !== void 0) children.push(valNode(c("wireframe"), spec.surfaceWireframe ? "1" : "0"));
6188
+ children.push(...groupSeries(g), ...axIdNodes(g));
6189
+ return elem(c(spec.surfaceContour === true ? "surfaceChart" : "surface3DChart"), { children });
6190
+ };
6191
+ /** One plot group, dispatched by its effective kind. */
6192
+ const buildPlotGroup = (g, kind) => {
5559
6193
  switch (kind) {
5560
- case "column": return buildBarChart(spec, sheet, "col", seriesIndices, axes);
5561
- case "bar": return buildBarChart(spec, sheet, "bar", seriesIndices, axes);
5562
- case "line": return buildLineChart(spec, sheet, seriesIndices, axes);
5563
- case "area": return buildAreaChart(spec, sheet, seriesIndices, axes);
5564
- default: throw new Error(`combo chart: series chartKind '${kind}' is not authorable`);
6194
+ case "column": return buildBarChart(g, "col");
6195
+ case "bar": return buildBarChart(g, "bar");
6196
+ case "line": return buildLineChart(g);
6197
+ case "area": return buildAreaChart(g);
6198
+ case "pie": return buildPieChart(g);
6199
+ case "doughnut": return buildDoughnutChart(g);
6200
+ case "scatter": return buildScatterChart(g);
6201
+ case "bubble": return buildBubbleChart(g);
6202
+ case "radar": return buildRadarChart(g);
6203
+ case "stock": return buildStockChart(g);
6204
+ case "surface": return buildSurfaceChart(g);
6205
+ default: throw new Error(`unsupported chart kind: ${String(kind)}`);
5565
6206
  }
5566
6207
  };
5567
6208
  /**
@@ -5590,6 +6231,7 @@ const secondaryValAxis = (spec) => {
5590
6231
  tickLabelPos: s.tickLabelPos,
5591
6232
  lineColor: s.lineColor,
5592
6233
  lineWidthEmu: s.lineWidthEmu,
6234
+ lineHidden: void 0,
5593
6235
  widthFields: {
5594
6236
  majorGridline: "secondaryValueAxis.majorGridlineWidthEmu",
5595
6237
  minorGridline: "secondaryValueAxis.minorGridlineWidthEmu",
@@ -5640,7 +6282,20 @@ const rPrAttrsFromStyle = (style) => {
5640
6282
  children
5641
6283
  };
5642
6284
  };
5643
- const titleElement = (title, style, rotationDeg) => {
6285
+ const manualLayoutElement = (position, size, target) => elem(c("layout"), { children: [elem(c("manualLayout"), { children: [
6286
+ ...target !== void 0 ? [valNode(c("layoutTarget"), target)] : [],
6287
+ valNode(c("xMode"), "edge"),
6288
+ valNode(c("yMode"), "edge"),
6289
+ valNode(c("x"), position.x),
6290
+ valNode(c("y"), position.y),
6291
+ ...size !== void 0 ? [valNode(c("w"), size.w), valNode(c("h"), size.h)] : []
6292
+ ] })] });
6293
+ const richText = (value) => elem(c("rich"), { children: [
6294
+ elem(a("bodyPr")),
6295
+ elem(a("lstStyle")),
6296
+ elem(a("p"), { children: [elem(a("r"), { children: [elem(a("t"), { children: [text(value)] })] })] })
6297
+ ] });
6298
+ const titleElement = (title, style, rotationDeg, placement) => {
5644
6299
  const pPr = elem(a("pPr"), { children: [elem(a("defRPr"))] });
5645
6300
  const { attrs: runAttrs, children: runChildren } = rPrAttrsFromStyle(style);
5646
6301
  const runRPr = elem(a("rPr"), {
@@ -5662,7 +6317,95 @@ const titleElement = (title, style, rotationDeg) => {
5662
6317
  elem(a("lstStyle")),
5663
6318
  para
5664
6319
  ] });
5665
- return elem(c("title"), { children: [elem(c("tx"), { children: [rich] }), valNode(c("overlay"), "0")] });
6320
+ return elem(c("title"), { children: [
6321
+ elem(c("tx"), { children: [rich] }),
6322
+ ...placement?.layout !== void 0 ? [manualLayoutElement(placement.layout)] : [],
6323
+ valNode(c("overlay"), placement?.overlay === true ? "1" : "0")
6324
+ ] });
6325
+ };
6326
+ const view3DDefaults = (spec) => {
6327
+ if (spec.kind === "surface" && spec.surfaceContour === true) return {
6328
+ rotX: 90,
6329
+ rotY: 0,
6330
+ rightAngleAxes: false,
6331
+ perspective: 0
6332
+ };
6333
+ if (spec.kind === "pie") return {
6334
+ rotX: 30,
6335
+ rotY: 0,
6336
+ rightAngleAxes: false
6337
+ };
6338
+ if (spec.kind === "surface") return {
6339
+ rotX: 15,
6340
+ rotY: 20,
6341
+ rightAngleAxes: false,
6342
+ perspective: 30
6343
+ };
6344
+ return {
6345
+ rotX: 15,
6346
+ rotY: 20,
6347
+ rightAngleAxes: true
6348
+ };
6349
+ };
6350
+ const view3DElement = (spec) => {
6351
+ const v = {
6352
+ ...view3DDefaults(spec),
6353
+ ...spec.view3D
6354
+ };
6355
+ const children = [];
6356
+ if (v.rotX !== void 0) children.push(valNode(c("rotX"), boundedInt(v.rotX, "rotX", "chart: view3D.rotX")));
6357
+ if (v.heightPercent !== void 0) children.push(valNode(c("hPercent"), boundedInt(v.heightPercent, "heightPercent", "chart: view3D.heightPercent")));
6358
+ if (v.rotY !== void 0) children.push(valNode(c("rotY"), boundedInt(v.rotY, "rotY", "chart: view3D.rotY")));
6359
+ if (v.depthPercent !== void 0) children.push(valNode(c("depthPercent"), boundedInt(v.depthPercent, "depthPercent", "chart: view3D.depthPercent")));
6360
+ if (v.rightAngleAxes !== void 0) children.push(valNode(c("rAngAx"), v.rightAngleAxes ? "1" : "0"));
6361
+ if (v.perspective !== void 0) children.push(valNode(c("perspective"), boundedInt(v.perspective, "perspective", "chart: view3D.perspective")));
6362
+ return elem(c("view3D"), { children });
6363
+ };
6364
+ const KINDS_WITH_VIEW_3D = new Set([
6365
+ "bar",
6366
+ "column",
6367
+ "line",
6368
+ "area",
6369
+ "pie",
6370
+ "surface"
6371
+ ]);
6372
+ const AXISLESS_KINDS = new Set(["pie", "doughnut"]);
6373
+ const XY_KINDS = new Set(["scatter", "bubble"]);
6374
+ const validateSpec = (spec, usesComboFields) => {
6375
+ if (usesComboFields && !COMBO_KINDS.has(spec.kind)) throw new Error(`chart kind '${spec.kind}' does not support per-series chartKind / secondaryAxis (combo charts require a bar / column / line / area base kind)`);
6376
+ if (spec.view3D !== void 0) {
6377
+ if (!KINDS_WITH_VIEW_3D.has(spec.kind)) throw new Error(`chart kind '${spec.kind}' has no 3-D variant; view3D applies to bar / column / line / area / pie / surface`);
6378
+ if (usesComboFields) throw new Error("chart: view3D cannot be combined with a combo chart");
6379
+ }
6380
+ if ((spec.bar3DShape !== void 0 || spec.gapDepthPct !== void 0) && spec.view3D === void 0) throw new Error("chart: bar3DShape / gapDepthPct require view3D");
6381
+ if (spec.ofPie !== void 0 && spec.kind !== "pie") throw new Error(`chart: ofPie applies to kind 'pie', not '${spec.kind}'`);
6382
+ if (spec.dataTable !== void 0 && (AXISLESS_KINDS.has(spec.kind) || XY_KINDS.has(spec.kind))) throw new Error(`chart kind '${spec.kind}' cannot show a data table`);
6383
+ if (spec.categoryAxisDate !== void 0) {
6384
+ if (AXISLESS_KINDS.has(spec.kind) || XY_KINDS.has(spec.kind)) throw new Error(`chart kind '${spec.kind}' has no category axis to make a date axis of`);
6385
+ if (spec.categoryGroupLevels !== void 0) throw new Error("chart: a date axis cannot have categoryGroupLevels");
6386
+ spec.categories.forEach((category, i) => {
6387
+ if (category.trim() === "" || !Number.isFinite(Number(category))) throw new Error(`chart: categories[${i}] is ${JSON.stringify(category)}; a date axis needs date serial numbers (e.g. "45292" for 2024-01-01)`);
6388
+ });
6389
+ }
6390
+ if (spec.categoryAxisScaling !== void 0 && spec.categoryAxisDate === void 0 && !XY_KINDS.has(spec.kind)) throw new Error("chart: categoryAxisScaling needs a numeric horizontal axis — a scatter / bubble chart or a date axis");
6391
+ spec.categoryGroupLevels?.forEach((level, i) => {
6392
+ if (level.length !== spec.categories.length) throw new Error(`chart: categoryGroupLevels[${i}] has ${level.length} entries for ${spec.categories.length} categories`);
6393
+ });
6394
+ if (XY_KINDS.has(spec.kind)) spec.series.forEach((series) => {
6395
+ if (series.xValues === void 0) throw new Error(`chart: ${spec.kind} series '${series.name}' needs xValues`);
6396
+ if (spec.kind === "bubble" && series.bubbleSizes === void 0) throw new Error(`chart: bubble series '${series.name}' needs bubbleSizes`);
6397
+ });
6398
+ };
6399
+ const dataTableElement = (table) => {
6400
+ const children = [
6401
+ valNode(c("showHorzBorder"), table.showHorizontalBorder === false ? "0" : "1"),
6402
+ valNode(c("showVertBorder"), table.showVerticalBorder === false ? "0" : "1"),
6403
+ valNode(c("showOutline"), table.showOutline === false ? "0" : "1"),
6404
+ valNode(c("showKeys"), table.showKeys === false ? "0" : "1")
6405
+ ];
6406
+ const txPr = axisTxPrElement(table.textStyle, void 0);
6407
+ if (txPr !== null) children.push(txPr);
6408
+ return elem(c("dTable"), { children });
5666
6409
  };
5667
6410
  /**
5668
6411
  * Builds a complete `<c:chartSpace>` document for `spec`. The caller
@@ -5670,55 +6413,48 @@ const titleElement = (title, style, rotationDeg) => {
5670
6413
  * `r:id="rId1"` for the embedded workbook.
5671
6414
  */
5672
6415
  const buildChartSpaceDoc = (spec) => {
5673
- const sheet = "Sheet1";
5674
6416
  const usesComboFields = spec.series.some((series) => series.chartKind !== void 0 || series.secondaryAxis === true);
5675
- if (usesComboFields && !COMBO_KINDS.has(spec.kind)) throw new Error(`chart kind '${spec.kind}' does not support per-series chartKind / secondaryAxis (combo charts require a bar / column / line / area base kind)`);
5676
- const allIndices = spec.series.map((_, i) => i);
6417
+ validateSpec(spec, usesComboFields);
6418
+ const layout = layoutChartSheet(spec);
5677
6419
  let plottedGroups;
5678
6420
  let hasSecondary = false;
5679
- switch (spec.kind) {
5680
- case "column":
5681
- case "bar":
5682
- case "line":
5683
- case "area":
5684
- if (usesComboFields) {
5685
- const groups = comboPlotGroups(spec);
5686
- hasSecondary = groups.some((group) => group.secondary);
5687
- plottedGroups = groups.map((group) => buildComboGroupChart(spec, sheet, group.kind, group.indices, group.secondary ? SECONDARY_AXES : PRIMARY_AXES));
5688
- } else plottedGroups = [buildComboGroupChart(spec, sheet, spec.kind, allIndices, PRIMARY_AXES)];
5689
- break;
5690
- case "pie":
5691
- plottedGroups = [buildPieChart(spec, sheet)];
5692
- break;
5693
- case "doughnut":
5694
- plottedGroups = [buildDoughnutChart(spec, sheet)];
5695
- break;
5696
- case "scatter":
5697
- case "radar":
5698
- case "bubble": throw new Error(`chart kind '${spec.kind}' is read-only; authoring scatter / radar / bubble charts is not yet supported`);
5699
- default: {
5700
- const exhaustive = spec.kind;
5701
- throw new Error(`unsupported chart kind: ${String(exhaustive)}`);
5702
- }
5703
- }
5704
- const axisless = spec.kind === "pie" || spec.kind === "doughnut";
5705
- const plotAreaChildren = [elem(c("layout")), ...plottedGroups];
5706
- if (!axisless) {
5707
- plotAreaChildren.push(catAxis(spec), valAxis(spec));
6421
+ if (usesComboFields) {
6422
+ const groups = comboPlotGroups(spec);
6423
+ hasSecondary = groups.some((group) => group.secondary);
6424
+ plottedGroups = groups.map((group) => buildPlotGroup({
6425
+ spec,
6426
+ layout,
6427
+ seriesIndices: group.indices,
6428
+ axes: group.secondary ? SECONDARY_AXES : PRIMARY_AXES
6429
+ }, group.kind));
6430
+ } else plottedGroups = [buildPlotGroup({
6431
+ spec,
6432
+ layout,
6433
+ seriesIndices: spec.series.map((_, i) => i),
6434
+ axes: PRIMARY_AXES
6435
+ }, spec.kind)];
6436
+ const plotLayout = spec.plotAreaLayout;
6437
+ const plotAreaChildren = [plotLayout !== void 0 ? manualLayoutElement(plotLayout, plotLayout, plotLayout.target) : elem(c("layout")), ...plottedGroups];
6438
+ if (!AXISLESS_KINDS.has(spec.kind)) {
6439
+ plotAreaChildren.push(XY_KINDS.has(spec.kind) ? xValAxis(spec) : catAxis(spec), valAxis(spec));
6440
+ if (hasSeriesAxis(spec)) plotAreaChildren.push(serAxis(spec));
5708
6441
  if (hasSecondary) plotAreaChildren.push(secondaryValAxis(spec), secondaryCatAxis(spec));
5709
6442
  }
6443
+ if (spec.dataTable !== void 0) plotAreaChildren.push(dataTableElement(spec.dataTable));
5710
6444
  if (spec.plotAreaFill !== void 0 || spec.plotAreaStrokeColor !== void 0) plotAreaChildren.push(spPrChildren(spec.plotAreaFill, spec.plotAreaStrokeColor));
5711
6445
  const plotArea = elem(c("plotArea"), { children: plotAreaChildren });
5712
6446
  const chartChildren = [];
5713
- if (spec.title !== void 0) {
5714
- const titleEl = titleElement(spec.title, spec.titleStyle);
5715
- if (spec.titleOverlay !== void 0) titleEl.children = [...titleEl.children.filter((c2) => !(c2.kind === "element" && c2.name.namespaceURI === NS_C$1 && c2.name.localName === "overlay")), valNode(c("overlay"), spec.titleOverlay ? "1" : "0")];
5716
- chartChildren.push(titleEl);
5717
- }
5718
- chartChildren.push(valNode(c("autoTitleDeleted"), spec.title !== void 0 ? "0" : "1"), plotArea);
6447
+ if (spec.title !== void 0) chartChildren.push(titleElement(spec.title, spec.titleStyle, void 0, {
6448
+ ...spec.titleOverlay !== void 0 ? { overlay: spec.titleOverlay } : {},
6449
+ ...spec.titleLayout !== void 0 ? { layout: spec.titleLayout } : {}
6450
+ }));
6451
+ chartChildren.push(valNode(c("autoTitleDeleted"), spec.title !== void 0 ? "0" : "1"));
6452
+ if (spec.view3D !== void 0 || spec.kind === "surface") chartChildren.push(view3DElement(spec));
6453
+ chartChildren.push(plotArea);
5719
6454
  if (spec.legend !== void 0 && spec.legend.position !== null) {
5720
6455
  const legendChildren = [valNode(c("legendPos"), spec.legend.position)];
5721
6456
  for (const idx of spec.legend.hiddenIndices ?? []) legendChildren.push(elem(c("legendEntry"), { children: [valNode(c("idx"), idx), valNode(c("delete"), "1")] }));
6457
+ if (spec.legend.layout !== void 0) legendChildren.push(manualLayoutElement(spec.legend.layout, spec.legend.layout));
5722
6458
  legendChildren.push(valNode(c("overlay"), spec.legend.overlay ? "1" : "0"));
5723
6459
  if (spec.legend.textStyle !== void 0) {
5724
6460
  const txPr = axisTxPrElement(spec.legend.textStyle, void 0);
@@ -5852,15 +6588,15 @@ const KIND_MAP = [
5852
6588
  },
5853
6589
  {
5854
6590
  localName: "stockChart",
5855
- kind: "line"
6591
+ kind: "stock"
5856
6592
  },
5857
6593
  {
5858
6594
  localName: "surfaceChart",
5859
- kind: "column"
6595
+ kind: "surface"
5860
6596
  },
5861
6597
  {
5862
6598
  localName: "surface3DChart",
5863
- kind: "column"
6599
+ kind: "surface"
5864
6600
  }
5865
6601
  ];
5866
6602
  const findFirst = (parent, names) => {
@@ -6293,6 +7029,10 @@ const readDataLabelsGroup = (host, inherited) => {
6293
7029
  const separator = readDataLabelSeparator(host);
6294
7030
  const txPrEl = firstChildElement(host, qname("c", "txPr", NS_C));
6295
7031
  const textStyle = txPrEl ? readLabelStyle(txPrEl) : void 0;
7032
+ const showBubbleSize = readToggle("showBubbleSize", inherited?.showBubbleSize ?? false);
7033
+ const showLegendKey = readToggle("showLegendKey", inherited?.showLegendKey ?? false);
7034
+ const spPr = firstChildElement(host, NAME_SP_PR_C);
7035
+ const fillColor = spPr !== null ? readSolidSrgb(spPr) : void 0;
6296
7036
  return {
6297
7037
  showValue: readToggle("showVal", inherited?.showValue ?? false),
6298
7038
  showCategory: readToggle("showCatName", inherited?.showCategory ?? false),
@@ -6301,9 +7041,28 @@ const readDataLabelsGroup = (host, inherited) => {
6301
7041
  ...numberFormat !== void 0 ? { numberFormat } : {},
6302
7042
  ...position !== void 0 ? { position } : {},
6303
7043
  ...separator !== void 0 ? { separator } : {},
6304
- ...textStyle !== void 0 ? { textStyle } : {}
7044
+ ...textStyle !== void 0 ? { textStyle } : {},
7045
+ ...showBubbleSize ? { showBubbleSize } : {},
7046
+ ...showLegendKey ? { showLegendKey } : {},
7047
+ ...fillColor !== void 0 ? { fillColor } : {}
6305
7048
  };
6306
7049
  };
7050
+ const readRichText = (host) => {
7051
+ const tx = firstChildElement(host, NAME_TX);
7052
+ const rich = tx !== null ? firstChildElement(tx, NAME_RICH) : null;
7053
+ if (rich === null) return void 0;
7054
+ const paragraphs = [];
7055
+ for (const p of allChildElements(rich, NAME_P_DML)) {
7056
+ let line = "";
7057
+ for (const r of allChildElements(p, NAME_R_DML)) {
7058
+ const t = firstChildElement(r, NAME_T);
7059
+ if (t === null) continue;
7060
+ for (const child of t.children) if (child.kind === "text" || child.kind === "cdata") line += child.data;
7061
+ }
7062
+ paragraphs.push(line);
7063
+ }
7064
+ return paragraphs.join("\n");
7065
+ };
6307
7066
  const readSeriesLevelDataLabels = (dLbls) => {
6308
7067
  const group = readDataLabelsGroup(dLbls, void 0);
6309
7068
  const leaderEl = firstChildElement(dLbls, qname("c", "showLeaderLines", NS_C));
@@ -6326,7 +7085,15 @@ const readPointDataLabels = (dLbls, pointCount, seriesLabels) => {
6326
7085
  const idx = readPointIndex(dLbl, pointCount);
6327
7086
  if (idx === null) continue;
6328
7087
  const deleteEl = firstChildElement(dLbl, qname("c", "delete", NS_C));
6329
- out[idx] = deleteEl !== null && readXmlBool(deleteEl) ? DELETED_POINT_LABEL : readDataLabelsGroup(dLbl, seriesLabels);
7088
+ if (deleteEl !== null && readXmlBool(deleteEl)) out[idx] = DELETED_POINT_LABEL;
7089
+ else {
7090
+ const group = readDataLabelsGroup(dLbl, seriesLabels);
7091
+ const literal = readRichText(dLbl);
7092
+ out[idx] = literal !== void 0 ? {
7093
+ ...group,
7094
+ text: literal
7095
+ } : group;
7096
+ }
6330
7097
  any = true;
6331
7098
  }
6332
7099
  if (!any) return void 0;
@@ -6340,6 +7107,7 @@ const readValueAxisScaling = (valAx) => {
6340
7107
  let minorUnit;
6341
7108
  let logBase;
6342
7109
  let displayUnits;
7110
+ let displayUnitsLabel = false;
6343
7111
  const scaling = firstChildElement(valAx, qname("c", "scaling", NS_C));
6344
7112
  const readNumOn = (parent, local) => {
6345
7113
  const el = firstChildElement(parent, qname("c", local, NS_C));
@@ -6376,6 +7144,7 @@ const readValueAxisScaling = (valAx) => {
6376
7144
  break;
6377
7145
  }
6378
7146
  }
7147
+ displayUnitsLabel = firstChildElement(dispUnits, qname("c", "dispUnitsLbl", NS_C)) !== null;
6379
7148
  }
6380
7149
  let numberFormat;
6381
7150
  const nfEl = firstChildElement(valAx, qname("c", "numFmt", NS_C));
@@ -6390,9 +7159,285 @@ const readValueAxisScaling = (valAx) => {
6390
7159
  ...minorUnit !== void 0 ? { minorUnit } : {},
6391
7160
  ...numberFormat !== void 0 ? { numberFormat } : {},
6392
7161
  ...logBase !== void 0 ? { logBase } : {},
6393
- ...displayUnits !== void 0 ? { displayUnits } : {}
7162
+ ...displayUnits !== void 0 ? { displayUnits } : {},
7163
+ ...displayUnits !== void 0 && displayUnitsLabel ? { displayUnitsLabel } : {}
7164
+ };
7165
+ };
7166
+ const childVal = (parent, local) => {
7167
+ const el = firstChildElement(parent, qname("c", local, NS_C));
7168
+ return el !== null ? getAttrValue(el, ATTR_VAL) : null;
7169
+ };
7170
+ const childNumber = (parent, local) => {
7171
+ const raw = childVal(parent, local);
7172
+ if (raw === null) return void 0;
7173
+ const n = Number.parseFloat(raw);
7174
+ return Number.isFinite(n) ? n : void 0;
7175
+ };
7176
+ const childBool = (parent, local) => {
7177
+ const el = firstChildElement(parent, qname("c", local, NS_C));
7178
+ return el !== null ? readXmlBool(el) : void 0;
7179
+ };
7180
+ const childToken = (parent, local, allowed) => {
7181
+ const raw = childVal(parent, local);
7182
+ return allowed.find((token) => token === raw);
7183
+ };
7184
+ const ALPHA_OPAQUE = 1e5;
7185
+ const readSeriesFillOpacity = (ser) => {
7186
+ const spPr = firstChildElement(ser, NAME_SP_PR_C);
7187
+ const fill = spPr !== null ? firstChildElement(spPr, NAME_SOLID_FILL$1) : null;
7188
+ const srgb = fill !== null ? firstChildElement(fill, NAME_SRGB_CLR) : null;
7189
+ const alpha = srgb !== null ? firstChildElement(srgb, qname("a", "alpha", NS_A)) : null;
7190
+ const raw = alpha !== null ? getAttrValue(alpha, ATTR_VAL) : null;
7191
+ if (raw === null || !/^\d+$/.test(raw)) return void 0;
7192
+ const n = Number.parseInt(raw, 10);
7193
+ return n <= ALPHA_OPAQUE ? n / ALPHA_OPAQUE : void 0;
7194
+ };
7195
+ const readErrorBarAmount = (errBars) => {
7196
+ const type = childToken(errBars, "errValType", [
7197
+ "cust",
7198
+ "fixedVal",
7199
+ "percentage",
7200
+ "stdDev",
7201
+ "stdErr"
7202
+ ]);
7203
+ if (type === void 0) return void 0;
7204
+ if (type === "stdErr") return { type };
7205
+ if (type === "cust") {
7206
+ const side = (local) => {
7207
+ const el = firstChildElement(errBars, qname("c", local, NS_C));
7208
+ return el !== null ? readNumChannel(el) ?? void 0 : void 0;
7209
+ };
7210
+ const plus = side("plus");
7211
+ const minus = side("minus");
7212
+ return {
7213
+ type,
7214
+ ...plus !== void 0 ? { plus } : {},
7215
+ ...minus !== void 0 ? { minus } : {}
7216
+ };
7217
+ }
7218
+ const value = childNumber(errBars, "val");
7219
+ return value !== void 0 ? {
7220
+ type,
7221
+ value
7222
+ } : void 0;
7223
+ };
7224
+ const readErrorBars = (ser) => {
7225
+ const out = {};
7226
+ for (const el of allChildElements(ser, qname("c", "errBars", NS_C))) {
7227
+ const barType = childToken(el, "errBarType", [
7228
+ "both",
7229
+ "minus",
7230
+ "plus"
7231
+ ]);
7232
+ const amount = readErrorBarAmount(el);
7233
+ if (barType === void 0 || amount === void 0) continue;
7234
+ const noEndCap = childBool(el, "noEndCap");
7235
+ const spPr = firstChildElement(el, NAME_SP_PR_C);
7236
+ const ln = spPr !== null ? firstChildElement(spPr, qname("a", "ln", NS_A)) : null;
7237
+ const color = readSolidSrgb(ln);
7238
+ const w = ln !== null ? getAttrValue(ln, qname("", "w", "")) : null;
7239
+ const bars = {
7240
+ barType,
7241
+ amount,
7242
+ ...noEndCap !== void 0 ? { noEndCap } : {},
7243
+ ...color !== void 0 ? { color } : {},
7244
+ ...w !== null && /^\d+$/.test(w) ? { lineWidthEmu: Number.parseInt(w, 10) } : {}
7245
+ };
7246
+ if (childVal(el, "errDir") === "x") out.xErrorBars ??= bars;
7247
+ else out.errorBars ??= bars;
7248
+ }
7249
+ return out;
7250
+ };
7251
+ const readView3D = (chart) => {
7252
+ const el = firstChildElement(chart, qname("c", "view3D", NS_C));
7253
+ if (el === null) return void 0;
7254
+ const rotX = childNumber(el, "rotX");
7255
+ const rotY = childNumber(el, "rotY");
7256
+ const rightAngleAxes = childBool(el, "rAngAx");
7257
+ const perspective = childNumber(el, "perspective");
7258
+ const depthPercent = childNumber(el, "depthPercent");
7259
+ const heightPercent = childNumber(el, "hPercent");
7260
+ return {
7261
+ ...rotX !== void 0 ? { rotX } : {},
7262
+ ...rotY !== void 0 ? { rotY } : {},
7263
+ ...rightAngleAxes !== void 0 ? { rightAngleAxes } : {},
7264
+ ...perspective !== void 0 ? { perspective } : {},
7265
+ ...depthPercent !== void 0 ? { depthPercent } : {},
7266
+ ...heightPercent !== void 0 ? { heightPercent } : {}
7267
+ };
7268
+ };
7269
+ const readOfPie = (group) => {
7270
+ const type = childToken(group, "ofPieType", ["pie", "bar"]);
7271
+ if (type === void 0) return void 0;
7272
+ const splitType = childToken(group, "splitType", [
7273
+ "auto",
7274
+ "cust",
7275
+ "percent",
7276
+ "pos",
7277
+ "val"
7278
+ ]);
7279
+ const splitPos = childNumber(group, "splitPos");
7280
+ const secondPieSizePct = childNumber(group, "secondPieSize");
7281
+ const gapWidthPct = childNumber(group, "gapWidth");
7282
+ const custSplit = firstChildElement(group, qname("c", "custSplit", NS_C));
7283
+ const customSplit = [];
7284
+ if (custSplit !== null) for (const pt of allChildElements(custSplit, qname("c", "secondPiePt", NS_C))) {
7285
+ const idx = parsePointIndex(getAttrValue(pt, ATTR_VAL), MAX_PT_COUNT);
7286
+ if (idx !== null) customSplit.push(idx);
7287
+ }
7288
+ const seriesLines = firstChildElement(group, qname("c", "serLines", NS_C)) !== null;
7289
+ return {
7290
+ type,
7291
+ ...splitType !== void 0 ? { splitType } : {},
7292
+ ...splitPos !== void 0 ? { splitPos } : {},
7293
+ ...custSplit !== null ? { customSplit } : {},
7294
+ ...secondPieSizePct !== void 0 ? { secondPieSizePct } : {},
7295
+ ...gapWidthPct !== void 0 ? { gapWidthPct } : {},
7296
+ ...seriesLines ? { seriesLines } : {}
7297
+ };
7298
+ };
7299
+ const readUpDownBars = (group) => {
7300
+ const el = firstChildElement(group, qname("c", "upDownBars", NS_C));
7301
+ if (el === null) return void 0;
7302
+ const barColor = (local) => {
7303
+ const bar = firstChildElement(el, qname("c", local, NS_C));
7304
+ return readSolidSrgb(bar !== null ? firstChildElement(bar, NAME_SP_PR_C) : null);
7305
+ };
7306
+ const gapWidthPct = childNumber(el, "gapWidth");
7307
+ const upColor = barColor("upBars");
7308
+ const downColor = barColor("downBars");
7309
+ return {
7310
+ ...gapWidthPct !== void 0 ? { gapWidthPct } : {},
7311
+ ...upColor !== void 0 ? { upColor } : {},
7312
+ ...downColor !== void 0 ? { downColor } : {}
7313
+ };
7314
+ };
7315
+ const readDataTable = (plotArea) => {
7316
+ const el = firstChildElement(plotArea, qname("c", "dTable", NS_C));
7317
+ if (el === null) return void 0;
7318
+ const showHorizontalBorder = childBool(el, "showHorzBorder");
7319
+ const showVerticalBorder = childBool(el, "showVertBorder");
7320
+ const showOutline = childBool(el, "showOutline");
7321
+ const showKeys = childBool(el, "showKeys");
7322
+ const txPr = firstChildElement(el, qname("c", "txPr", NS_C));
7323
+ const textStyle = txPr !== null ? readLabelStyle(txPr) : void 0;
7324
+ return {
7325
+ ...showHorizontalBorder !== void 0 ? { showHorizontalBorder } : {},
7326
+ ...showVerticalBorder !== void 0 ? { showVerticalBorder } : {},
7327
+ ...showOutline !== void 0 ? { showOutline } : {},
7328
+ ...showKeys !== void 0 ? { showKeys } : {},
7329
+ ...textStyle !== void 0 ? { textStyle } : {}
7330
+ };
7331
+ };
7332
+ const TIME_UNITS = [
7333
+ "days",
7334
+ "months",
7335
+ "years"
7336
+ ];
7337
+ const readDateAxis = (dateAx) => {
7338
+ const baseTimeUnit = childToken(dateAx, "baseTimeUnit", TIME_UNITS);
7339
+ const majorUnit = childNumber(dateAx, "majorUnit");
7340
+ const majorTimeUnit = childToken(dateAx, "majorTimeUnit", TIME_UNITS);
7341
+ const minorUnit = childNumber(dateAx, "minorUnit");
7342
+ const minorTimeUnit = childToken(dateAx, "minorTimeUnit", TIME_UNITS);
7343
+ return {
7344
+ ...baseTimeUnit !== void 0 ? { baseTimeUnit } : {},
7345
+ ...majorUnit !== void 0 ? { majorUnit } : {},
7346
+ ...majorTimeUnit !== void 0 ? { majorTimeUnit } : {},
7347
+ ...minorUnit !== void 0 ? { minorUnit } : {},
7348
+ ...minorTimeUnit !== void 0 ? { minorTimeUnit } : {}
7349
+ };
7350
+ };
7351
+ const withoutNumberFormat = (scaling) => {
7352
+ if (scaling === void 0) return void 0;
7353
+ const { numberFormat: _numberFormat, ...rest } = scaling;
7354
+ return Object.keys(rest).length > 0 ? rest : void 0;
7355
+ };
7356
+ const minMaxOnly = (scaling) => {
7357
+ if (scaling?.min === void 0 && scaling?.max === void 0) return void 0;
7358
+ return {
7359
+ ...scaling.min !== void 0 ? { min: scaling.min } : {},
7360
+ ...scaling.max !== void 0 ? { max: scaling.max } : {}
7361
+ };
7362
+ };
7363
+ const isAxisLineHidden = (axis) => {
7364
+ const spPr = firstChildElement(axis, NAME_SP_PR_C);
7365
+ const ln = spPr !== null ? firstChildElement(spPr, qname("a", "ln", NS_A)) : null;
7366
+ return ln !== null && firstChildElement(ln, qname("a", "noFill", NS_A)) !== null;
7367
+ };
7368
+ const readSeriesAxis = (plotArea) => {
7369
+ const el = firstChildElement(plotArea, qname("c", "serAx", NS_C));
7370
+ if (el === null) return void 0;
7371
+ const hidden = childBool(el, "delete");
7372
+ const title = readTitle(el);
7373
+ const titleEl = firstChildElement(el, NAME_TITLE);
7374
+ const titleStyle = titleEl !== null ? readTitleStyleOf(titleEl) : void 0;
7375
+ const txPr = firstChildElement(el, qname("c", "txPr", NS_C));
7376
+ const labelStyle = txPr !== null ? readLabelStyle(txPr) : void 0;
7377
+ const majorGridlines = firstChildElement(el, qname("c", "majorGridlines", NS_C)) !== null;
7378
+ const scaling = firstChildElement(el, qname("c", "scaling", NS_C));
7379
+ const orientation = scaling !== null ? childToken(scaling, "orientation", ["minMax", "maxMin"]) : void 0;
7380
+ const tickLabelPos = childToken(el, "tickLblPos", [
7381
+ "none",
7382
+ "low",
7383
+ "high",
7384
+ "nextTo"
7385
+ ]);
7386
+ const tickLabelSkip = childNumber(el, "tickLblSkip");
7387
+ const spPr = firstChildElement(el, NAME_SP_PR_C);
7388
+ const lineColor = readSolidSrgb(spPr !== null ? firstChildElement(spPr, qname("a", "ln", NS_A)) : null);
7389
+ const fields = {
7390
+ ...hidden === true ? { hidden } : {},
7391
+ ...title !== void 0 ? { title } : {},
7392
+ ...titleStyle !== void 0 ? { titleStyle } : {},
7393
+ ...labelStyle !== void 0 ? { labelStyle } : {},
7394
+ ...majorGridlines ? { majorGridlines } : {},
7395
+ ...orientation === "maxMin" ? { orientation } : {},
7396
+ ...tickLabelPos !== void 0 ? { tickLabelPos } : {},
7397
+ ...tickLabelSkip !== void 0 ? { tickLabelSkip } : {},
7398
+ ...lineColor !== void 0 ? { lineColor } : {}
7399
+ };
7400
+ return Object.keys(fields).length > 0 ? fields : void 0;
7401
+ };
7402
+ const readManualLayout = (host) => {
7403
+ const layout = firstChildElement(host, qname("c", "layout", NS_C));
7404
+ const manual = layout !== null ? firstChildElement(layout, qname("c", "manualLayout", NS_C)) : null;
7405
+ if (manual === null) return void 0;
7406
+ if (childVal(manual, "xMode") !== "edge" || childVal(manual, "yMode") !== "edge") return void 0;
7407
+ const sizeMode = (local) => (childVal(manual, local) ?? "factor") === "factor";
7408
+ if (!sizeMode("wMode") || !sizeMode("hMode")) return void 0;
7409
+ const x = childNumber(manual, "x");
7410
+ const y = childNumber(manual, "y");
7411
+ if (x === void 0 || y === void 0) return void 0;
7412
+ const w = childNumber(manual, "w");
7413
+ const h = childNumber(manual, "h");
7414
+ const target = childToken(manual, "layoutTarget", ["inner", "outer"]);
7415
+ return {
7416
+ x,
7417
+ y,
7418
+ ...w !== void 0 ? { w } : {},
7419
+ ...h !== void 0 ? { h } : {},
7420
+ ...target !== void 0 ? { target } : {}
7421
+ };
7422
+ };
7423
+ const readBoxLayout = (host) => {
7424
+ const layout = readManualLayout(host);
7425
+ if (layout === void 0 || layout.w === void 0 || layout.h === void 0) return void 0;
7426
+ return {
7427
+ x: layout.x,
7428
+ y: layout.y,
7429
+ w: layout.w,
7430
+ h: layout.h,
7431
+ ...layout.target !== void 0 ? { target: layout.target } : {}
6394
7432
  };
6395
7433
  };
7434
+ const readCategoryGroupLevels = (cat) => {
7435
+ const multi = firstChildElement(cat, NAME_MULTI_LVL_STR_REF);
7436
+ const cache = multi !== null ? firstChildElement(multi, NAME_MULTI_LVL_STR_CACHE) : null;
7437
+ if (cache === null) return void 0;
7438
+ const outer = allChildElements(cache, NAME_LVL).slice(1).map((lvl) => readPtArray(lvl, cache));
7439
+ return outer.length > 0 ? outer : void 0;
7440
+ };
6396
7441
  /**
6397
7442
  * Parses a `<c:chartSpace>` element into a typed `ChartSpec`. Throws if
6398
7443
  * the root or any required child is missing. Returns `null` only when
@@ -6445,6 +7490,7 @@ const readChartSpec = (root) => {
6445
7490
  const groupUsesSecondaryAxis = (group) => groupAxisIds(group).some((id) => secondaryValAxisIds.has(id));
6446
7491
  const series = [];
6447
7492
  let categoriesFromFirst = null;
7493
+ let categoryGroupLevels;
6448
7494
  const serEntries = [];
6449
7495
  for (const group of plotGroups) {
6450
7496
  const secondary = groupUsesSecondaryAxis(group.element);
@@ -6459,6 +7505,7 @@ const readChartSpec = (root) => {
6459
7505
  const cat = firstChildElement(ser, NAME_CAT);
6460
7506
  if (cat !== null && categoriesFromFirst === null) {
6461
7507
  categoriesFromFirst = readStringRef(cat) ?? null;
7508
+ categoryGroupLevels = readCategoryGroupLevels(cat);
6462
7509
  if (categoriesFromFirst === null) {
6463
7510
  const nums = readNumRef(cat);
6464
7511
  if (nums !== null) categoriesFromFirst = nums.map((n) => n === null || !Number.isFinite(n) ? "" : String(n));
@@ -6481,6 +7528,8 @@ const readChartSpec = (root) => {
6481
7528
  const smoothEl = firstChildElement(ser, qname("c", "smooth", NS_C));
6482
7529
  const smooth = smoothEl !== null && readXmlBool(smoothEl);
6483
7530
  const trendline = readTrendline(ser);
7531
+ const fillOpacity = readSeriesFillOpacity(ser);
7532
+ const { errorBars, xErrorBars } = readErrorBars(ser);
6484
7533
  const serDLblsEl = firstChildElement(ser, NAME_D_LBLS);
6485
7534
  const serDataLabels = serDLblsEl !== null && hasDataLabelGroupChild(serDLblsEl) ? readSeriesLevelDataLabels(serDLblsEl) : void 0;
6486
7535
  const pointDataLabels = serDLblsEl !== null ? readPointDataLabels(serDLblsEl, pointCount, serDataLabels) : void 0;
@@ -6505,7 +7554,10 @@ const readChartSpec = (root) => {
6505
7554
  ...pointDataLabels !== void 0 ? { pointDataLabels } : {},
6506
7555
  ...smoothEl !== null ? { smooth } : {},
6507
7556
  ...trendline !== void 0 ? { trendline } : {},
6508
- ...serDataLabels !== void 0 ? { dataLabels: serDataLabels } : {}
7557
+ ...serDataLabels !== void 0 ? { dataLabels: serDataLabels } : {},
7558
+ ...fillOpacity !== void 0 ? { fillOpacity } : {},
7559
+ ...errorBars !== void 0 ? { errorBars } : {},
7560
+ ...xErrorBars !== void 0 ? { xErrorBars } : {}
6509
7561
  });
6510
7562
  }
6511
7563
  const categories = categoriesFromFirst ?? [];
@@ -6525,6 +7577,22 @@ const readChartSpec = (root) => {
6525
7577
  valAx = secValAx;
6526
7578
  secValAx = null;
6527
7579
  }
7580
+ const isXyKind = kind === "scatter" || kind === "bubble";
7581
+ let xValAx = null;
7582
+ if (isXyKind) {
7583
+ const [xId, yId] = groupAxisIds(plotted);
7584
+ const valAxById = /* @__PURE__ */ new Map();
7585
+ for (const el of allChildElements(plotArea, NAME_VAL_AX)) {
7586
+ const id = childVal(el, "axId");
7587
+ if (id !== null) valAxById.set(id, el);
7588
+ }
7589
+ const x = xId !== void 0 ? valAxById.get(xId) : void 0;
7590
+ const y = yId !== void 0 ? valAxById.get(yId) : void 0;
7591
+ if (x !== void 0 && y !== void 0) {
7592
+ xValAx = x;
7593
+ valAx = y;
7594
+ }
7595
+ }
6528
7596
  const valueAxis = valAx !== null ? readValueAxisScaling(valAx) : void 0;
6529
7597
  let grouping;
6530
7598
  if (kind === "column" || kind === "bar" || kind === "area" || kind === "line") {
@@ -6641,11 +7709,7 @@ const readChartSpec = (root) => {
6641
7709
  const v = getAttrValue(srgb, ATTR_VAL);
6642
7710
  return v !== null ? `#${v.toUpperCase()}` : void 0;
6643
7711
  };
6644
- const catAx = findFirst(plotArea, [
6645
- "catAx",
6646
- "dateAx",
6647
- "serAx"
6648
- ]);
7712
+ const catAx = xValAx ?? findFirst(plotArea, ["catAx", "dateAx"]);
6649
7713
  const isHidden = (axis) => {
6650
7714
  const d = firstChildElement(axis, qname("c", "delete", NS_C));
6651
7715
  if (!d) return void 0;
@@ -6939,9 +8003,12 @@ const readChartSpec = (root) => {
6939
8003
  const n = Number.parseInt(idxV, 10);
6940
8004
  if (Number.isFinite(n) && n >= 0) hiddenIndices.push(n);
6941
8005
  }
8006
+ const position = tok === "r" || tok === "t" || tok === "b" || tok === "l" || tok === "tr" ? tok : "r";
8007
+ const legendLayout = readBoxLayout(legendEl);
6942
8008
  legend = {
6943
- position: tok === "r" || tok === "t" || tok === "b" || tok === "l" || tok === "tr" ? tok : "r",
8009
+ position,
6944
8010
  ...overlay ? { overlay } : {},
8011
+ ...legendLayout !== void 0 ? { layout: legendLayout } : {},
6945
8012
  ...textStyle !== void 0 ? { textStyle } : {},
6946
8013
  ...hiddenIndices.length > 0 ? { hiddenIndices } : {}
6947
8014
  };
@@ -7012,6 +8079,38 @@ const readChartSpec = (root) => {
7012
8079
  else if (v === "w") bubbleSizeRepresents = "width";
7013
8080
  }
7014
8081
  }
8082
+ const plottedName = plotted.name.localName;
8083
+ const view3DEl = readView3D(chart);
8084
+ const view3D = plottedName.endsWith("3DChart") || kind === "surface" ? view3DEl : void 0;
8085
+ const bar3DShape = plottedName === "bar3DChart" ? childToken(plotted, "shape", [
8086
+ "box",
8087
+ "cone",
8088
+ "coneToMax",
8089
+ "cylinder",
8090
+ "pyramid",
8091
+ "pyramidToMax"
8092
+ ]) : void 0;
8093
+ const gapDepthPct = view3D !== void 0 ? childNumber(plotted, "gapDepth") : void 0;
8094
+ const bubble3D = kind === "bubble" && allChildElements(plotted, NAME_SER).some((ser) => childBool(ser, "bubble3D") === true);
8095
+ const showNegativeBubbles = kind === "bubble" ? childBool(plotted, "showNegBubbles") : void 0;
8096
+ const ofPie = plottedName === "ofPieChart" ? readOfPie(plotted) : void 0;
8097
+ const surfaceContour = plottedName === "surfaceChart";
8098
+ const surfaceWireframe = kind === "surface" ? childBool(plotted, "wireframe") : void 0;
8099
+ const upDownBars = readUpDownBars(plotted);
8100
+ const dataTable = readDataTable(plotArea);
8101
+ const seriesAxis = readSeriesAxis(plotArea);
8102
+ const plotAreaLayout = readBoxLayout(plotArea);
8103
+ const chartTitleEl = firstChildElement(chart, NAME_TITLE);
8104
+ const titlePosition = chartTitleEl !== null ? readManualLayout(chartTitleEl) : void 0;
8105
+ const titleLayout = titlePosition !== void 0 ? {
8106
+ x: titlePosition.x,
8107
+ y: titlePosition.y
8108
+ } : void 0;
8109
+ const categoryAxisDate = catAx !== null && catAx.name.localName === "dateAx" ? readDateAxis(catAx) : void 0;
8110
+ const horizontalScaling = catAx !== null ? readValueAxisScaling(catAx) : void 0;
8111
+ const categoryAxisScaling = isXyKind ? withoutNumberFormat(horizontalScaling) : categoryAxisDate !== void 0 ? minMaxOnly(horizontalScaling) : void 0;
8112
+ const valueAxisLineHidden = valAx !== null && isAxisLineHidden(valAx);
8113
+ const categoryAxisLineHidden = catAx !== null && isAxisLineHidden(catAx);
7015
8114
  return {
7016
8115
  kind,
7017
8116
  categories,
@@ -7089,80 +8188,28 @@ const readChartSpec = (root) => {
7089
8188
  ...scatterStyle !== void 0 ? { scatterStyle } : {},
7090
8189
  ...radarStyle !== void 0 ? { radarStyle } : {},
7091
8190
  ...bubbleScale !== void 0 ? { bubbleScale } : {},
7092
- ...bubbleSizeRepresents !== void 0 ? { bubbleSizeRepresents } : {}
8191
+ ...bubbleSizeRepresents !== void 0 ? { bubbleSizeRepresents } : {},
8192
+ ...bubble3D === true ? { bubble3D } : {},
8193
+ ...showNegativeBubbles !== void 0 ? { showNegativeBubbles } : {},
8194
+ ...view3D !== void 0 ? { view3D } : {},
8195
+ ...bar3DShape !== void 0 ? { bar3DShape } : {},
8196
+ ...gapDepthPct !== void 0 ? { gapDepthPct } : {},
8197
+ ...seriesAxis !== void 0 ? { seriesAxis } : {},
8198
+ ...ofPie !== void 0 ? { ofPie } : {},
8199
+ ...surfaceContour ? { surfaceContour } : {},
8200
+ ...surfaceWireframe !== void 0 ? { surfaceWireframe } : {},
8201
+ ...upDownBars !== void 0 ? { upDownBars } : {},
8202
+ ...dataTable !== void 0 ? { dataTable } : {},
8203
+ ...categoryAxisDate !== void 0 ? { categoryAxisDate } : {},
8204
+ ...categoryAxisScaling !== void 0 ? { categoryAxisScaling } : {},
8205
+ ...categoryGroupLevels !== void 0 ? { categoryGroupLevels } : {},
8206
+ ...plotAreaLayout !== void 0 ? { plotAreaLayout } : {},
8207
+ ...titleLayout !== void 0 ? { titleLayout } : {},
8208
+ ...valueAxisLineHidden ? { valueAxisLineHidden } : {},
8209
+ ...categoryAxisLineHidden ? { categoryAxisLineHidden } : {}
7093
8210
  };
7094
8211
  };
7095
8212
  //#endregion
7096
- //#region src/internal/chartml/embedded-xlsx.ts
7097
- const TEXT_ENCODER = new TextEncoder();
7098
- const encode = (s) => TEXT_ENCODER.encode(s);
7099
- const xmlEscape = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
7100
- const colLetter = (col) => {
7101
- let n = col;
7102
- let out = "";
7103
- while (true) {
7104
- out = String.fromCharCode(65 + n % 26) + out;
7105
- if (n < 26) return out;
7106
- n = Math.floor(n / 26) - 1;
7107
- }
7108
- };
7109
- const cellRef = (row, col) => `${colLetter(col)}${row + 1}`;
7110
- /**
7111
- * Builds the bytes of a fresh xlsx whose only sheet is laid out as
7112
- *
7113
- * | | seriesNames[0] | seriesNames[1] | ...
7114
- * |-------|----------------|----------------|----
7115
- * | row0 | row0.values[0] | row0.values[1] | ...
7116
- * | row1 | row1.values[0] | ... | ...
7117
- *
7118
- * Header row is row 1 in the sheet (1-indexed). The first column carries
7119
- * category labels; subsequent columns carry series values.
7120
- */
7121
- const buildEmbeddedXlsx = (seriesNames, rows) => {
7122
- const sheetXmlParts = [];
7123
- sheetXmlParts.push("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">", "<sheetData>");
7124
- sheetXmlParts.push("<row r=\"1\">");
7125
- sheetXmlParts.push(`<c r="${cellRef(0, 0)}" t="inlineStr"><is><t></t></is></c>`);
7126
- for (let i = 0; i < seriesNames.length; i++) sheetXmlParts.push(`<c r="${cellRef(0, i + 1)}" t="inlineStr"><is><t>${xmlEscape(seriesNames[i] ?? "")}</t></is></c>`);
7127
- sheetXmlParts.push("</row>");
7128
- for (let r = 0; r < rows.length; r++) {
7129
- const row = rows[r];
7130
- const rowIdx = r + 1;
7131
- sheetXmlParts.push(`<row r="${rowIdx + 1}">`);
7132
- sheetXmlParts.push(`<c r="${cellRef(rowIdx, 0)}" t="inlineStr"><is><t>${xmlEscape(row.label)}</t></is></c>`);
7133
- for (let i = 0; i < row.values.length; i++) {
7134
- const v = row.values[i];
7135
- if (v === null || v === void 0) continue;
7136
- sheetXmlParts.push(`<c r="${cellRef(rowIdx, i + 1)}"><v>${v}</v></c>`);
7137
- }
7138
- sheetXmlParts.push("</row>");
7139
- }
7140
- sheetXmlParts.push("</sheetData></worksheet>");
7141
- const sheetXml = sheetXmlParts.join("");
7142
- return writeZip([
7143
- {
7144
- name: "[Content_Types].xml",
7145
- data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/><Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/></Types>")
7146
- },
7147
- {
7148
- name: "_rels/.rels",
7149
- data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/></Relationships>")
7150
- },
7151
- {
7152
- name: "xl/workbook.xml",
7153
- data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>")
7154
- },
7155
- {
7156
- name: "xl/_rels/workbook.xml.rels",
7157
- data: encode("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/></Relationships>")
7158
- },
7159
- {
7160
- name: "xl/worksheets/sheet1.xml",
7161
- data: encode(sheetXml)
7162
- }
7163
- ]);
7164
- };
7165
- //#endregion
7166
8213
  //#region src/api/fn/slide-background.ts
7167
8214
  const setSlideBackgroundXml = (slide, configure) => {
7168
8215
  const cSld = firstChildElement(slide[SLIDE_DOCUMENT].root, NAME_CSLD);
@@ -8138,12 +9185,22 @@ const validateChartSpecColors = (spec) => {
8138
9185
  checkChartColor(spec.categoryAxisLineColor, "addSlideChart: categoryAxisLineColor");
8139
9186
  checkChartColor(spec.secondaryValueAxis?.majorGridlineColor, "addSlideChart: secondaryValueAxis.majorGridlineColor");
8140
9187
  checkChartColor(spec.secondaryValueAxis?.lineColor, "addSlideChart: secondaryValueAxis.lineColor");
9188
+ checkChartColor(spec.dataLabels?.fillColor, "addSlideChart: dataLabels.fillColor");
9189
+ checkChartColor(spec.upDownBars?.upColor, "addSlideChart: upDownBars.upColor");
9190
+ checkChartColor(spec.upDownBars?.downColor, "addSlideChart: upDownBars.downColor");
9191
+ checkChartColor(spec.seriesAxis?.lineColor, "addSlideChart: seriesAxis.lineColor");
8141
9192
  spec.series.forEach((series, i) => {
8142
9193
  checkChartColor(series.color, `addSlideChart: series[${i}].color`);
8143
9194
  checkChartColor(series.lineColor, `addSlideChart: series[${i}].lineColor`);
8144
9195
  checkChartColor(series.markerColor, `addSlideChart: series[${i}].markerColor`);
8145
9196
  checkChartColor(series.markerLineColor, `addSlideChart: series[${i}].markerLineColor`);
8146
9197
  checkChartColor(series.trendline?.color, `addSlideChart: series[${i}].trendline.color`);
9198
+ checkChartColor(series.errorBars?.color, `addSlideChart: series[${i}].errorBars.color`);
9199
+ checkChartColor(series.xErrorBars?.color, `addSlideChart: series[${i}].xErrorBars.color`);
9200
+ checkChartColor(series.dataLabels?.fillColor, `addSlideChart: series[${i}].dataLabels.fillColor`);
9201
+ series.pointDataLabels?.forEach((label, j) => {
9202
+ checkChartColor(label?.fillColor, `addSlideChart: series[${i}].pointDataLabels[${j}].fillColor`);
9203
+ });
8147
9204
  series.pointColors?.forEach((c, j) => {
8148
9205
  checkChartColor(c, `addSlideChart: series[${i}].pointColors[${j}]`);
8149
9206
  });
@@ -8154,9 +9211,10 @@ const validateChartSpecAxes = (spec) => {
8154
9211
  };
8155
9212
  /**
8156
9213
  * Adds a chart to the slide. Returns the new shape handle (kind
8157
- * `graphicFrame`). Authorable chart kinds: `bar`, `column`, `line`,
8158
- * `pie`, `doughnut`, `area`. `scatter`, `radar` and `bubble` are read +
8159
- * render only and are rejected here — see `ChartKind`.
9214
+ * `graphicFrame`). Every `ChartKind` is authorable, and the `view3D` /
9215
+ * `ofPie` / `surfaceContour` modifiers reach the remaining plot-group
9216
+ * elements (3-D bar / line / area / pie, pie-of-pie, contour) — see the
9217
+ * table on `ChartKind`.
8160
9218
  *
8161
9219
  * Side effects:
8162
9220
  *
@@ -8170,9 +9228,15 @@ const validateChartSpecAxes = (spec) => {
8170
9228
  *
8171
9229
  * Constraints:
8172
9230
  *
8173
- * - `pie` charts require exactly one series.
8174
- * - All series should have at most `categories.length` values; missing
8175
- * values are treated as blanks (gaps in the visualization).
9231
+ * - `pie` / `doughnut` charts require exactly one series; `stock`
9232
+ * charts exactly three (high, low, close) or four (open first).
9233
+ * - `scatter` / `bubble` series carry their own `xValues` (and
9234
+ * `bubbleSizes`); `categories` is unused for them.
9235
+ * - All other series should have at most `categories.length` values;
9236
+ * missing values are treated as blanks (gaps in the visualization).
9237
+ * - A spec whose fields contradict each other (e.g. `view3D` on a
9238
+ * scatter chart, error bars on a pie) throws instead of writing a
9239
+ * chart PowerPoint would repair.
8176
9240
  */
8177
9241
  const withChartDefaultTextColor = (spec, color) => {
8178
9242
  if (color === null) return spec;
@@ -8210,11 +9274,7 @@ const addSlideChart = (slide, opts) => {
8210
9274
  const chartN = allocateChartIndex(pkg);
8211
9275
  const chartPartName = partName(`/ppt/charts/chart${chartN}.xml`);
8212
9276
  const xlsxPartName = partName(`/ppt/embeddings/Microsoft_Excel_Worksheet${chartN}.xlsx`);
8213
- const xlsxRows = spec.categories.map((label, i) => ({
8214
- label,
8215
- values: spec.series.map((s) => s.values[i] ?? null)
8216
- }));
8217
- const xlsxBytes = buildEmbeddedXlsx(spec.series.map((s) => s.name), xlsxRows);
9277
+ const xlsxBytes = buildEmbeddedXlsx(layoutChartSheet(spec).grid);
8218
9278
  const chartBytes = encode$1(serializeXml(buildChartSpaceDoc(spec)));
8219
9279
  pkg.addPart(chartPartName, CHART_CONTENT_TYPE, chartBytes);
8220
9280
  pkg.addPart(xlsxPartName, EMBEDDED_XLSX_CONTENT_TYPE, xlsxBytes);
@@ -8304,12 +9364,7 @@ const setChartSpec = (chart, spec) => {
8304
9364
  if (xlsxRel) {
8305
9365
  const xlsxName = xlsxRel.target.startsWith("/") ? partName(xlsxRel.target) : resolveTarget(resolved.partName, xlsxRel.target);
8306
9366
  const xlsxPart = pkg.getPart(xlsxName);
8307
- const rows = spec.categories.map((label, i) => ({
8308
- label,
8309
- values: spec.series.map((s) => s.values[i] ?? null)
8310
- }));
8311
- const xlsxBytes = buildEmbeddedXlsx(spec.series.map((s) => s.name), rows);
8312
- if (xlsxPart) xlsxPart.data = xlsxBytes;
9367
+ if (xlsxPart) xlsxPart.data = buildEmbeddedXlsx(layoutChartSheet(spec).grid);
8313
9368
  }
8314
9369
  }
8315
9370
  };
@@ -8464,7 +9519,9 @@ const getPresentationChartKindCounts = (pres) => {
8464
9519
  area: 0,
8465
9520
  scatter: 0,
8466
9521
  radar: 0,
8467
- bubble: 0
9522
+ bubble: 0,
9523
+ stock: 0,
9524
+ surface: 0
8468
9525
  };
8469
9526
  for (const slide of getSlides(pres)) for (const chart of getSlideCharts(slide)) {
8470
9527
  if (chart.spec === null) continue;
@@ -10397,7 +11454,7 @@ const PRES_PART = partName("/ppt/presentation.xml");
10397
11454
  const PRES_RELS = partName("/ppt/_rels/presentation.xml.rels");
10398
11455
  const NAME_SLD_ID_LST = qname("p", "sldIdLst", NS.pml);
10399
11456
  const NAME_SLD_ID = qname("p", "sldId", NS.pml);
10400
- const ATTR_ID = qname("", "id", "");
11457
+ const ATTR_ID$1 = qname("", "id", "");
10401
11458
  const ATTR_R_ID = qname("r", "id", NS.officeDocRels);
10402
11459
  const decoder = new TextDecoder();
10403
11460
  const decode = (b) => decoder.decode(b);
@@ -10444,7 +11501,7 @@ const validatePresentationPackage = (pkg) => {
10444
11501
  const seenRIds = /* @__PURE__ */ new Set();
10445
11502
  const slidePartNames = [];
10446
11503
  if (sldIdLst !== null) for (const sldId of allChildElements(sldIdLst, NAME_SLD_ID)) {
10447
- const idRaw = getAttrValue(sldId, ATTR_ID);
11504
+ const idRaw = getAttrValue(sldId, ATTR_ID$1);
10448
11505
  const rIdRaw = getAttrValue(sldId, ATTR_R_ID);
10449
11506
  if (idRaw === null) {
10450
11507
  issues.push({
@@ -10548,7 +11605,7 @@ const validatePresentationPackage = (pkg) => {
10548
11605
  });
10549
11606
  for (const rel of slideRels.items) {
10550
11607
  if (rel.targetMode === "External") continue;
10551
- if (rel.type !== REL_TYPES.image && rel.type !== REL_TYPES.chart && rel.type !== REL_TYPES.notesSlide && rel.type !== REL_TYPES.comments && rel.type !== REL_TYPES.oleObject && rel.type !== REL_TYPES.package) continue;
11608
+ if (rel.type !== REL_TYPES.image && rel.type !== REL_TYPES.media && rel.type !== REL_TYPES.video && rel.type !== REL_TYPES.audio && rel.type !== REL_TYPES.chart && rel.type !== REL_TYPES.notesSlide && rel.type !== REL_TYPES.comments && rel.type !== REL_TYPES.oleObject && rel.type !== REL_TYPES.package) continue;
10552
11609
  const targetName = targetPartName(slideName, rel);
10553
11610
  if (pkg.getPart(targetName) === null) issues.push({
10554
11611
  severity: "error",
@@ -10582,7 +11639,7 @@ const validatePresentationPackage = (pkg) => {
10582
11639
  if (!nvHost) continue;
10583
11640
  const cNvPr = firstChildElement(nvHost, qname("p", "cNvPr", NS.pml));
10584
11641
  if (!cNvPr) continue;
10585
- const id = getAttrValue(cNvPr, ATTR_ID);
11642
+ const id = getAttrValue(cNvPr, ATTR_ID$1);
10586
11643
  if (id === null) continue;
10587
11644
  seenShapeIds.set(id, (seenShapeIds.get(id) ?? 0) + 1);
10588
11645
  }
@@ -10593,6 +11650,23 @@ const validatePresentationPackage = (pkg) => {
10593
11650
  message: `duplicate shape id="${id}" appears ${count}× in slide ${slideName}`,
10594
11651
  partName: slideName
10595
11652
  });
11653
+ const timing = firstChildElement(slideRoot, qname("p", "timing", NS.pml));
11654
+ const checkMediaNodes = (host) => {
11655
+ for (const child of host.children) {
11656
+ if (child.kind !== "element") continue;
11657
+ if (!isMediaTimingNode(child)) {
11658
+ checkMediaNodes(child);
11659
+ continue;
11660
+ }
11661
+ const target = mediaTimingNodeTarget(child);
11662
+ if (target !== null && !seenShapeIds.has(String(target))) issues.push({
11663
+ severity: "error",
11664
+ message: `media time node in slide ${slideName} targets missing shape id="${target}"`,
11665
+ partName: slideName
11666
+ });
11667
+ }
11668
+ };
11669
+ if (timing) checkMediaNodes(timing);
10596
11670
  }
10597
11671
  for (const part of pkg.parts) {
10598
11672
  if (part.contentType !== "application/vnd.openxmlformats-officedocument.drawingml.chart+xml") continue;
@@ -12066,6 +13140,83 @@ const setShapeImageCrop = (shape, crop) => {
12066
13140
  commitAndRefresh(shape);
12067
13141
  };
12068
13142
  //#endregion
13143
+ //#region src/api/fn/_media-timing.ts
13144
+ const NAME_TIMING = qname("p", "timing", NS.pml);
13145
+ const NAME_TN_LST = qname("p", "tnLst", NS.pml);
13146
+ const NAME_PAR = qname("p", "par", NS.pml);
13147
+ const NAME_C_TN = qname("p", "cTn", NS.pml);
13148
+ const NAME_CHILD_TN_LST = qname("p", "childTnLst", NS.pml);
13149
+ const NAME_EXT_LST$1 = qname("p", "extLst", NS.pml);
13150
+ const ATTR_ID = qname("", "id", "");
13151
+ const findSlideTiming = (slide) => firstChildElement(slide[SLIDE_DOCUMENT].root, NAME_TIMING);
13152
+ const insertSlideTiming = (slide, timing) => {
13153
+ const root = slide[SLIDE_DOCUMENT].root;
13154
+ const extLst = firstChildElement(root, NAME_EXT_LST$1);
13155
+ if (extLst === null) root.children.push(timing);
13156
+ else root.children.splice(root.children.indexOf(extLst), 0, timing);
13157
+ };
13158
+ /** The root time node's `<p:childTnLst>` — where media nodes and sequences live. */
13159
+ const rootChildTnLst = (timing) => {
13160
+ const tnLst = firstChildElement(timing, NAME_TN_LST);
13161
+ const par = tnLst ? firstChildElement(tnLst, NAME_PAR) : null;
13162
+ const cTn = par ? firstChildElement(par, NAME_C_TN) : null;
13163
+ return cTn ? firstChildElement(cTn, NAME_CHILD_TN_LST) : null;
13164
+ };
13165
+ const maxCTnId = (el) => {
13166
+ let max = 0;
13167
+ const walk = (e) => {
13168
+ if (e.name.namespaceURI === NS.pml && e.name.localName === "cTn") {
13169
+ const n = Number.parseInt(getAttrValue(e, ATTR_ID) ?? "", 10);
13170
+ if (Number.isFinite(n) && n > max) max = n;
13171
+ }
13172
+ for (const c of e.children) if (c.kind === "element") walk(c);
13173
+ };
13174
+ walk(el);
13175
+ return max;
13176
+ };
13177
+ /** Adds the media time node for shape `spid`. The caller commits the slide. */
13178
+ const addMediaTimingNode = (slide, kind, spid) => {
13179
+ const timing = findSlideTiming(slide);
13180
+ if (timing === null) {
13181
+ insertSlideTiming(slide, buildTimingRoot([buildMediaTimingNode(kind, spid, 2)]));
13182
+ return;
13183
+ }
13184
+ const node = buildMediaTimingNode(kind, spid, maxCTnId(timing) + 1);
13185
+ const childTnLst = rootChildTnLst(timing);
13186
+ if (childTnLst !== null) {
13187
+ childTnLst.children.push(node);
13188
+ return;
13189
+ }
13190
+ const fresh = buildTimingRoot([node]);
13191
+ const rest = timing.children.filter((c) => !(c.kind === "element" && c.name.namespaceURI === NS.pml && c.name.localName === "tnLst"));
13192
+ timing.children = [...fresh.children, ...rest];
13193
+ };
13194
+ /**
13195
+ * Removes the media nodes targeting any of `spids`, and the whole `<p:timing>`
13196
+ * when that leaves the root without children (an empty `<p:childTnLst>` is
13197
+ * schema-invalid and an empty root animates nothing). The caller commits.
13198
+ */
13199
+ const removeMediaTimingNodes = (slide, spids) => {
13200
+ const timing = findSlideTiming(slide);
13201
+ const childTnLst = timing ? rootChildTnLst(timing) : null;
13202
+ if (timing === null || childTnLst === null) return;
13203
+ childTnLst.children = childTnLst.children.filter((c) => {
13204
+ if (c.kind !== "element" || !isMediaTimingNode(c)) return true;
13205
+ const target = mediaTimingNodeTarget(c);
13206
+ return target === null || !spids.has(target);
13207
+ });
13208
+ if (!childTnLst.children.some((c) => c.kind === "element")) {
13209
+ const root = slide[SLIDE_DOCUMENT].root;
13210
+ root.children = root.children.filter((c) => c !== timing);
13211
+ }
13212
+ };
13213
+ /** Media nodes at the timing root, in document order. */
13214
+ const mediaTimingNodes = (timing) => {
13215
+ const childTnLst = rootChildTnLst(timing);
13216
+ if (childTnLst === null) return [];
13217
+ return childTnLst.children.filter((c) => c.kind === "element" && isMediaTimingNode(c));
13218
+ };
13219
+ //#endregion
12069
13220
  //#region src/api/fn/shape-animation.ts
12070
13221
  NS.pml;
12071
13222
  const ATTR_ID_FN = qname("", "id", "");
@@ -12085,18 +13236,6 @@ const findDescendant = (el, pred) => {
12085
13236
  return null;
12086
13237
  };
12087
13238
  const isPml = (el, local) => el.name.namespaceURI === NS.pml && el.name.localName === local;
12088
- const maxCTnId = (el) => {
12089
- let max = 0;
12090
- const walk = (e) => {
12091
- if (isPml(e, "cTn")) {
12092
- const n = Number.parseInt(getAttrValue(e, ATTR_ID_FN) ?? "", 10);
12093
- if (Number.isFinite(n) && n > max) max = n;
12094
- }
12095
- for (const c of e.children) if (c.kind === "element") walk(c);
12096
- };
12097
- walk(el);
12098
- return max;
12099
- };
12100
13239
  const shiftCTnIds = (el, offset) => {
12101
13240
  const walk = (e) => {
12102
13241
  if (isPml(e, "cTn")) {
@@ -12130,29 +13269,40 @@ const setGrpId = (el, grpId) => {
12130
13269
  value: grpId
12131
13270
  } : a);
12132
13271
  };
13272
+ const isMainSeqCTn = (e) => isPml(e, "cTn") && getAttrValue(e, qname("", "nodeType", "")) === "mainSeq";
12133
13273
  const mergeEffectInto = (existing, fresh) => {
12134
- const existingMainSeqChildTnLst = (() => {
12135
- const mainSeq = findDescendant(existing, (e) => isPml(e, "cTn") && getAttrValue(e, qname("", "nodeType", "")) === "mainSeq");
12136
- return mainSeq ? firstChildElement(mainSeq, qname("p", "childTnLst", NS.pml)) : null;
12137
- })();
12138
- if (!existingMainSeqChildTnLst) return false;
12139
- const freshMainSeq = findDescendant(fresh, (e) => isPml(e, "cTn") && getAttrValue(e, qname("", "nodeType", "")) === "mainSeq");
13274
+ const freshMainSeq = findDescendant(fresh, isMainSeqCTn);
12140
13275
  const freshChildTnLst = freshMainSeq ? firstChildElement(freshMainSeq, qname("p", "childTnLst", NS.pml)) : null;
12141
13276
  const newPar = freshChildTnLst ? freshChildTnLst.children.find((c) => c.kind === "element" && isPml(c, "par")) : null;
12142
13277
  const freshBldP = findDescendant(fresh, (e) => isPml(e, "bldP"));
12143
13278
  if (!newPar || !freshBldP) return false;
12144
- const offset = maxCTnId(existing) - 2;
12145
- if (offset > 0) shiftCTnIds(newPar, offset);
12146
13279
  const newGrpId = String(maxGrpId(existing) + 1);
12147
13280
  const effectCTn = findDescendant(newPar, (e) => getAttrValue(e, qname("", "presetID", "")) !== null);
13281
+ const existingMainSeq = findDescendant(existing, isMainSeqCTn);
13282
+ const existingMainSeqChildTnLst = existingMainSeq ? firstChildElement(existingMainSeq, qname("p", "childTnLst", NS.pml)) : null;
13283
+ if (existingMainSeqChildTnLst) {
13284
+ const offset = maxCTnId(existing) - 2;
13285
+ if (offset > 0) shiftCTnIds(newPar, offset);
13286
+ existingMainSeqChildTnLst.children.push(newPar);
13287
+ } else {
13288
+ const rootList = rootChildTnLst(existing);
13289
+ const freshSeq = rootChildTnLst(fresh)?.children.find((c) => c.kind === "element" && isPml(c, "seq"));
13290
+ if (!rootList || !freshSeq) return false;
13291
+ shiftCTnIds(freshSeq, maxCTnId(existing) - 1);
13292
+ rootList.children.unshift(freshSeq);
13293
+ }
12148
13294
  if (effectCTn) setGrpId(effectCTn, newGrpId);
12149
13295
  setGrpId(freshBldP, newGrpId);
12150
- existingMainSeqChildTnLst.children.push(newPar);
12151
13296
  const existingBldLst = findDescendant(existing, (e) => isPml(e, "bldLst"));
12152
13297
  if (existingBldLst) existingBldLst.children.push(freshBldP);
12153
- else existing.children.push(elem(qname("p", "bldLst", NS.pml), { children: [freshBldP] }));
13298
+ else insertBldLst(existing, elem(qname("p", "bldLst", NS.pml), { children: [freshBldP] }));
12154
13299
  return true;
12155
13300
  };
13301
+ const insertBldLst = (timing, bldLst) => {
13302
+ const extLst = firstChildElement(timing, qname("p", "extLst", NS.pml));
13303
+ if (extLst === null) timing.children.push(bldLst);
13304
+ else timing.children.splice(timing.children.indexOf(extLst), 0, bldLst);
13305
+ };
12156
13306
  /**
12157
13307
  * Sets a single click-triggered animation effect on the given shape.
12158
13308
  *
@@ -12240,7 +13390,12 @@ const findShapesWithAnimation = (slide) => {
12240
13390
  return out;
12241
13391
  };
12242
13392
  const clearSlideAnimations = (slide) => {
12243
- removeExistingTiming(slide);
13393
+ const existing = findTiming(slide);
13394
+ const mediaNodes = existing ? mediaTimingNodes(existing) : [];
13395
+ if (existing !== null && mediaNodes.length > 0) {
13396
+ const root = slide[SLIDE_DOCUMENT].root;
13397
+ root.children[root.children.indexOf(existing)] = buildTimingRoot(mediaNodes);
13398
+ } else removeExistingTiming(slide);
12244
13399
  commitSlideData(slide);
12245
13400
  refreshSlideData(slide);
12246
13401
  };
@@ -15791,7 +16946,8 @@ const copyShape = (targetSlide, sourceShape) => {
15791
16946
  const pkg = targetSlide[INTERNAL_PACKAGE];
15792
16947
  const sourceEl = sourceShape[SHAPE_ELEMENT];
15793
16948
  const cloned = cloneXmlElement(sourceEl);
15794
- rewriteCNvPrId(cloned, nextShapeId(targetSlide));
16949
+ const newId = nextShapeId(targetSlide);
16950
+ rewriteCNvPrId(cloned, newId);
15795
16951
  const sourceRels = pkg.getRels(sourceSlide[SLIDE_PART_NAME]);
15796
16952
  if (sourceRels) {
15797
16953
  const targetRels = pkg.getRels(targetSlide[SLIDE_PART_NAME]) ?? emptyRels();
@@ -15811,6 +16967,8 @@ const copyShape = (targetSlide, sourceShape) => {
15811
16967
  });
15812
16968
  pkg.setRels(targetSlide[SLIDE_PART_NAME], targetRels);
15813
16969
  }
16970
+ const media = cloned.name.localName === "pic" ? readPictureMediaRef(cloned) : null;
16971
+ if (media !== null) addMediaTimingNode(targetSlide, media.kind, newId);
15814
16972
  return appendAndReturnNewShape(targetSlide, cloned);
15815
16973
  };
15816
16974
  /** Recursively clone an XML element (no parent, deep). */
@@ -15995,7 +17153,13 @@ const sendShapeBackward = (shape) => {
15995
17153
  */
15996
17154
  const clearSlideShapes = (slide) => {
15997
17155
  const spTree = requireSpTree(slide);
15998
- spTree.children = spTree.children.filter((c) => !(c.kind === "element" && c.name.namespaceURI === NS.pml && SHAPE_CHILD_LOCALS.has(c.name.localName)));
17156
+ const removedIds = /* @__PURE__ */ new Set();
17157
+ spTree.children = spTree.children.filter((c) => {
17158
+ const isShape = c.kind === "element" && c.name.namespaceURI === NS.pml && SHAPE_CHILD_LOCALS.has(c.name.localName);
17159
+ if (isShape) collectShapeIds(c, removedIds);
17160
+ return !isShape;
17161
+ });
17162
+ removeMediaTimingNodes(slide, removedIds);
15999
17163
  commitSlideData(slide);
16000
17164
  rebuildShapesFromDocument(slide);
16001
17165
  };
@@ -16009,9 +17173,20 @@ const removeShape = (shape) => {
16009
17173
  const idx = spTree.children.indexOf(shape[SHAPE_ELEMENT]);
16010
17174
  if (idx < 0) return;
16011
17175
  spTree.children.splice(idx, 1);
17176
+ const removedIds = /* @__PURE__ */ new Set();
17177
+ collectShapeIds(shape[SHAPE_ELEMENT], removedIds);
17178
+ removeMediaTimingNodes(slide, removedIds);
16012
17179
  commitSlideData(slide);
16013
17180
  rebuildShapesFromDocument(slide);
16014
17181
  };
17182
+ const collectShapeIds = (el, into) => {
17183
+ if (el.name.namespaceURI === NS.pml && el.name.localName === "cNvPr") {
17184
+ const id = Number.parseInt(getAttrValue(el, qname("", "id", "")) ?? "", 10);
17185
+ if (Number.isFinite(id)) into.add(id);
17186
+ return;
17187
+ }
17188
+ for (const c of el.children) if (c.kind === "element") collectShapeIds(c, into);
17189
+ };
16015
17190
  //#endregion
16016
17191
  //#region src/api/fn/shape-authoring.ts
16017
17192
  /**
@@ -16839,7 +18014,7 @@ const ensureSldIdLst = (presentationRoot) => {
16839
18014
  const allocateSldId = (sldIdLst) => {
16840
18015
  let max = 255;
16841
18016
  for (const sldId of allChildElements(sldIdLst, NAME_SLD_ID$1)) {
16842
- const raw = getAttrValue(sldId, ATTR_ID$1);
18017
+ const raw = getAttrValue(sldId, ATTR_ID$2);
16843
18018
  if (raw === null) continue;
16844
18019
  const n = Number.parseInt(raw, 10);
16845
18020
  if (Number.isFinite(n) && n > max) max = n;
@@ -16970,7 +18145,7 @@ const addSlide = (pres, options) => {
16970
18145
  targetMode: "Internal"
16971
18146
  });
16972
18147
  pkg.setRels(PRES_PART_NAME, presRels);
16973
- sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$1, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
18148
+ sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$2, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
16974
18149
  presPart.data = encode$1(serializeXml(presDoc));
16975
18150
  pres._slidesCache = null;
16976
18151
  const slides = getSlides(pres);
@@ -17149,7 +18324,7 @@ const duplicateSlide = (pres, slide) => {
17149
18324
  targetMode: "Internal"
17150
18325
  });
17151
18326
  pkg.setRels(PRES_PART_NAME, presRels);
17152
- sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$1, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
18327
+ sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$2, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
17153
18328
  presPart.data = encode$1(serializeXml(presDoc));
17154
18329
  pres._slidesCache = null;
17155
18330
  const slides = getSlides(pres);
@@ -17179,6 +18354,12 @@ const collectRelRefs = (el, into) => {
17179
18354
  for (const a of el.attrs) if (a.name.namespaceURI === NS.officeDocRels) into.add(a.value);
17180
18355
  for (const c of el.children) if (c.kind === "element") collectRelRefs(c, into);
17181
18356
  };
18357
+ const IMPORTED_MEDIA_REL_TYPES = new Set([
18358
+ REL_TYPES.image,
18359
+ REL_TYPES.media,
18360
+ REL_TYPES.video,
18361
+ REL_TYPES.audio
18362
+ ]);
17182
18363
  const pruneDanglingGraphicFrames = (el, keptRelIds) => {
17183
18364
  el.children = el.children.filter((c) => {
17184
18365
  if (c.kind !== "element") return true;
@@ -17200,8 +18381,8 @@ const pruneDanglingGraphicFrames = (el, keptRelIds) => {
17200
18381
  *
17201
18382
  * Limitations (v1):
17202
18383
  *
17203
- * - Only `image` rels are copied across. Other rels (charts, embedded
17204
- * workbooks, oleObjects, comments) are dropped from the imported
18384
+ * - Only image / video / audio rels are copied across. Other rels (charts,
18385
+ * embedded workbooks, oleObjects, comments) are dropped from the imported
17205
18386
  * slide. A diagnostic message is appended for each dropped rel.
17206
18387
  * - Hyperlinks (external URLs) are preserved.
17207
18388
  * - Slide → notesSlide is dropped (notes don't follow imports).
@@ -17233,31 +18414,42 @@ const importSlide = (targetPres, sourceSlide, targetLayout) => {
17233
18414
  target: `../slideLayouts/${basename(layoutPartName)}`,
17234
18415
  targetMode: "Internal"
17235
18416
  });
18417
+ const importedMedia = /* @__PURE__ */ new Map();
17236
18418
  if (sourceRels !== null) for (const rel of sourceRels.items) {
17237
18419
  if (rel.type === REL_TYPES.slideLayout) continue;
17238
18420
  if (rel.type === REL_TYPES.notesSlide) continue;
17239
- if (rel.type === REL_TYPES.image && rel.targetMode === "Internal") {
18421
+ if (IMPORTED_MEDIA_REL_TYPES.has(rel.type)) {
18422
+ if (rel.targetMode === "External") {
18423
+ newRels.items.push({ ...rel });
18424
+ continue;
18425
+ }
17240
18426
  const mediaName = rel.target.startsWith("/") ? partName(rel.target) : resolveTarget(sourcePartName, rel.target);
17241
- const mediaPart = sourcePkg.getPart(mediaName);
17242
- if (!mediaPart) continue;
17243
- const dotIdx = mediaName.lastIndexOf(".");
17244
- const extension = dotIdx >= 0 ? mediaName.slice(dotIdx + 1) : "bin";
17245
- let nextN = 1;
17246
- const re = /^\/ppt\/media\/image(\d+)\./;
17247
- for (const p of targetPkg.parts) {
17248
- const m = p.name.match(re);
17249
- if (m?.[1] !== void 0) {
17250
- const n = Number.parseInt(m[1], 10);
17251
- if (Number.isFinite(n) && n >= nextN) nextN = n + 1;
18427
+ let target = importedMedia.get(mediaName);
18428
+ if (target === void 0) {
18429
+ const mediaPart = sourcePkg.getPart(mediaName);
18430
+ if (!mediaPart) continue;
18431
+ const dotIdx = mediaName.lastIndexOf(".");
18432
+ const extension = dotIdx >= 0 ? mediaName.slice(dotIdx + 1) : "bin";
18433
+ const stem = rel.type === REL_TYPES.image ? "image" : "media";
18434
+ let nextN = 1;
18435
+ const re = new RegExp(`^/ppt/media/${stem}(\\d+)\\.`);
18436
+ for (const p of targetPkg.parts) {
18437
+ const m = p.name.match(re);
18438
+ if (m?.[1] !== void 0) {
18439
+ const n = Number.parseInt(m[1], 10);
18440
+ if (Number.isFinite(n) && n >= nextN) nextN = n + 1;
18441
+ }
17252
18442
  }
18443
+ const newMediaName = partName(`/ppt/media/${stem}${nextN}.${extension}`);
18444
+ setOpcDefault(targetPkg, extension.toLowerCase(), mediaPart.contentType);
18445
+ targetPkg.addPart(newMediaName, mediaPart.contentType, new Uint8Array(mediaPart.data));
18446
+ target = `../media/${stem}${nextN}.${extension}`;
18447
+ importedMedia.set(mediaName, target);
17253
18448
  }
17254
- const newMediaName = partName(`/ppt/media/image${nextN}.${extension}`);
17255
- setOpcDefault(targetPkg, extension.toLowerCase(), mediaPart.contentType);
17256
- targetPkg.addPart(newMediaName, mediaPart.contentType, new Uint8Array(mediaPart.data));
17257
18449
  newRels.items.push({
17258
18450
  id: rel.id,
17259
- type: REL_TYPES.image,
17260
- target: `../media/image${nextN}.${extension}`,
18451
+ type: rel.type,
18452
+ target,
17261
18453
  targetMode: "Internal"
17262
18454
  });
17263
18455
  continue;
@@ -17293,7 +18485,7 @@ const importSlide = (targetPres, sourceSlide, targetLayout) => {
17293
18485
  targetMode: "Internal"
17294
18486
  });
17295
18487
  targetPkg.setRels(PRES_PART_NAME, presRels);
17296
- sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$1, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
18488
+ sldIdLst.children.push(elem(NAME_SLD_ID$1, { attrs: [attr(ATTR_ID$2, String(newSldId)), attr(ATTR_R_ID$1, newRId)] }));
17297
18489
  presPart.data = encode$1(serializeXml(presDoc));
17298
18490
  targetPres._slidesCache = null;
17299
18491
  const slides = getSlides(targetPres);
@@ -17436,9 +18628,204 @@ const ungroupShapes = (group) => {
17436
18628
  });
17437
18629
  };
17438
18630
  //#endregion
18631
+ //#region src/api/fn/media.ts
18632
+ const DEFAULT_POSTER_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAUAAAAC0AQMAAADfKmdSAAAABlBMVEUmJib///+/9FOwAAAAvUlEQVR42u3XMQ7DIBAEQOfnfhpP4QmUFAgiJUqdKa6xtFtPA8J36+tKkiRJkiR5RF4Mm8KucCrcCg/DpnAoXAq3wnMr7AqnwqXwMGwKu8KpcCukK//ApnAoXAq3QjnNF3aFU+FSeBg2hUPhVLgV/r/yH2wKRzls1YfZ5Rc+yh9F+cOd5R/XXT0AVvmQatWDlEczD3teH7yQypcmr2Fe7FoVuHxwneGCxJWrvBZy0eTqymU4fxhJkiRJkjwqbzMmJGbQfp8bAAAAAElFTkSuQmCC";
18633
+ const defaultPoster = () => Uint8Array.from(atob(DEFAULT_POSTER_BASE64), (ch) => ch.charCodeAt(0));
18634
+ const YOUTUBE_HOSTS = new Set([
18635
+ "youtube.com",
18636
+ "www.youtube.com",
18637
+ "m.youtube.com"
18638
+ ]);
18639
+ const YOUTUBE_SHORT_HOST = "youtu.be";
18640
+ const YOUTUBE_ID = /^[A-Za-z0-9_-]+$/;
18641
+ const youtubeVideoId = (url) => {
18642
+ const segments = url.pathname.split("/").filter((s) => s !== "");
18643
+ if (url.hostname === YOUTUBE_SHORT_HOST) return segments[0] ?? null;
18644
+ if (!YOUTUBE_HOSTS.has(url.hostname)) return null;
18645
+ if (segments[0] === "watch") return url.searchParams.get("v");
18646
+ if (segments[0] === "shorts" || segments[0] === "live") return segments[1] ?? null;
18647
+ return null;
18648
+ };
18649
+ const resolveOnlineVideoUrl = (input) => {
18650
+ let url;
18651
+ try {
18652
+ url = new URL(input);
18653
+ } catch {
18654
+ throw new Error(`addSlideMedia: url is not an absolute URL: ${JSON.stringify(input)}`);
18655
+ }
18656
+ if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error(`addSlideMedia: url must be http(s), got ${JSON.stringify(input)}`);
18657
+ const id = youtubeVideoId(url);
18658
+ if (id === null || !YOUTUBE_ID.test(id)) return url.href;
18659
+ return `https://www.youtube.com/embed/${id}?feature=oembed`;
18660
+ };
18661
+ const MEDIA_DIR = "/ppt/media/";
18662
+ const nextMediaPartName = (pkg, stem, extension) => {
18663
+ let nextN = 1;
18664
+ const pattern = new RegExp(`^/ppt/media/${stem}(\\d+)\\.`);
18665
+ for (const p of pkg.parts) {
18666
+ const m = p.name.match(pattern);
18667
+ if (m?.[1] !== void 0) {
18668
+ const n = Number.parseInt(m[1], 10);
18669
+ if (n >= nextN) nextN = n + 1;
18670
+ }
18671
+ }
18672
+ return partName(`${MEDIA_DIR}${stem}${nextN}.${extension}`);
18673
+ };
18674
+ const bytesEqual = (a, b) => {
18675
+ if (a.length !== b.length) return false;
18676
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
18677
+ return true;
18678
+ };
18679
+ const internClipPart = (pkg, extension, contentType, bytes) => {
18680
+ for (const p of pkg.parts) if (p.name.startsWith(MEDIA_DIR) && p.contentType === contentType && bytesEqual(p.data, bytes)) return p.name;
18681
+ const name = nextMediaPartName(pkg, "media", extension);
18682
+ setOpcDefault(pkg, extension, contentType);
18683
+ pkg.addPart(name, contentType, bytes);
18684
+ return name;
18685
+ };
18686
+ const resolveSource = (source) => {
18687
+ switch (source.kind) {
18688
+ case "online": return { url: resolveOnlineVideoUrl(source.url) };
18689
+ case "video": {
18690
+ const format = source.format ?? detectVideoFormat(source.data);
18691
+ if (format === null) throw new Error("addSlideMedia: could not detect the video format. Pass options.format explicitly.");
18692
+ const contentType = contentTypeForVideoFormat(format);
18693
+ return {
18694
+ data: source.data,
18695
+ extension: format,
18696
+ contentType
18697
+ };
18698
+ }
18699
+ case "audio": {
18700
+ const format = source.format ?? detectAudioFormat(source.data);
18701
+ if (format === null) throw new Error("addSlideMedia: could not detect the audio format. Pass options.format explicitly.");
18702
+ const contentType = contentTypeForAudioFormat(format);
18703
+ return {
18704
+ data: source.data,
18705
+ extension: format,
18706
+ contentType
18707
+ };
18708
+ }
18709
+ }
18710
+ };
18711
+ const DEFAULT_NAME_PREFIX = {
18712
+ video: "Video",
18713
+ audio: "Audio",
18714
+ online: "Online Media"
18715
+ };
18716
+ /**
18717
+ * Adds a video, an audio clip or an online (URL) video to the slide. Returns
18718
+ * the new picture shape — the clip's poster frame.
18719
+ *
18720
+ * Embedded clips are stored once per package: adding the same bytes again
18721
+ * reuses the existing `/ppt/media/mediaN.<ext>` part. The container format is
18722
+ * detected from the bytes (mp4 / m4v / mov / webm / avi / wmv, mp3 / wav / m4a /
18723
+ * ogg / wma); pass `format` for anything the signature check cannot tell.
18724
+ * Whether a clip plays depends on the codecs of the viewing application.
18725
+ *
18726
+ * The shape is an ordinary picture: `getShapeImageBytes` / `setShapeImage`
18727
+ * read and replace the poster, `getShapeMedia` reads the clip.
18728
+ */
18729
+ const addSlideMedia = (slide, opts) => {
18730
+ const x = emuCoordinate(opts.x, "addSlideMedia: x");
18731
+ const y = emuCoordinate(opts.y, "addSlideMedia: y");
18732
+ const w = emuExtent(opts.w, "addSlideMedia: w");
18733
+ const h = emuExtent(opts.h, "addSlideMedia: h");
18734
+ const source = resolveSource(opts);
18735
+ const poster = opts.poster ?? defaultPoster();
18736
+ const posterFormat = opts.posterFormat ?? detectImageFormat(poster);
18737
+ if (posterFormat === null) throw new Error("addSlideMedia: could not detect the poster image format. Pass options.posterFormat explicitly.");
18738
+ const pkg = slide[INTERNAL_PACKAGE];
18739
+ const slidePartName = slide[SLIDE_PART_NAME];
18740
+ const rels = pkg.getRels(slidePartName) ?? emptyRels();
18741
+ const usedIds = rels.items.map((r) => r.id);
18742
+ const relate = (type, target, targetMode) => {
18743
+ const existing = rels.items.find((r) => r.type === type && r.target === target && r.targetMode === targetMode);
18744
+ if (existing) return existing.id;
18745
+ const id = nextRelId(usedIds);
18746
+ usedIds.push(id);
18747
+ rels.items.push({
18748
+ id,
18749
+ type,
18750
+ target,
18751
+ targetMode
18752
+ });
18753
+ return id;
18754
+ };
18755
+ const relativeTarget = (name) => `../media/${name.slice(11)}`;
18756
+ const kind = opts.kind === "audio" ? "audio" : "video";
18757
+ const fileRelType = kind === "audio" ? REL_TYPES.audio : REL_TYPES.video;
18758
+ let rLink;
18759
+ let rMedia;
18760
+ if ("url" in source) rLink = relate(fileRelType, source.url, "External");
18761
+ else {
18762
+ const clipPart = internClipPart(pkg, source.extension, source.contentType, source.data);
18763
+ rMedia = relate(REL_TYPES.media, relativeTarget(clipPart), "Internal");
18764
+ rLink = relate(fileRelType, relativeTarget(clipPart), "Internal");
18765
+ }
18766
+ const posterExtension = extensionForFormat(posterFormat);
18767
+ const posterContentType = contentTypeForFormat(posterFormat);
18768
+ const posterPart = nextMediaPartName(pkg, "image", posterExtension);
18769
+ setOpcDefault(pkg, posterExtension, posterContentType);
18770
+ pkg.addPart(posterPart, posterContentType, poster);
18771
+ const rPoster = relate(REL_TYPES.image, relativeTarget(posterPart), "Internal");
18772
+ pkg.setRels(slidePartName, rels);
18773
+ const id = nextShapeId(slide);
18774
+ const pic = buildMediaPicture({
18775
+ id,
18776
+ name: opts.name ?? `${DEFAULT_NAME_PREFIX[opts.kind]} ${id}`,
18777
+ kind,
18778
+ rLink,
18779
+ ...rMedia !== void 0 ? { rMedia } : {},
18780
+ rEmbed: rPoster,
18781
+ x,
18782
+ y,
18783
+ w,
18784
+ h
18785
+ });
18786
+ addMediaTimingNode(slide, kind, id);
18787
+ return appendAndReturnNewShape(slide, pic);
18788
+ };
18789
+ /**
18790
+ * Returns the clip behind a media picture, or `null` when the shape is not
18791
+ * one. Reads PowerPoint-, PptxGenJS- and python-pptx-authored media alike: the
18792
+ * embedded part is taken from `<p14:media r:embed>` when present and from the
18793
+ * DrawingML `r:link` otherwise; a relationship with an external target is
18794
+ * reported as `'online'`.
18795
+ */
18796
+ const getShapeMedia = (shape) => {
18797
+ if (shape[SHAPE_SNAPSHOT].kind !== "picture") return null;
18798
+ const ref = readPictureMediaRef(shape[SHAPE_ELEMENT]);
18799
+ if (ref === null) return null;
18800
+ const slide = shape[SHAPE_SLIDE];
18801
+ const pkg = slide[INTERNAL_PACKAGE];
18802
+ const rels = pkg.getRels(slide[SLIDE_PART_NAME]);
18803
+ if (rels === null) return null;
18804
+ const relsById = new Map(rels.items.map((r) => [r.id, r]));
18805
+ for (const rId of [ref.mediaRId, ref.fileRId]) {
18806
+ const rel = rId === null ? void 0 : relsById.get(rId);
18807
+ if (rel === void 0) continue;
18808
+ if (rel.targetMode === "External") return {
18809
+ kind: "online",
18810
+ url: rel.target
18811
+ };
18812
+ const name = rel.target.startsWith("/") ? partName(rel.target) : resolveTarget(slide[SLIDE_PART_NAME], rel.target);
18813
+ const part = pkg.getPart(name);
18814
+ if (part) return {
18815
+ kind: ref.kind,
18816
+ partName: part.name,
18817
+ contentType: part.contentType,
18818
+ bytes: part.data
18819
+ };
18820
+ }
18821
+ return null;
18822
+ };
18823
+ /** Every shape on the slide that `getShapeMedia` reports a clip for. */
18824
+ const findShapesWithMedia = (slide) => slide[SLIDE_SHAPES].filter((shape) => getShapeMedia(shape) !== null);
18825
+ //#endregion
17439
18826
  //#region src/api/index.ts
17440
- const VERSION = "0.16.1";
18827
+ const VERSION = "0.17.0";
17441
18828
  //#endregion
17442
- export { slideHasAnimations as $, getTableCellMargins as $a, clearSlideHyperlinks as $i, getShapeText as $n, getSlideLayouts as $o, getShapeRunCount as $r, getCommentAuthor as $s, getShapeStrokeColorResolved as $t, getPresentationTextLength as A, clearSlideTransition as Aa, getShapeImageContrast as Ai, findShapesAtPoint as An, setTableStyleFlags as Ao, setShapeSize as Ar, getSlideLayoutBackgroundImageBytes as As, setShapeTextBodyRotationDeg as At, getSlideText as B, listPackageParts as Ba, isShapeImageGrayscale as Bi, getShapeCenter as Bn, setCoreProperties as Bo, getParagraphAlignment as Br, setSlideBackgroundImage as Bs, getShapeEffectsEffective as Bt, findSlideByTitle as C, getSlidesWithOverlap as Ca, pt as Cc, findSlidesByLayoutName as Ci, getSlideLayout as Cn, setTableCellMargins as Co, setShapeGradientFill as Cr, getSlideBackground as Cs, getShapeTextWrap as Ct, getOutlineText as D, removeSlideNotes as Da, getShapeImageBiLevelThreshold as Di, setSlideLayout as Dn, setTableCellTextFormat as Do, setShapePatternFill as Dr, getSlideColorMapOverride as Ds, setShapeText as Dt, getAllShapes as E, hasSlideNotes as Ea, getPresentationImageCountsBySlide as Ei, replaceTokensInSlide as En, setTableCellTextDirection as Eo, setShapeNoStroke as Er, getSlideBackgroundPatternFill as Es, setShapeParagraphs as Et, getSlideIndex as F, getMediaParts as Fa, getShapeImageLinkUrl as Fi, getMaxShapeIdInPresentation as Fn, getCoreProperties as Fo, setShapeStrokeDash as Fr, getSlideMasterBackgroundGradientFill as Fs, setShapeTextWrap as Ft, isSlideHidden as G, clearTableCellFill as Ga, SLIDE_SIZE_16_10 as Gi, getShapeKind as Gn, findSlideLayoutByPartName as Go, getParagraphIndent as Gr, clearAllSlideComments as Gs, getShapeFill as Gt, getSlideXmlString as H, setMediaPartBytes as Ha, setShapeImageContrast as Hi, getShapeDescription as Hn, touchModified as Ho, getParagraphBulletImageBytes as Hr, setShapeClickAction as Hs, setShapeShadow as Ht, getSlideInfo as I, getOrphanMediaPartNames as Ia, getShapeImageOpacity as Ii, getShapeAdjustValues as In, getExtendedProperties as Io, setShapeStrokeJoin as Ir, getSlideMasterBackgroundImageBytes as Is, clearShapeEffects as It, replaceTextInSlide as J, getTableCell as Ja, getSlideSize as Ji, getShapePlaceholderType as Jn, getSlideLayoutPartName as Jo, getParagraphSpacing as Jr, findCommentsAfter as Js, getShapeFillEffective as Jt, replaceTextInNotes as K, getPresentationTableCountsBySlide as Ka, SLIDE_SIZE_16_9 as Ki, getShapeName as Kn, findSlideLayoutByType as Ko, getParagraphLevel as Kr, clearSlideComments as Ks, getShapeFillColor as Kt, getSlideLayoutCount as L, getPackageSize as La, getShapeImagePartName as Li, getShapeAltTitle as Ln, getPresentationCreated as Lo, getShapeRunFormat as Lr, getSlideMasterBackgroundPatternFill as Ls, findShapesByEffect as Lt, getShapeAt as M, setSlideTransition as Ma, getShapeImageDuotone as Mi, getGroupChildren as Mn, getThumbnail as Mo, setShapeStrokeArrow as Mr, getSlideLayoutBackgroundShapes as Ms, setShapeTextDirection as Mt, getSlideAt as N, _internalPackageOf as Na, getShapeImageFillBytes as Ni, getGroupTransform as Nn, removeThumbnail as No, setShapeStrokeCap as Nr, getSlideLayoutShapes as Ns, setShapeTextFormat as Nt, getPresentationShapeCountsBySlide as O, replaceHyperlink as Oa, getShapeImageBrightness as Oi, translateShapes as On, setTableColumnWidth as Oo, setShapePosition as Or, getSlideLayoutBackground as Os, setShapeTextAnchor as Ot, getSlideCount as P, compactPackage as Pa, getShapeImageFormat as Pi, getMaxShapeId as Pn, setThumbnail as Po, setShapeStrokeCompound as Pr, getSlideMasterBackground as Ps, setShapeTextMargins as Pt, setSlideHidden as Q, getTableCellFill as Qa, clearAllSlideNotes as Qi, getShapeSize as Qn, getSlideLayoutUsageCountsByType as Qo, getShapeRunClickAction as Qr, findSlidesWithCommentsByAuthor as Qs, getShapeStrokeColor as Qt, getSlideOutline as R, getPresentationSummary as Ra, hasShapeImage as Ri, getShapeBounds as Rn, getPresentationModified as Ro, resolveDrawingColor as Rr, getSlideMasterShapes as Rs, getShapeEffect as Rt, findSlideByText as S, getSlidesWithNotes as Sa, mm as Sc, findShapesOutsideCanvas as Si, getShapesBounds as Sn, setTableCellFill as So, setShapeFlip as Sr, clearSlideBackground as Ss, getShapeTextMargins as St, findSlidesByText as T, getVisibleSlides as Ta, findSlidesByLayoutType as Ti, getSlidesWithEmptyPlaceholders as Tn, setTableCellText as To, setShapeNoFill as Tr, getSlideBackgroundImageBytes as Ts, setShapeBullets as Tt, getSlides as U, slidesUsingMediaPart as Ua, setShapeImageCrop as Ui, getShapeFlip as Un, findLayoutsWithPlaceholderType as Uo, getParagraphBulletStyle as Ur, setShapeImage as Us, getShapeGradientFill as Ut, getSlideTextLength as V, readPackagePart as Va, setShapeImageBrightness as Vi, getShapeCustomGeometry as Vn, setExtendedProperties as Vo, getParagraphBullet as Vr, getShapeClickAction as Vs, setShapeGlow as Vt, getSlidesByLayout as W, validatePresentation as Wa, setShapeImageOpacity as Wi, getShapeId as Wn, findSlideLayout as Wo, getParagraphEndFormat as Wr, addSlideComment as Ws, getShapeGradientFillEffective as Wt, replaceTokensInPresentation as X, getTableCellAnchor as Xa, appendSlideNotes as Xi, getShapePreset as Xn, getSlideLayoutType as Xo, getShapeParagraphCount as Xr, findCommentsByAuthor as Xs, getShapeStroke as Xt, replaceTextInSlideNotes as Y, getTableCellAlignment as Ya, setSlideSize as Yi, getShapePosition as Yn, getSlideLayoutPlaceholders as Yo, getShapeHyperlinkTooltip as Yr, findCommentsBefore as Ys, getShapeFillOpacity as Yt, searchSlides as Z, getTableCellBorders as Za, clearAllHyperlinks as Zi, getShapeRotation as Zn, getSlideLayoutUsageCounts as Zo, getShapeParagraphElements as Zr, findCommentsByText as Zs, getShapeStrokeCap as Zt, sortSlides as _, getSlideNotesLength as _a, loadPresentation as _c, findShapesWithAnimation as _i, findSlidePlaceholderByIdx as _n, removeTableColumn as _o, getShapePatternFill as _r, getShapeChartSpec as _s, getShapeTextAutoFit as _t, addContentSlide as a, getAllHyperlinks as aa, getCommentsSortedByDate as ac, setParagraphBullet as ai, findEmptyPlaceholders as an, getTableCells as ao, isShapeHidden as ar, setShapeRunFormat as as, bringShapeForward as at, setSlideSections as b, getSlidesWithHyperlinks as ba, emu as bc, findFlippedShapes as bi, getShapeSlide as bn, setTableCellAnchor as bo, setShapeAdjustValues as br, getEffectiveColorMap as bs, getShapeTextColumns as bt, addSlideAt as c, getAllTables as ca, getPresentationCommenters as cc, setParagraphSpacing as ci, findShapeByText as cn, getTableRowHeights as co, pointInShape as cr, findChartsBySeriesName as cs, copyShape as ct, duplicateSlideAt as d, getHiddenSlides as da, removeSlideComment as dc, getSlideBody as di, findShapesByKind as dn, getTableStyleId as do, setShapeBounds as dr, getPresentationChartCountsBySlide as ds, sendShapeBackward as dt, findSlidesByHyperlink as ea, getCommentAuthors as ec, getShapeRunHyperlink as ei, getShapeStrokeCompound as en, getTableCellParagraphs as eo, getSlideMasterCount as er, getUnusedSlideLayouts as es, addSlideImage as et, importSlide as f, getPresentationHyperlinkCountsBySlide as fa, getPresentationFonts as fc, getSlideTitle as fi, findShapesByName as fn, insertTableColumn as fo, setShapeDescription as fr, getPresentationChartKindCounts as fs, sendShapeToBack as ft, reverseSlides as g, getSlideNotes as ga, createPresentation as gc, clearSlideAnimations as gi, findSlidePlaceholder as gn, mergeTableCells as go, clearShapeStroke as gr, getShapeChartSeriesValues as gs, getShapeTextAnchor as gt, removeSlide as h, getPresentationNotesText as ha, setPresentationTheme as hc, setSlideTitle as hi, findShapesWithHyperlinks as hn, isTableShape as ho, clearShapeFill as hr, getShapeChartSeriesNames as hs, getShapeBodyPrEffective as ht, addBlankSlide as i, getAllComments as ia, getCommentText as ic, setParagraphAlignment as ii, getShapeStrokeWidth as in, getTableCellTextDirection as io, getUnusedSlideMasters as ir, setShapeHyperlink as is, addSlideTextBox as it, getPresentationTextLengthsBySlide as j, getSlideTransition as ja, getShapeImageCrop as ji, findShapesInRect as jn, setTableStyleId as jo, setShapeStroke as jr, getSlideLayoutBackgroundPatternFill as js, setShapeTextColumns as jt, getPresentationText as k, setSlideNotes as ka, getShapeImageBytes as ki, centerShapeOnSlide as kn, setTableRowHeight as ko, setShapeRotation as kr, getSlideLayoutBackgroundGradientFill as ks, setShapeTextAutoFit as kt, addTitleSlide as l, getDistinctHyperlinkUrls as la, getSlideCommentAuthors as lc, setShapeRunHyperlink as li, findShapeInPresentation as ln, getTableSize as lo, renameShape as lr, findChartsWithDataLabels as ls, getShapeZIndex as lt, moveSlide as m, getPresentationNotesLengthsBySlide as ma, setPresentationFonts as mc, setSlidePlaceholders as mi, findShapesByText as mn, isChartShape as mo, shapesOverlap as mr, getShapeChartKind as ms, appendShapeText as mt, groupShapes as n, findSlidesWithChartTrendlines as na, getCommentPosition as nc, getShapeRunText as ni, getShapeStrokeJoin as nn, getTableCellSpan as no, getSlideMasterPartNames as nr, getShapeHyperlink as ns, addSlideShape as nt, addSectionHeaderSlide as o, getAllImages as oa, getPresentationCommentCountsByAuthor as oc, setParagraphLevel as oi, findShapeById as on, getTableColumnWidths as oo, isShapePlaceholder as or, addSlideChart as os, bringShapeToFront as ot, mergePresentations as p, getPresentationNotesLength as pa, getPresentationTheme as pc, setSlideBody as pi, findShapesByPreset as pn, insertTableRow as po, setShapeHidden as pr, getShapeChartCategories as ps, setShapeZIndex as pt, replaceTextInPresentation as q, getSlideTables as qa, SLIDE_SIZE_4_3 as qi, getShapePlaceholderIdx as qn, getSlideLayoutName as qo, getParagraphLineSpacing as qr, findCommentAuthorByName as qs, getShapeFillColorResolved as qt, ungroupShapes as r, getAllCharts as ra, getCommentSlide as rc, isParagraphBulletPicture as ri, getShapeStrokeOpacity as rn, getTableCellText as ro, getSlideMasterUsageCounts as rr, getShapeRunFormatEffective as rs, addSlideTable as rt, addSlide as s, getAllNotes as sa, getPresentationCommentCountsBySlide as sc, setParagraphLineSpacing as si, findShapeByName as sn, getTableDimensions as so, isShapeTextBox as sr, findChartByKind as ss, clearSlideShapes as st, VERSION as t, findSlidesWithChartKind as ta, getCommentDate as tc, getShapeRunHyperlinkTooltip as ti, getShapeStrokeEffective as tn, getTableCellPosition as to, getSlideMasterPartName as tr, getParagraphPropertiesEffective as ts, addSlideLine as tt, duplicateSlide as u, getEmptySlides as ua, getSlideComments as uc, setShapeRunText as ui, findShapesByHyperlink as un, getTableStyleFlags as uo, setShapeAltTitle as ur, findChartsWithTrendlines as us, removeShape as ut, swapSlides as v, getSlidesWithCharts as va, savePresentation as vc, getShapeAnimation as vi, findSlidePlaceholders as vn, removeTableRow as vo, getShapeStrokeArrow as vr, getSlideCharts as vs, getShapeTextAutoFitParams as vt, findSlidesByNotes as w, getSlidesWithTables as wa, findSlidesByLayoutPartName as wi, getSlideShapes as wn, setTableCellParagraphs as wo, setShapeImageFill as wr, getSlideBackgroundGradientFill as ws, setShapeAlignment as wt, findSlideByPartName as x, getSlidesWithImages as xa, inches as xc, findOverlappingShapePairs as xi, getShapeXmlString as xn, setTableCellBorders as xo, setShapeFill as xr, resolveDeckBodyTextColor as xs, getShapeTextDirection as xt, getSlideSections as y, getSlidesWithComments as ya, cm as yc, setShapeAnimation as yi, getShapeIndex as yn, setTableCellAlignment as yo, getShapeStrokeDash as yr, setChartSpec as ys, getShapeTextBodyRotationDeg as yt, getSlidePartName as z, getSlideMediaPartNames as za, hasShapeText as zi, getShapeBoundsResolved as zn, incrementRevision as zo, resolveDrawingColorOpacity as zr, setSlideBackground as zs, getShapeEffects as zt };
18829
+ export { replaceTokensInPresentation as $, getTableCellAnchor as $a, appendSlideNotes as $i, getShapePreset as $n, getSlideLayoutType as $o, getShapeParagraphCount as $r, findCommentsByAuthor as $s, getShapeStroke as $t, getOutlineText as A, removeSlideNotes as Aa, getShapeImageBiLevelThreshold as Ai, setSlideLayout as An, setTableCellTextFormat as Ao, setShapePatternFill as Ar, getSlideColorMapOverride as As, setShapeText as At, getSlideLayoutCount as B, getPackageSize as Ba, getShapeImagePartName as Bi, getShapeAltTitle as Bn, getPresentationCreated as Bo, getShapeRunFormat as Br, getSlideMasterBackgroundPatternFill as Bs, findShapesByEffect as Bt, setSlideSections as C, getSlidesWithHyperlinks as Ca, emu as Cc, findFlippedShapes as Ci, getShapeSlide as Cn, setTableCellAnchor as Co, setShapeAdjustValues as Cr, getEffectiveColorMap as Cs, getShapeTextColumns as Ct, findSlidesByNotes as D, getSlidesWithTables as Da, findSlidesByLayoutPartName as Di, getSlideShapes as Dn, setTableCellParagraphs as Do, setShapeImageFill as Dr, getSlideBackgroundGradientFill as Ds, setShapeAlignment as Dt, findSlideByTitle as E, getSlidesWithOverlap as Ea, pt as Ec, findSlidesByLayoutName as Ei, getSlideLayout as En, setTableCellMargins as Eo, setShapeGradientFill as Er, getSlideBackground as Es, getShapeTextWrap as Et, getShapeAt as F, setSlideTransition as Fa, getShapeImageDuotone as Fi, getGroupChildren as Fn, getThumbnail as Fo, setShapeStrokeArrow as Fr, getSlideLayoutBackgroundShapes as Fs, setShapeTextDirection as Ft, getSlideXmlString as G, setMediaPartBytes as Ga, setShapeImageContrast as Gi, getShapeDescription as Gn, touchModified as Go, getParagraphBulletImageBytes as Gr, setShapeClickAction as Gs, setShapeShadow as Gt, getSlidePartName as H, getSlideMediaPartNames as Ha, hasShapeText as Hi, getShapeBoundsResolved as Hn, incrementRevision as Ho, resolveDrawingColorOpacity as Hr, setSlideBackground as Hs, getShapeEffects as Ht, getSlideAt as I, _internalPackageOf as Ia, getShapeImageFillBytes as Ii, getGroupTransform as In, removeThumbnail as Io, setShapeStrokeCap as Ir, getSlideLayoutShapes as Is, setShapeTextFormat as It, isSlideHidden as J, clearTableCellFill as Ja, SLIDE_SIZE_16_10 as Ji, getShapeKind as Jn, findSlideLayoutByPartName as Jo, getParagraphIndent as Jr, clearAllSlideComments as Js, getShapeFill as Jt, getSlides as K, slidesUsingMediaPart as Ka, setShapeImageCrop as Ki, getShapeFlip as Kn, findLayoutsWithPlaceholderType as Ko, getParagraphBulletStyle as Kr, setShapeImage as Ks, getShapeGradientFill as Kt, getSlideCount as L, compactPackage as La, getShapeImageFormat as Li, getMaxShapeId as Ln, setThumbnail as Lo, setShapeStrokeCompound as Lr, getSlideMasterBackground as Ls, setShapeTextMargins as Lt, getPresentationText as M, setSlideNotes as Ma, getShapeImageBytes as Mi, centerShapeOnSlide as Mn, setTableRowHeight as Mo, setShapeRotation as Mr, getSlideLayoutBackgroundGradientFill as Ms, setShapeTextAutoFit as Mt, getPresentationTextLength as N, clearSlideTransition as Na, getShapeImageContrast as Ni, findShapesAtPoint as Nn, setTableStyleFlags as No, setShapeSize as Nr, getSlideLayoutBackgroundImageBytes as Ns, setShapeTextBodyRotationDeg as Nt, findSlidesByText as O, getVisibleSlides as Oa, findSlidesByLayoutType as Oi, getSlidesWithEmptyPlaceholders as On, setTableCellText as Oo, setShapeNoFill as Or, getSlideBackgroundImageBytes as Os, setShapeBullets as Ot, getPresentationTextLengthsBySlide as P, getSlideTransition as Pa, getShapeImageCrop as Pi, findShapesInRect as Pn, setTableStyleId as Po, setShapeStroke as Pr, getSlideLayoutBackgroundPatternFill as Ps, setShapeTextColumns as Pt, replaceTextInSlideNotes as Q, getTableCellAlignment as Qa, setSlideSize as Qi, getShapePosition as Qn, getSlideLayoutPlaceholders as Qo, getShapeHyperlinkTooltip as Qr, findCommentsBefore as Qs, getShapeFillOpacity as Qt, getSlideIndex as R, getMediaParts as Ra, getShapeImageLinkUrl as Ri, getMaxShapeIdInPresentation as Rn, getCoreProperties as Ro, setShapeStrokeDash as Rr, getSlideMasterBackgroundGradientFill as Rs, setShapeTextWrap as Rt, getSlideSections as S, getSlidesWithComments as Sa, cm as Sc, setShapeAnimation as Si, getShapeIndex as Sn, setTableCellAlignment as So, getShapeStrokeDash as Sr, setChartSpec as Ss, getShapeTextBodyRotationDeg as St, findSlideByText as T, getSlidesWithNotes as Ta, mm as Tc, findShapesOutsideCanvas as Ti, getShapesBounds as Tn, setTableCellFill as To, setShapeFlip as Tr, clearSlideBackground as Ts, getShapeTextMargins as Tt, getSlideText as U, listPackageParts as Ua, isShapeImageGrayscale as Ui, getShapeCenter as Un, setCoreProperties as Uo, getParagraphAlignment as Ur, setSlideBackgroundImage as Us, getShapeEffectsEffective as Ut, getSlideOutline as V, getPresentationSummary as Va, hasShapeImage as Vi, getShapeBounds as Vn, getPresentationModified as Vo, resolveDrawingColor as Vr, getSlideMasterShapes as Vs, getShapeEffect as Vt, getSlideTextLength as W, readPackagePart as Wa, setShapeImageBrightness as Wi, getShapeCustomGeometry as Wn, setExtendedProperties as Wo, getParagraphBullet as Wr, getShapeClickAction as Ws, setShapeGlow as Wt, replaceTextInPresentation as X, getSlideTables as Xa, SLIDE_SIZE_4_3 as Xi, getShapePlaceholderIdx as Xn, getSlideLayoutName as Xo, getParagraphLineSpacing as Xr, findCommentAuthorByName as Xs, getShapeFillColorResolved as Xt, replaceTextInNotes as Y, getPresentationTableCountsBySlide as Ya, SLIDE_SIZE_16_9 as Yi, getShapeName as Yn, findSlideLayoutByType as Yo, getParagraphLevel as Yr, clearSlideComments as Ys, getShapeFillColor as Yt, replaceTextInSlide as Z, getTableCell as Za, getSlideSize as Zi, getShapePlaceholderType as Zn, getSlideLayoutPartName as Zo, getParagraphSpacing as Zr, findCommentsAfter as Zs, getShapeFillEffective as Zt, moveSlide as _, getPresentationNotesLengthsBySlide as _a, setPresentationFonts as _c, setSlidePlaceholders as _i, findShapesByText as _n, isChartShape as _o, shapesOverlap as _r, getShapeChartKind as _s, appendShapeText as _t, groupShapes as a, findSlidesWithChartTrendlines as aa, getCommentPosition as ac, getShapeRunText as ai, getShapeStrokeJoin as an, getTableCellSpan as ao, getSlideMasterPartNames as ar, getShapeHyperlink as as, addSlideShape as at, sortSlides as b, getSlideNotesLength as ba, loadPresentation as bc, findShapesWithAnimation as bi, findSlidePlaceholderByIdx as bn, removeTableColumn as bo, getShapePatternFill as br, getShapeChartSpec as bs, getShapeTextAutoFit as bt, addContentSlide as c, getAllHyperlinks as ca, getCommentsSortedByDate as cc, setParagraphBullet as ci, findEmptyPlaceholders as cn, getTableCells as co, isShapeHidden as cr, setShapeRunFormat as cs, bringShapeForward as ct, addSlideAt as d, getAllTables as da, getPresentationCommenters as dc, setParagraphSpacing as di, findShapeByText as dn, getTableRowHeights as do, pointInShape as dr, findChartsBySeriesName as ds, copyShape as dt, clearAllHyperlinks as ea, findCommentsByText as ec, getShapeParagraphElements as ei, getShapeStrokeCap as en, getTableCellBorders as eo, getShapeRotation as er, getSlideLayoutUsageCounts as es, searchSlides as et, addTitleSlide as f, getDistinctHyperlinkUrls as fa, getSlideCommentAuthors as fc, setShapeRunHyperlink as fi, findShapeInPresentation as fn, getTableSize as fo, renameShape as fr, findChartsWithDataLabels as fs, getShapeZIndex as ft, mergePresentations as g, getPresentationNotesLength as ga, getPresentationTheme as gc, setSlideBody as gi, findShapesByPreset as gn, insertTableRow as go, setShapeHidden as gr, getShapeChartCategories as gs, setShapeZIndex as gt, importSlide as h, getPresentationHyperlinkCountsBySlide as ha, getPresentationFonts as hc, getSlideTitle as hi, findShapesByName as hn, insertTableColumn as ho, setShapeDescription as hr, getPresentationChartKindCounts as hs, sendShapeToBack as ht, getShapeMedia as i, findSlidesWithChartKind as ia, getCommentDate as ic, getShapeRunHyperlinkTooltip as ii, getShapeStrokeEffective as in, getTableCellPosition as io, getSlideMasterPartName as ir, getParagraphPropertiesEffective as is, addSlideLine as it, getPresentationShapeCountsBySlide as j, replaceHyperlink as ja, getShapeImageBrightness as ji, translateShapes as jn, setTableColumnWidth as jo, setShapePosition as jr, getSlideLayoutBackground as js, setShapeTextAnchor as jt, getAllShapes as k, hasSlideNotes as ka, getPresentationImageCountsBySlide as ki, replaceTokensInSlide as kn, setTableCellTextDirection as ko, setShapeNoStroke as kr, getSlideBackgroundPatternFill as ks, setShapeParagraphs as kt, addSectionHeaderSlide as l, getAllImages as la, getPresentationCommentCountsByAuthor as lc, setParagraphLevel as li, findShapeById as ln, getTableColumnWidths as lo, isShapePlaceholder as lr, addSlideChart as ls, bringShapeToFront as lt, duplicateSlideAt as m, getHiddenSlides as ma, removeSlideComment as mc, getSlideBody as mi, findShapesByKind as mn, getTableStyleId as mo, setShapeBounds as mr, getPresentationChartCountsBySlide as ms, sendShapeBackward as mt, addSlideMedia as n, clearSlideHyperlinks as na, getCommentAuthor as nc, getShapeRunCount as ni, getShapeStrokeColorResolved as nn, getTableCellMargins as no, getShapeText as nr, getSlideLayouts as ns, slideHasAnimations as nt, ungroupShapes as o, getAllCharts as oa, getCommentSlide as oc, isParagraphBulletPicture as oi, getShapeStrokeOpacity as on, getTableCellText as oo, getSlideMasterUsageCounts as or, getShapeRunFormatEffective as os, addSlideTable as ot, duplicateSlide as p, getEmptySlides as pa, getSlideComments as pc, setShapeRunText as pi, findShapesByHyperlink as pn, getTableStyleFlags as po, setShapeAltTitle as pr, findChartsWithTrendlines as ps, removeShape as pt, getSlidesByLayout as q, validatePresentation as qa, setShapeImageOpacity as qi, getShapeId as qn, findSlideLayout as qo, getParagraphEndFormat as qr, addSlideComment as qs, getShapeGradientFillEffective as qt, findShapesWithMedia as r, findSlidesByHyperlink as ra, getCommentAuthors as rc, getShapeRunHyperlink as ri, getShapeStrokeCompound as rn, getTableCellParagraphs as ro, getSlideMasterCount as rr, getUnusedSlideLayouts as rs, addSlideImage as rt, addBlankSlide as s, getAllComments as sa, getCommentText as sc, setParagraphAlignment as si, getShapeStrokeWidth as sn, getTableCellTextDirection as so, getUnusedSlideMasters as sr, setShapeHyperlink as ss, addSlideTextBox as st, VERSION as t, clearAllSlideNotes as ta, findSlidesWithCommentsByAuthor as tc, getShapeRunClickAction as ti, getShapeStrokeColor as tn, getTableCellFill as to, getShapeSize as tr, getSlideLayoutUsageCountsByType as ts, setSlideHidden as tt, addSlide as u, getAllNotes as ua, getPresentationCommentCountsBySlide as uc, setParagraphLineSpacing as ui, findShapeByName as un, getTableDimensions as uo, isShapeTextBox as ur, findChartByKind as us, clearSlideShapes as ut, removeSlide as v, getPresentationNotesText as va, setPresentationTheme as vc, setSlideTitle as vi, findShapesWithHyperlinks as vn, isTableShape as vo, clearShapeFill as vr, getShapeChartSeriesNames as vs, getShapeBodyPrEffective as vt, findSlideByPartName as w, getSlidesWithImages as wa, inches as wc, findOverlappingShapePairs as wi, getShapeXmlString as wn, setTableCellBorders as wo, setShapeFill as wr, resolveDeckBodyTextColor as ws, getShapeTextDirection as wt, swapSlides as x, getSlidesWithCharts as xa, savePresentation as xc, getShapeAnimation as xi, findSlidePlaceholders as xn, removeTableRow as xo, getShapeStrokeArrow as xr, getSlideCharts as xs, getShapeTextAutoFitParams as xt, reverseSlides as y, getSlideNotes as ya, createPresentation as yc, clearSlideAnimations as yi, findSlidePlaceholder as yn, mergeTableCells as yo, clearShapeStroke as yr, getShapeChartSeriesValues as ys, getShapeTextAnchor as yt, getSlideInfo as z, getOrphanMediaPartNames as za, getShapeImageOpacity as zi, getShapeAdjustValues as zn, getExtendedProperties as zo, setShapeStrokeJoin as zr, getSlideMasterBackgroundImageBytes as zs, clearShapeEffects as zt };
17443
18830
 
17444
- //# sourceMappingURL=api-Dt6q_IAv.js.map
18831
+ //# sourceMappingURL=api-DTHZaBPq.js.map