@cj-tech-master/excelts 9.4.2 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (618) hide show
  1. package/dist/browser/index.browser.d.ts +8 -5
  2. package/dist/browser/index.browser.js +19 -1
  3. package/dist/browser/index.d.ts +4 -2
  4. package/dist/browser/index.js +9 -1
  5. package/dist/browser/modules/excel/chart/cache-populator.d.ts +49 -0
  6. package/dist/browser/modules/excel/chart/cache-populator.js +1171 -0
  7. package/dist/browser/modules/excel/chart/chart-api.d.ts +92 -0
  8. package/dist/browser/modules/excel/chart/chart-api.js +364 -0
  9. package/dist/browser/modules/excel/chart/chart-builder.d.ts +48 -0
  10. package/dist/browser/modules/excel/chart/chart-builder.js +2432 -0
  11. package/dist/browser/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  12. package/dist/browser/modules/excel/chart/chart-ex-builder.js +903 -0
  13. package/dist/browser/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  14. package/dist/browser/modules/excel/chart/chart-ex-parser.js +1205 -0
  15. package/dist/browser/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  16. package/dist/browser/modules/excel/chart/chart-ex-renderer.js +5352 -0
  17. package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +531 -0
  18. package/dist/browser/modules/excel/chart/chart-ex-types.js +11 -0
  19. package/dist/browser/modules/excel/chart/chart-images.d.ts +78 -0
  20. package/dist/browser/modules/excel/chart/chart-images.js +363 -0
  21. package/dist/browser/modules/excel/chart/chart-presets.d.ts +392 -0
  22. package/dist/browser/modules/excel/chart/chart-presets.js +179 -0
  23. package/dist/browser/modules/excel/chart/chart-renderer.d.ts +550 -0
  24. package/dist/browser/modules/excel/chart/chart-renderer.js +6440 -0
  25. package/dist/browser/modules/excel/chart/chart-sidecar.d.ts +21 -0
  26. package/dist/browser/modules/excel/chart/chart-sidecar.js +427 -0
  27. package/dist/browser/modules/excel/chart/chart-utils.d.ts +306 -0
  28. package/dist/browser/modules/excel/chart/chart-utils.js +821 -0
  29. package/dist/browser/modules/excel/chart/chart.d.ts +504 -0
  30. package/dist/browser/modules/excel/chart/chart.js +1320 -0
  31. package/dist/browser/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  32. package/dist/browser/modules/excel/chart/glyph-rasterizer.js +658 -0
  33. package/dist/browser/modules/excel/chart/index.d.ts +54 -0
  34. package/dist/browser/modules/excel/chart/index.js +46 -0
  35. package/dist/browser/modules/excel/chart/install.d.ts +44 -0
  36. package/dist/browser/modules/excel/chart/install.js +91 -0
  37. package/dist/browser/modules/excel/chart/shape-properties.d.ts +156 -0
  38. package/dist/browser/modules/excel/chart/shape-properties.js +1557 -0
  39. package/dist/browser/modules/excel/chart/stroke-font.d.ts +36 -0
  40. package/dist/browser/modules/excel/chart/stroke-font.js +1556 -0
  41. package/dist/browser/modules/excel/chart/topojson.d.ts +98 -0
  42. package/dist/browser/modules/excel/chart/topojson.js +236 -0
  43. package/dist/browser/modules/excel/chart/types.d.ts +2559 -0
  44. package/dist/browser/modules/excel/chart/types.js +8 -0
  45. package/dist/browser/modules/excel/chart-host-registry.d.ts +157 -0
  46. package/dist/browser/modules/excel/chart-host-registry.js +90 -0
  47. package/dist/browser/modules/excel/chartsheet.d.ts +102 -0
  48. package/dist/browser/modules/excel/chartsheet.js +196 -0
  49. package/dist/browser/modules/excel/defined-names.d.ts +35 -0
  50. package/dist/browser/modules/excel/defined-names.js +44 -4
  51. package/dist/browser/modules/excel/errors.d.ts +6 -0
  52. package/dist/browser/modules/excel/errors.js +9 -0
  53. package/dist/browser/modules/excel/form-control.d.ts +6 -0
  54. package/dist/browser/modules/excel/form-control.js +17 -0
  55. package/dist/browser/modules/excel/image.js +12 -2
  56. package/dist/browser/modules/excel/pivot-chart.d.ts +7 -0
  57. package/dist/browser/modules/excel/pivot-chart.js +53 -0
  58. package/dist/browser/modules/excel/pivot-table.d.ts +55 -0
  59. package/dist/browser/modules/excel/pivot-table.js +35 -0
  60. package/dist/browser/modules/excel/range.js +5 -1
  61. package/dist/browser/modules/excel/sparkline/index.d.ts +7 -0
  62. package/dist/browser/modules/excel/sparkline/index.js +7 -0
  63. package/dist/browser/modules/excel/sparkline/sparkline.d.ts +206 -0
  64. package/dist/browser/modules/excel/sparkline/sparkline.js +750 -0
  65. package/dist/browser/modules/excel/stream/worksheet-writer.js +3 -2
  66. package/dist/browser/modules/excel/table.js +42 -6
  67. package/dist/browser/modules/excel/types.d.ts +72 -0
  68. package/dist/browser/modules/excel/utils/address.d.ts +18 -0
  69. package/dist/browser/modules/excel/utils/address.js +28 -0
  70. package/dist/browser/modules/excel/utils/drawing-utils.js +11 -6
  71. package/dist/browser/modules/excel/utils/guid.d.ts +15 -0
  72. package/dist/browser/modules/excel/utils/guid.js +35 -0
  73. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +74 -0
  74. package/dist/browser/modules/excel/utils/ooxml-paths.js +206 -9
  75. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  76. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  77. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  78. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  79. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  80. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  81. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  82. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  83. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  84. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  85. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  86. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  87. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  88. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  89. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  90. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  91. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  92. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  93. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  94. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  95. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  96. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  97. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  98. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  99. package/dist/browser/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  100. package/dist/browser/modules/excel/utils/ooxml-validator/context.js +191 -0
  101. package/dist/browser/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  102. package/dist/browser/modules/excel/utils/ooxml-validator/index.js +102 -0
  103. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  104. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  105. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  106. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  107. package/dist/browser/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  108. package/dist/browser/modules/excel/utils/ooxml-validator/types.js +12 -0
  109. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  110. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  111. package/dist/browser/modules/excel/workbook.browser.d.ts +248 -30
  112. package/dist/browser/modules/excel/workbook.browser.js +966 -31
  113. package/dist/browser/modules/excel/workbook.d.ts +43 -0
  114. package/dist/browser/modules/excel/workbook.js +48 -0
  115. package/dist/browser/modules/excel/worksheet.d.ts +157 -3
  116. package/dist/browser/modules/excel/worksheet.js +394 -35
  117. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +40 -0
  118. package/dist/browser/modules/excel/xlsx/rel-type.js +41 -1
  119. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  120. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  121. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  122. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  123. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  124. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  125. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  126. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  127. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  128. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  129. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  130. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  131. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  132. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  133. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  134. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  135. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  136. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  137. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  138. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  139. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  140. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  141. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  142. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  143. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  144. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  145. package/dist/browser/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  146. package/dist/browser/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  147. package/dist/browser/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  148. package/dist/browser/modules/excel/xlsx/xform/xsd-values.js +101 -0
  149. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  150. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +4422 -78
  151. package/dist/browser/modules/pdf/builder/document-builder.d.ts +74 -0
  152. package/dist/browser/modules/pdf/builder/document-builder.js +507 -2
  153. package/dist/browser/modules/pdf/builder/pdf-editor.js +48 -3
  154. package/dist/browser/modules/pdf/excel-bridge.d.ts +69 -0
  155. package/dist/browser/modules/pdf/excel-bridge.js +683 -12
  156. package/dist/browser/modules/pdf/font/font-manager.d.ts +25 -0
  157. package/dist/browser/modules/pdf/font/font-manager.js +39 -0
  158. package/dist/browser/modules/pdf/index.d.ts +5 -2
  159. package/dist/browser/modules/pdf/index.js +3 -1
  160. package/dist/browser/modules/pdf/render/chart-surface.d.ts +33 -0
  161. package/dist/browser/modules/pdf/render/chart-surface.js +200 -0
  162. package/dist/browser/modules/pdf/render/layout-engine.d.ts +22 -1
  163. package/dist/browser/modules/pdf/render/layout-engine.js +436 -56
  164. package/dist/browser/modules/pdf/render/page-renderer.js +169 -28
  165. package/dist/browser/modules/pdf/render/pdf-exporter.js +117 -7
  166. package/dist/browser/modules/pdf/types.d.ts +227 -23
  167. package/dist/browser/modules/pdf/types.js +4 -0
  168. package/dist/browser/modules/pdf/word-bridge.d.ts +47 -0
  169. package/dist/browser/modules/pdf/word-bridge.js +304 -0
  170. package/dist/browser/modules/word/constants.d.ts +179 -0
  171. package/dist/browser/modules/word/constants.js +231 -0
  172. package/dist/browser/modules/word/content-types.d.ts +27 -0
  173. package/dist/browser/modules/word/content-types.js +53 -0
  174. package/dist/browser/modules/word/digital-signatures.d.ts +87 -0
  175. package/dist/browser/modules/word/digital-signatures.js +134 -0
  176. package/dist/browser/modules/word/document.d.ts +728 -0
  177. package/dist/browser/modules/word/document.js +1795 -0
  178. package/dist/browser/modules/word/docx-packager.d.ts +14 -0
  179. package/dist/browser/modules/word/docx-packager.js +822 -0
  180. package/dist/browser/modules/word/docx-reader.d.ts +11 -0
  181. package/dist/browser/modules/word/docx-reader.js +4929 -0
  182. package/dist/browser/modules/word/encryption.d.ts +102 -0
  183. package/dist/browser/modules/word/encryption.js +274 -0
  184. package/dist/browser/modules/word/errors.d.ts +49 -0
  185. package/dist/browser/modules/word/errors.js +68 -0
  186. package/dist/browser/modules/word/font-obfuscation.d.ts +31 -0
  187. package/dist/browser/modules/word/font-obfuscation.js +83 -0
  188. package/dist/browser/modules/word/html-renderer.d.ts +38 -0
  189. package/dist/browser/modules/word/html-renderer.js +782 -0
  190. package/dist/browser/modules/word/index.base.d.ts +19 -0
  191. package/dist/browser/modules/word/index.base.js +51 -0
  192. package/dist/browser/modules/word/index.browser.d.ts +4 -0
  193. package/dist/browser/modules/word/index.browser.js +4 -0
  194. package/dist/browser/modules/word/index.d.ts +4 -0
  195. package/dist/browser/modules/word/index.js +4 -0
  196. package/dist/browser/modules/word/internal-utils.d.ts +23 -0
  197. package/dist/browser/modules/word/internal-utils.js +54 -0
  198. package/dist/browser/modules/word/relationships.d.ts +31 -0
  199. package/dist/browser/modules/word/relationships.js +56 -0
  200. package/dist/browser/modules/word/types.d.ts +2325 -0
  201. package/dist/browser/modules/word/types.js +10 -0
  202. package/dist/browser/modules/word/units.d.ts +49 -0
  203. package/dist/browser/modules/word/units.js +111 -0
  204. package/dist/browser/modules/word/writers/chart-writer.d.ts +10 -0
  205. package/dist/browser/modules/word/writers/chart-writer.js +385 -0
  206. package/dist/browser/modules/word/writers/checkbox-writer.d.ts +9 -0
  207. package/dist/browser/modules/word/writers/checkbox-writer.js +42 -0
  208. package/dist/browser/modules/word/writers/comment-writer.d.ts +15 -0
  209. package/dist/browser/modules/word/writers/comment-writer.js +70 -0
  210. package/dist/browser/modules/word/writers/document-writer.d.ts +16 -0
  211. package/dist/browser/modules/word/writers/document-writer.js +461 -0
  212. package/dist/browser/modules/word/writers/footnote-writer.d.ts +11 -0
  213. package/dist/browser/modules/word/writers/footnote-writer.js +72 -0
  214. package/dist/browser/modules/word/writers/header-footer-writer.d.ts +13 -0
  215. package/dist/browser/modules/word/writers/header-footer-writer.js +129 -0
  216. package/dist/browser/modules/word/writers/image-writer.d.ts +10 -0
  217. package/dist/browser/modules/word/writers/image-writer.js +185 -0
  218. package/dist/browser/modules/word/writers/math-writer.d.ts +9 -0
  219. package/dist/browser/modules/word/writers/math-writer.js +428 -0
  220. package/dist/browser/modules/word/writers/numbering-writer.d.ts +10 -0
  221. package/dist/browser/modules/word/writers/numbering-writer.js +125 -0
  222. package/dist/browser/modules/word/writers/paragraph-writer.d.ts +13 -0
  223. package/dist/browser/modules/word/writers/paragraph-writer.js +516 -0
  224. package/dist/browser/modules/word/writers/parts-writer.d.ts +26 -0
  225. package/dist/browser/modules/word/writers/parts-writer.js +660 -0
  226. package/dist/browser/modules/word/writers/run-writer.d.ts +15 -0
  227. package/dist/browser/modules/word/writers/run-writer.js +649 -0
  228. package/dist/browser/modules/word/writers/section-writer.d.ts +10 -0
  229. package/dist/browser/modules/word/writers/section-writer.js +238 -0
  230. package/dist/browser/modules/word/writers/styles-writer.d.ts +10 -0
  231. package/dist/browser/modules/word/writers/styles-writer.js +242 -0
  232. package/dist/browser/modules/word/writers/table-writer.d.ts +10 -0
  233. package/dist/browser/modules/word/writers/table-writer.js +503 -0
  234. package/dist/browser/modules/word/writers/textbox-writer.d.ts +9 -0
  235. package/dist/browser/modules/word/writers/textbox-writer.js +53 -0
  236. package/dist/browser/modules/word/writers/toc-writer.d.ts +9 -0
  237. package/dist/browser/modules/word/writers/toc-writer.js +79 -0
  238. package/dist/browser/modules/xml/encode.d.ts +56 -7
  239. package/dist/browser/modules/xml/encode.js +157 -11
  240. package/dist/cjs/index.js +13 -2
  241. package/dist/cjs/modules/excel/chart/cache-populator.js +1178 -0
  242. package/dist/cjs/modules/excel/chart/chart-api.js +371 -0
  243. package/dist/cjs/modules/excel/chart/chart-builder.js +2440 -0
  244. package/dist/cjs/modules/excel/chart/chart-ex-builder.js +907 -0
  245. package/dist/cjs/modules/excel/chart/chart-ex-parser.js +1208 -0
  246. package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +5364 -0
  247. package/dist/cjs/modules/excel/chart/chart-ex-types.js +12 -0
  248. package/dist/cjs/modules/excel/chart/chart-images.js +366 -0
  249. package/dist/cjs/modules/excel/chart/chart-presets.js +184 -0
  250. package/dist/cjs/modules/excel/chart/chart-renderer.js +6450 -0
  251. package/dist/cjs/modules/excel/chart/chart-sidecar.js +433 -0
  252. package/dist/cjs/modules/excel/chart/chart-utils.js +845 -0
  253. package/dist/cjs/modules/excel/chart/chart.js +1324 -0
  254. package/dist/cjs/modules/excel/chart/glyph-rasterizer.js +664 -0
  255. package/dist/cjs/modules/excel/chart/index.js +101 -0
  256. package/dist/cjs/modules/excel/chart/install.js +95 -0
  257. package/dist/cjs/modules/excel/chart/shape-properties.js +1577 -0
  258. package/dist/cjs/modules/excel/chart/stroke-font.js +1559 -0
  259. package/dist/cjs/modules/excel/chart/topojson.js +239 -0
  260. package/dist/cjs/modules/excel/chart/types.js +9 -0
  261. package/dist/cjs/modules/excel/chart-host-registry.js +96 -0
  262. package/dist/cjs/modules/excel/chartsheet.js +199 -0
  263. package/dist/cjs/modules/excel/defined-names.js +44 -4
  264. package/dist/cjs/modules/excel/errors.js +11 -1
  265. package/dist/cjs/modules/excel/form-control.js +17 -0
  266. package/dist/cjs/modules/excel/image.js +12 -2
  267. package/dist/cjs/modules/excel/pivot-chart.js +56 -0
  268. package/dist/cjs/modules/excel/pivot-table.js +35 -0
  269. package/dist/cjs/modules/excel/range.js +5 -1
  270. package/dist/cjs/modules/excel/sparkline/index.js +23 -0
  271. package/dist/cjs/modules/excel/sparkline/sparkline.js +756 -0
  272. package/dist/cjs/modules/excel/stream/worksheet-writer.js +3 -2
  273. package/dist/cjs/modules/excel/table.js +42 -6
  274. package/dist/cjs/modules/excel/utils/address.js +29 -0
  275. package/dist/cjs/modules/excel/utils/drawing-utils.js +11 -6
  276. package/dist/cjs/modules/excel/utils/guid.js +38 -0
  277. package/dist/cjs/modules/excel/utils/ooxml-paths.js +246 -9
  278. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +103 -0
  279. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart.js +2128 -0
  280. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chartsheet.js +29 -0
  281. package/dist/cjs/modules/excel/utils/ooxml-validator/check-content-types.js +184 -0
  282. package/dist/cjs/modules/excel/utils/ooxml-validator/check-drawing.js +270 -0
  283. package/dist/cjs/modules/excel/utils/ooxml-validator/check-pivot.js +107 -0
  284. package/dist/cjs/modules/excel/utils/ooxml-validator/check-relationships.js +188 -0
  285. package/dist/cjs/modules/excel/utils/ooxml-validator/check-structure.js +60 -0
  286. package/dist/cjs/modules/excel/utils/ooxml-validator/check-styles.js +92 -0
  287. package/dist/cjs/modules/excel/utils/ooxml-validator/check-table.js +180 -0
  288. package/dist/cjs/modules/excel/utils/ooxml-validator/check-workbook.js +166 -0
  289. package/dist/cjs/modules/excel/utils/ooxml-validator/check-worksheet.js +572 -0
  290. package/dist/cjs/modules/excel/utils/ooxml-validator/context.js +196 -0
  291. package/dist/cjs/modules/excel/utils/ooxml-validator/index.js +105 -0
  292. package/dist/cjs/modules/excel/utils/ooxml-validator/path-utils.js +168 -0
  293. package/dist/cjs/modules/excel/utils/ooxml-validator/reporter.js +66 -0
  294. package/dist/cjs/modules/excel/utils/ooxml-validator/types.js +13 -0
  295. package/dist/cjs/modules/excel/utils/ooxml-validator/xml-utils.js +110 -0
  296. package/dist/cjs/modules/excel/workbook.browser.js +973 -38
  297. package/dist/cjs/modules/excel/workbook.js +48 -0
  298. package/dist/cjs/modules/excel/worksheet.js +393 -34
  299. package/dist/cjs/modules/excel/xlsx/rel-type.js +41 -1
  300. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  301. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  302. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  303. package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6003 -0
  304. package/dist/cjs/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +219 -0
  305. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +149 -10
  306. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  307. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  308. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  309. package/dist/cjs/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +228 -0
  310. package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  311. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  312. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  313. package/dist/cjs/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +444 -0
  314. package/dist/cjs/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  315. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +195 -19
  316. package/dist/cjs/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  317. package/dist/cjs/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  318. package/dist/cjs/modules/excel/xlsx/xform/xsd-values.js +106 -0
  319. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +4420 -76
  320. package/dist/cjs/modules/pdf/builder/document-builder.js +506 -1
  321. package/dist/cjs/modules/pdf/builder/pdf-editor.js +48 -3
  322. package/dist/cjs/modules/pdf/excel-bridge.js +684 -12
  323. package/dist/cjs/modules/pdf/font/font-manager.js +39 -0
  324. package/dist/cjs/modules/pdf/index.js +5 -1
  325. package/dist/cjs/modules/pdf/render/chart-surface.js +203 -0
  326. package/dist/cjs/modules/pdf/render/layout-engine.js +437 -56
  327. package/dist/cjs/modules/pdf/render/page-renderer.js +169 -28
  328. package/dist/cjs/modules/pdf/render/pdf-exporter.js +115 -5
  329. package/dist/cjs/modules/pdf/types.js +5 -0
  330. package/dist/cjs/modules/pdf/word-bridge.js +307 -0
  331. package/dist/cjs/modules/word/constants.js +234 -0
  332. package/dist/cjs/modules/word/content-types.js +57 -0
  333. package/dist/cjs/modules/word/digital-signatures.js +140 -0
  334. package/dist/cjs/modules/word/document.js +1909 -0
  335. package/dist/cjs/modules/word/docx-packager.js +825 -0
  336. package/dist/cjs/modules/word/docx-reader.js +4932 -0
  337. package/dist/cjs/modules/word/encryption.js +282 -0
  338. package/dist/cjs/modules/word/errors.js +88 -0
  339. package/dist/cjs/modules/word/font-obfuscation.js +88 -0
  340. package/dist/cjs/modules/word/html-renderer.js +785 -0
  341. package/dist/cjs/modules/word/index.base.js +199 -0
  342. package/dist/cjs/modules/word/index.browser.js +20 -0
  343. package/dist/cjs/modules/word/index.js +20 -0
  344. package/dist/cjs/modules/word/internal-utils.js +59 -0
  345. package/dist/cjs/modules/word/relationships.js +60 -0
  346. package/dist/cjs/modules/word/types.js +11 -0
  347. package/dist/cjs/modules/word/units.js +135 -0
  348. package/dist/cjs/modules/word/writers/chart-writer.js +388 -0
  349. package/dist/cjs/modules/word/writers/checkbox-writer.js +45 -0
  350. package/dist/cjs/modules/word/writers/comment-writer.js +74 -0
  351. package/dist/cjs/modules/word/writers/document-writer.js +465 -0
  352. package/dist/cjs/modules/word/writers/footnote-writer.js +76 -0
  353. package/dist/cjs/modules/word/writers/header-footer-writer.js +134 -0
  354. package/dist/cjs/modules/word/writers/image-writer.js +188 -0
  355. package/dist/cjs/modules/word/writers/math-writer.js +431 -0
  356. package/dist/cjs/modules/word/writers/numbering-writer.js +128 -0
  357. package/dist/cjs/modules/word/writers/paragraph-writer.js +521 -0
  358. package/dist/cjs/modules/word/writers/parts-writer.js +671 -0
  359. package/dist/cjs/modules/word/writers/run-writer.js +655 -0
  360. package/dist/cjs/modules/word/writers/section-writer.js +241 -0
  361. package/dist/cjs/modules/word/writers/styles-writer.js +245 -0
  362. package/dist/cjs/modules/word/writers/table-writer.js +506 -0
  363. package/dist/cjs/modules/word/writers/textbox-writer.js +56 -0
  364. package/dist/cjs/modules/word/writers/toc-writer.js +82 -0
  365. package/dist/cjs/modules/xml/encode.js +158 -11
  366. package/dist/esm/index.browser.js +20 -2
  367. package/dist/esm/index.js +9 -1
  368. package/dist/esm/modules/excel/chart/cache-populator.js +1171 -0
  369. package/dist/esm/modules/excel/chart/chart-api.js +364 -0
  370. package/dist/esm/modules/excel/chart/chart-builder.js +2432 -0
  371. package/dist/esm/modules/excel/chart/chart-ex-builder.js +903 -0
  372. package/dist/esm/modules/excel/chart/chart-ex-parser.js +1205 -0
  373. package/dist/esm/modules/excel/chart/chart-ex-renderer.js +5352 -0
  374. package/dist/esm/modules/excel/chart/chart-ex-types.js +11 -0
  375. package/dist/esm/modules/excel/chart/chart-images.js +363 -0
  376. package/dist/esm/modules/excel/chart/chart-presets.js +179 -0
  377. package/dist/esm/modules/excel/chart/chart-renderer.js +6440 -0
  378. package/dist/esm/modules/excel/chart/chart-sidecar.js +427 -0
  379. package/dist/esm/modules/excel/chart/chart-utils.js +821 -0
  380. package/dist/esm/modules/excel/chart/chart.js +1320 -0
  381. package/dist/esm/modules/excel/chart/glyph-rasterizer.js +658 -0
  382. package/dist/esm/modules/excel/chart/index.js +46 -0
  383. package/dist/esm/modules/excel/chart/install.js +91 -0
  384. package/dist/esm/modules/excel/chart/shape-properties.js +1557 -0
  385. package/dist/esm/modules/excel/chart/stroke-font.js +1556 -0
  386. package/dist/esm/modules/excel/chart/topojson.js +236 -0
  387. package/dist/esm/modules/excel/chart/types.js +8 -0
  388. package/dist/esm/modules/excel/chart-host-registry.js +90 -0
  389. package/dist/esm/modules/excel/chartsheet.js +196 -0
  390. package/dist/esm/modules/excel/defined-names.js +44 -4
  391. package/dist/esm/modules/excel/errors.js +9 -0
  392. package/dist/esm/modules/excel/form-control.js +17 -0
  393. package/dist/esm/modules/excel/image.js +12 -2
  394. package/dist/esm/modules/excel/pivot-chart.js +53 -0
  395. package/dist/esm/modules/excel/pivot-table.js +35 -0
  396. package/dist/esm/modules/excel/range.js +5 -1
  397. package/dist/esm/modules/excel/sparkline/index.js +7 -0
  398. package/dist/esm/modules/excel/sparkline/sparkline.js +750 -0
  399. package/dist/esm/modules/excel/stream/worksheet-writer.js +3 -2
  400. package/dist/esm/modules/excel/table.js +42 -6
  401. package/dist/esm/modules/excel/utils/address.js +28 -0
  402. package/dist/esm/modules/excel/utils/drawing-utils.js +11 -6
  403. package/dist/esm/modules/excel/utils/guid.js +35 -0
  404. package/dist/esm/modules/excel/utils/ooxml-paths.js +206 -9
  405. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  406. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  407. package/dist/esm/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  408. package/dist/esm/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  409. package/dist/esm/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  410. package/dist/esm/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  411. package/dist/esm/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  412. package/dist/esm/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  413. package/dist/esm/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  414. package/dist/esm/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  415. package/dist/esm/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  416. package/dist/esm/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  417. package/dist/esm/modules/excel/utils/ooxml-validator/context.js +191 -0
  418. package/dist/esm/modules/excel/utils/ooxml-validator/index.js +102 -0
  419. package/dist/esm/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  420. package/dist/esm/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  421. package/dist/esm/modules/excel/utils/ooxml-validator/types.js +12 -0
  422. package/dist/esm/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  423. package/dist/esm/modules/excel/workbook.browser.js +969 -34
  424. package/dist/esm/modules/excel/workbook.js +48 -0
  425. package/dist/esm/modules/excel/worksheet.js +394 -35
  426. package/dist/esm/modules/excel/xlsx/rel-type.js +41 -1
  427. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  428. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  429. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  430. package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  431. package/dist/esm/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  432. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  433. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  434. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  435. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  436. package/dist/esm/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  437. package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  438. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  439. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  440. package/dist/esm/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  441. package/dist/esm/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  442. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  443. package/dist/esm/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  444. package/dist/esm/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  445. package/dist/esm/modules/excel/xlsx/xform/xsd-values.js +101 -0
  446. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +4422 -78
  447. package/dist/esm/modules/pdf/builder/document-builder.js +507 -2
  448. package/dist/esm/modules/pdf/builder/pdf-editor.js +48 -3
  449. package/dist/esm/modules/pdf/excel-bridge.js +683 -12
  450. package/dist/esm/modules/pdf/font/font-manager.js +39 -0
  451. package/dist/esm/modules/pdf/index.js +3 -1
  452. package/dist/esm/modules/pdf/render/chart-surface.js +200 -0
  453. package/dist/esm/modules/pdf/render/layout-engine.js +436 -56
  454. package/dist/esm/modules/pdf/render/page-renderer.js +169 -28
  455. package/dist/esm/modules/pdf/render/pdf-exporter.js +117 -7
  456. package/dist/esm/modules/pdf/types.js +4 -0
  457. package/dist/esm/modules/pdf/word-bridge.js +304 -0
  458. package/dist/esm/modules/word/constants.js +231 -0
  459. package/dist/esm/modules/word/content-types.js +53 -0
  460. package/dist/esm/modules/word/digital-signatures.js +134 -0
  461. package/dist/esm/modules/word/document.js +1795 -0
  462. package/dist/esm/modules/word/docx-packager.js +822 -0
  463. package/dist/esm/modules/word/docx-reader.js +4929 -0
  464. package/dist/esm/modules/word/encryption.js +274 -0
  465. package/dist/esm/modules/word/errors.js +68 -0
  466. package/dist/esm/modules/word/font-obfuscation.js +83 -0
  467. package/dist/esm/modules/word/html-renderer.js +782 -0
  468. package/dist/esm/modules/word/index.base.js +51 -0
  469. package/dist/esm/modules/word/index.browser.js +4 -0
  470. package/dist/esm/modules/word/index.js +4 -0
  471. package/dist/esm/modules/word/internal-utils.js +54 -0
  472. package/dist/esm/modules/word/relationships.js +56 -0
  473. package/dist/esm/modules/word/types.js +10 -0
  474. package/dist/esm/modules/word/units.js +111 -0
  475. package/dist/esm/modules/word/writers/chart-writer.js +385 -0
  476. package/dist/esm/modules/word/writers/checkbox-writer.js +42 -0
  477. package/dist/esm/modules/word/writers/comment-writer.js +70 -0
  478. package/dist/esm/modules/word/writers/document-writer.js +461 -0
  479. package/dist/esm/modules/word/writers/footnote-writer.js +72 -0
  480. package/dist/esm/modules/word/writers/header-footer-writer.js +129 -0
  481. package/dist/esm/modules/word/writers/image-writer.js +185 -0
  482. package/dist/esm/modules/word/writers/math-writer.js +428 -0
  483. package/dist/esm/modules/word/writers/numbering-writer.js +125 -0
  484. package/dist/esm/modules/word/writers/paragraph-writer.js +516 -0
  485. package/dist/esm/modules/word/writers/parts-writer.js +660 -0
  486. package/dist/esm/modules/word/writers/run-writer.js +649 -0
  487. package/dist/esm/modules/word/writers/section-writer.js +238 -0
  488. package/dist/esm/modules/word/writers/styles-writer.js +242 -0
  489. package/dist/esm/modules/word/writers/table-writer.js +503 -0
  490. package/dist/esm/modules/word/writers/textbox-writer.js +53 -0
  491. package/dist/esm/modules/word/writers/toc-writer.js +79 -0
  492. package/dist/esm/modules/xml/encode.js +157 -11
  493. package/dist/iife/excelts.iife.js +11789 -687
  494. package/dist/iife/excelts.iife.js.map +1 -1
  495. package/dist/iife/excelts.iife.min.js +52 -44
  496. package/dist/types/index.browser.d.ts +8 -5
  497. package/dist/types/index.d.ts +4 -2
  498. package/dist/types/modules/excel/chart/cache-populator.d.ts +49 -0
  499. package/dist/types/modules/excel/chart/chart-api.d.ts +92 -0
  500. package/dist/types/modules/excel/chart/chart-builder.d.ts +48 -0
  501. package/dist/types/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  502. package/dist/types/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  503. package/dist/types/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  504. package/dist/types/modules/excel/chart/chart-ex-types.d.ts +531 -0
  505. package/dist/types/modules/excel/chart/chart-images.d.ts +78 -0
  506. package/dist/types/modules/excel/chart/chart-presets.d.ts +392 -0
  507. package/dist/types/modules/excel/chart/chart-renderer.d.ts +550 -0
  508. package/dist/types/modules/excel/chart/chart-sidecar.d.ts +21 -0
  509. package/dist/types/modules/excel/chart/chart-utils.d.ts +306 -0
  510. package/dist/types/modules/excel/chart/chart.d.ts +504 -0
  511. package/dist/types/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  512. package/dist/types/modules/excel/chart/index.d.ts +54 -0
  513. package/dist/types/modules/excel/chart/install.d.ts +44 -0
  514. package/dist/types/modules/excel/chart/shape-properties.d.ts +156 -0
  515. package/dist/types/modules/excel/chart/stroke-font.d.ts +36 -0
  516. package/dist/types/modules/excel/chart/topojson.d.ts +98 -0
  517. package/dist/types/modules/excel/chart/types.d.ts +2559 -0
  518. package/dist/types/modules/excel/chart-host-registry.d.ts +157 -0
  519. package/dist/types/modules/excel/chartsheet.d.ts +102 -0
  520. package/dist/types/modules/excel/defined-names.d.ts +35 -0
  521. package/dist/types/modules/excel/errors.d.ts +6 -0
  522. package/dist/types/modules/excel/form-control.d.ts +6 -0
  523. package/dist/types/modules/excel/pivot-chart.d.ts +7 -0
  524. package/dist/types/modules/excel/pivot-table.d.ts +55 -0
  525. package/dist/types/modules/excel/sparkline/index.d.ts +7 -0
  526. package/dist/types/modules/excel/sparkline/sparkline.d.ts +206 -0
  527. package/dist/types/modules/excel/types.d.ts +72 -0
  528. package/dist/types/modules/excel/utils/address.d.ts +18 -0
  529. package/dist/types/modules/excel/utils/guid.d.ts +15 -0
  530. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +74 -0
  531. package/dist/types/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  532. package/dist/types/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  533. package/dist/types/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  534. package/dist/types/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  535. package/dist/types/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  536. package/dist/types/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  537. package/dist/types/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  538. package/dist/types/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  539. package/dist/types/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  540. package/dist/types/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  541. package/dist/types/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  542. package/dist/types/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  543. package/dist/types/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  544. package/dist/types/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  545. package/dist/types/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  546. package/dist/types/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  547. package/dist/types/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  548. package/dist/types/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  549. package/dist/types/modules/excel/workbook.browser.d.ts +248 -30
  550. package/dist/types/modules/excel/workbook.d.ts +43 -0
  551. package/dist/types/modules/excel/worksheet.d.ts +157 -3
  552. package/dist/types/modules/excel/xlsx/rel-type.d.ts +40 -0
  553. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  554. package/dist/types/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  555. package/dist/types/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  556. package/dist/types/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  557. package/dist/types/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  558. package/dist/types/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  559. package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  560. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  561. package/dist/types/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  562. package/dist/types/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  563. package/dist/types/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  564. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  565. package/dist/types/modules/pdf/builder/document-builder.d.ts +74 -0
  566. package/dist/types/modules/pdf/excel-bridge.d.ts +69 -0
  567. package/dist/types/modules/pdf/font/font-manager.d.ts +25 -0
  568. package/dist/types/modules/pdf/index.d.ts +5 -2
  569. package/dist/types/modules/pdf/render/chart-surface.d.ts +33 -0
  570. package/dist/types/modules/pdf/render/layout-engine.d.ts +22 -1
  571. package/dist/types/modules/pdf/types.d.ts +227 -23
  572. package/dist/types/modules/pdf/word-bridge.d.ts +47 -0
  573. package/dist/types/modules/word/constants.d.ts +179 -0
  574. package/dist/types/modules/word/content-types.d.ts +27 -0
  575. package/dist/types/modules/word/digital-signatures.d.ts +87 -0
  576. package/dist/types/modules/word/document.d.ts +728 -0
  577. package/dist/types/modules/word/docx-packager.d.ts +14 -0
  578. package/dist/types/modules/word/docx-reader.d.ts +11 -0
  579. package/dist/types/modules/word/encryption.d.ts +102 -0
  580. package/dist/types/modules/word/errors.d.ts +49 -0
  581. package/dist/types/modules/word/font-obfuscation.d.ts +31 -0
  582. package/dist/types/modules/word/html-renderer.d.ts +38 -0
  583. package/dist/types/modules/word/index.base.d.ts +19 -0
  584. package/dist/types/modules/word/index.browser.d.ts +4 -0
  585. package/dist/types/modules/word/index.d.ts +4 -0
  586. package/dist/types/modules/word/internal-utils.d.ts +23 -0
  587. package/dist/types/modules/word/relationships.d.ts +31 -0
  588. package/dist/types/modules/word/types.d.ts +2325 -0
  589. package/dist/types/modules/word/units.d.ts +49 -0
  590. package/dist/types/modules/word/writers/chart-writer.d.ts +10 -0
  591. package/dist/types/modules/word/writers/checkbox-writer.d.ts +9 -0
  592. package/dist/types/modules/word/writers/comment-writer.d.ts +15 -0
  593. package/dist/types/modules/word/writers/document-writer.d.ts +16 -0
  594. package/dist/types/modules/word/writers/footnote-writer.d.ts +11 -0
  595. package/dist/types/modules/word/writers/header-footer-writer.d.ts +13 -0
  596. package/dist/types/modules/word/writers/image-writer.d.ts +10 -0
  597. package/dist/types/modules/word/writers/math-writer.d.ts +9 -0
  598. package/dist/types/modules/word/writers/numbering-writer.d.ts +10 -0
  599. package/dist/types/modules/word/writers/paragraph-writer.d.ts +13 -0
  600. package/dist/types/modules/word/writers/parts-writer.d.ts +26 -0
  601. package/dist/types/modules/word/writers/run-writer.d.ts +15 -0
  602. package/dist/types/modules/word/writers/section-writer.d.ts +10 -0
  603. package/dist/types/modules/word/writers/styles-writer.d.ts +10 -0
  604. package/dist/types/modules/word/writers/table-writer.d.ts +10 -0
  605. package/dist/types/modules/word/writers/textbox-writer.d.ts +9 -0
  606. package/dist/types/modules/word/writers/toc-writer.d.ts +9 -0
  607. package/dist/types/modules/xml/encode.d.ts +56 -7
  608. package/package.json +29 -11
  609. package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +0 -48
  610. package/dist/browser/modules/excel/utils/ooxml-validator.js +0 -493
  611. package/dist/browser/modules/excel/utils/passthrough-manager.d.ts +0 -77
  612. package/dist/browser/modules/excel/utils/passthrough-manager.js +0 -129
  613. package/dist/cjs/modules/excel/utils/ooxml-validator.js +0 -499
  614. package/dist/cjs/modules/excel/utils/passthrough-manager.js +0 -133
  615. package/dist/esm/modules/excel/utils/ooxml-validator.js +0 -493
  616. package/dist/esm/modules/excel/utils/passthrough-manager.js +0 -129
  617. package/dist/types/modules/excel/utils/ooxml-validator.d.ts +0 -48
  618. package/dist/types/modules/excel/utils/passthrough-manager.d.ts +0 -77
@@ -0,0 +1,2440 @@
1
+ "use strict";
2
+ /**
3
+ * Chart Builder - Constructs a ChartModel from simplified AddChartOptions.
4
+ *
5
+ * This bridges the high-level API (worksheet.addChart) to the full
6
+ * OOXML chart model that the XForm layer serialises.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.hexToColor = hexToColor;
10
+ exports.toShapeProperties = toShapeProperties;
11
+ exports.buildChartSeriesForType = buildChartSeriesForType;
12
+ exports.applyChartSeriesOptionsPatch = applyChartSeriesOptionsPatch;
13
+ exports.buildChartModel = buildChartModel;
14
+ exports.buildComboChartModel = buildComboChartModel;
15
+ const errors_1 = require("../errors.js");
16
+ const chart_utils_1 = require("./chart-utils");
17
+ const EMU_PER_POINT = 12700;
18
+ const DEFAULT_AXIS_START_ID = 100000000;
19
+ const AXIS_CHART_TYPES = new Set([
20
+ "bar",
21
+ "bar3D",
22
+ "line",
23
+ "line3D",
24
+ "area",
25
+ "area3D",
26
+ "scatter",
27
+ "bubble",
28
+ "radar",
29
+ "stock",
30
+ "surface",
31
+ "surface3D"
32
+ ]);
33
+ const NO_TRENDLINE_CHART_TYPES = new Set([
34
+ "pie",
35
+ "pie3D",
36
+ "doughnut",
37
+ "ofPie",
38
+ "surface",
39
+ "surface3D"
40
+ ]);
41
+ const PIE_FAMILY_CHART_TYPES = new Set([
42
+ "pie",
43
+ "pie3D",
44
+ "doughnut",
45
+ "ofPie"
46
+ ]);
47
+ /**
48
+ * Valid `c:dLblPos` values Excel accepts per chart type.
49
+ *
50
+ * Although ECMA-376 `ST_DLblPos` technically allows any of the nine
51
+ * values (`b | bestFit | ctr | inBase | inEnd | l | outEnd | r | t`)
52
+ * on any `c:dLbl` / `c:dLbls` element, Excel's reader is stricter:
53
+ * emitting a value outside the per-chart-type allow-list below
54
+ * triggers "Repaired Records: Drawing" warnings on open, and for
55
+ * doughnut charts the offending `drawing*.xml` part is stripped
56
+ * entirely ("Removed Part"). The allow-lists match the options
57
+ * surfaced by Excel 365's "Format Data Labels → Label Position"
58
+ * panel, which is the canonical UI reference.
59
+ *
60
+ * - `doughnut`: Excel's UI exposes no position choices at all, and
61
+ * any `c:dLblPos` in a doughnut chart's `c:dLbls` causes the
62
+ * entire drawing part to be removed on open. Use an empty list so
63
+ * the validator rejects every value.
64
+ * - `bar` / `bar3D`: `inBase` is unique to bar — it anchors the
65
+ * label to the axis end of a column, useful for negative values.
66
+ * - `pie`, `pie3D`, `ofPie`: share the pie label set. `bestFit` is
67
+ * Excel's default and the only value that lets Excel place labels
68
+ * automatically with leader lines.
69
+ * - `line` / `line3D` / `scatter` / `bubble` / `radar` / `stock`:
70
+ * share the cartesian label set (above / below / left / right /
71
+ * center).
72
+ * - `area` / `area3D`: Excel only accepts `ctr` for area fills.
73
+ * - `surface` / `surface3D`: data labels are already rejected
74
+ * wholesale by `validateChartLevelOptions`.
75
+ */
76
+ const VALID_DLBL_POSITIONS_BY_TYPE = {
77
+ bar: new Set(["ctr", "inBase", "inEnd", "outEnd"]),
78
+ bar3D: new Set(["ctr", "inBase", "inEnd", "outEnd"]),
79
+ line: new Set(["ctr", "l", "r", "t", "b"]),
80
+ line3D: new Set(["ctr", "l", "r", "t", "b"]),
81
+ scatter: new Set(["ctr", "l", "r", "t", "b"]),
82
+ bubble: new Set(["ctr", "l", "r", "t", "b"]),
83
+ radar: new Set(["ctr", "l", "r", "t", "b"]),
84
+ stock: new Set(["ctr", "l", "r", "t", "b"]),
85
+ pie: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
86
+ pie3D: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
87
+ ofPie: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
88
+ doughnut: new Set(),
89
+ area: new Set(["ctr"]),
90
+ area3D: new Set(["ctr"])
91
+ };
92
+ /**
93
+ * Simple axis ID allocator — scoped per buildChartModel call.
94
+ * Axis IDs only need to be unique within a single chart.
95
+ */
96
+ class AxIdAllocator {
97
+ constructor(start = DEFAULT_AXIS_START_ID) {
98
+ this.next = start;
99
+ }
100
+ alloc() {
101
+ return this.next++;
102
+ }
103
+ }
104
+ function makeNumRef(formula) {
105
+ return { formula, cache: { points: [] } };
106
+ }
107
+ function makeStrRef(formula) {
108
+ return { formula, cache: { points: [] } };
109
+ }
110
+ function makeNumData(formula) {
111
+ return { numRef: makeNumRef(formula) };
112
+ }
113
+ function makeCatData(formula) {
114
+ return { strRef: makeStrRef(formula) };
115
+ }
116
+ function makeAxisData(input) {
117
+ return typeof input === "string" ? makeCatData(input) : input;
118
+ }
119
+ function makeNumericAxisData(input) {
120
+ return typeof input === "string" ? { numRef: makeNumRef(input) } : input;
121
+ }
122
+ /**
123
+ * Wrap a scatter/bubble `xValues` input as the appropriate
124
+ * {@link AxisDataSource}. `xValueType` disambiguates the two OOXML
125
+ * spellings:
126
+ *
127
+ * - `"number"` (default) → `numRef` — standard scatter usage
128
+ * - `"text"` → `strRef` — labelled scatter / bubble with
129
+ * categorical x axis (Excel renders it as evenly-spaced labels)
130
+ *
131
+ * When the caller passes a pre-built `AxisDataSource`, the hint is
132
+ * ignored — the structure already carries the intent.
133
+ */
134
+ function makeXAxisData(input, xValueType) {
135
+ if (typeof input !== "string") {
136
+ return input;
137
+ }
138
+ return xValueType === "text" ? makeCatData(input) : makeNumericAxisData(input);
139
+ }
140
+ function assertChartOptions(condition, message) {
141
+ if (!condition) {
142
+ throw new errors_1.ChartOptionsError(message);
143
+ }
144
+ }
145
+ function assertFiniteNumber(value, path) {
146
+ assertChartOptions(typeof value === "number" && Number.isFinite(value), `${path} must be a finite number.`);
147
+ }
148
+ function assertIntegerInRange(value, path, min, max) {
149
+ assertFiniteNumber(value, path);
150
+ assertChartOptions(Number.isInteger(value) && value >= min && value <= max, `${path} must be an integer between ${min} and ${max}.`);
151
+ }
152
+ function assertNumberInRange(value, path, min, max) {
153
+ assertFiniteNumber(value, path);
154
+ assertChartOptions(value >= min && value <= max, `${path} must be between ${min} and ${max}.`);
155
+ }
156
+ function validateChartOptions(opts, path = "chart") {
157
+ assertChartOptions(!!opts && typeof opts === "object", `${path} options are required.`);
158
+ assertChartOptions(!!opts.type, `${path}.type is required.`);
159
+ validateChartLevelOptions(opts, path);
160
+ const series = opts.series ?? [];
161
+ // A chart with zero series is invalid — Excel will either refuse to
162
+ // open the file or render a broken chart area. Catch it at build
163
+ // time with a precise error instead of deferring to Excel.
164
+ assertChartOptions(series.length > 0, `${path}.series must contain at least one series.`);
165
+ for (let i = 0; i < series.length; i++) {
166
+ validateSeriesOptions(opts.type, series[i], `${path}.series[${i}]`);
167
+ }
168
+ }
169
+ function validateComboChartOptions(opts) {
170
+ assertChartOptions(!!opts && typeof opts === "object", "combo chart options are required.");
171
+ assertChartOptions(Array.isArray(opts.groups) && opts.groups.length > 0, "combo chart groups must contain at least one group.");
172
+ for (let i = 0; i < opts.groups.length; i++) {
173
+ validateChartOptions(opts.groups[i], `groups[${i}]`);
174
+ }
175
+ validateSharedChartOptions(opts, "combo chart");
176
+ }
177
+ function validateChartLevelOptions(opts, path) {
178
+ validateSharedChartOptions(opts, path);
179
+ if (opts.grouping !== undefined) {
180
+ assertChartOptions(opts.type === "bar" ||
181
+ opts.type === "bar3D" ||
182
+ opts.type === "line" ||
183
+ opts.type === "line3D" ||
184
+ opts.type === "area" ||
185
+ opts.type === "area3D", `${path}.grouping is only valid for bar, line, and area charts.`);
186
+ // `BarGrouping` and `LineGrouping` overlap on stacked/percentStacked but
187
+ // diverge on `clustered` (bar only) and `standard` (line/area only).
188
+ // Reject the wrong-family value up front instead of silently emitting
189
+ // invalid OOXML.
190
+ const g = opts.grouping;
191
+ if (opts.type === "bar" || opts.type === "bar3D") {
192
+ assertChartOptions(g === "clustered" || g === "stacked" || g === "percentStacked", `${path}.grouping=${JSON.stringify(g)} is not valid for bar charts (use "clustered" | "stacked" | "percentStacked").`);
193
+ }
194
+ else {
195
+ assertChartOptions(g === "standard" || g === "stacked" || g === "percentStacked", `${path}.grouping=${JSON.stringify(g)} is not valid for ${opts.type} charts (use "standard" | "stacked" | "percentStacked").`);
196
+ }
197
+ }
198
+ if (opts.barDir !== undefined) {
199
+ assertChartOptions(opts.type === "bar" || opts.type === "bar3D", `${path}.barDir is only valid for bar and bar3D charts.`);
200
+ }
201
+ if (opts.scatterStyle !== undefined) {
202
+ assertChartOptions(opts.type === "scatter", `${path}.scatterStyle is only valid for scatter charts.`);
203
+ }
204
+ if (opts.radarStyle !== undefined) {
205
+ assertChartOptions(opts.type === "radar", `${path}.radarStyle is only valid for radar charts.`);
206
+ }
207
+ if (opts.ofPieType !== undefined) {
208
+ assertChartOptions(opts.type === "ofPie", `${path}.ofPieType is only valid for ofPie charts.`);
209
+ }
210
+ if (opts.wireframe !== undefined) {
211
+ assertChartOptions(opts.type === "surface" || opts.type === "surface3D", `${path}.wireframe is only valid for surface and surface3D charts.`);
212
+ }
213
+ if (opts.bandFormats !== undefined) {
214
+ assertChartOptions(opts.type === "surface" || opts.type === "surface3D", `${path}.bandFormats is only valid for surface and surface3D charts.`);
215
+ for (let i = 0; i < opts.bandFormats.length; i++) {
216
+ assertIntegerInRange(opts.bandFormats[i].index, `${path}.bandFormats[${i}].index`, 0, Number.MAX_SAFE_INTEGER);
217
+ }
218
+ }
219
+ if (!AXIS_CHART_TYPES.has(opts.type)) {
220
+ assertChartOptions(opts.categoryAxis === undefined, `${path}.categoryAxis is not valid for ${opts.type} charts because they do not have axes.`);
221
+ assertChartOptions(opts.valueAxis === undefined, `${path}.valueAxis is not valid for ${opts.type} charts because they do not have axes.`);
222
+ }
223
+ if ((opts.type === "surface" || opts.type === "surface3D") && opts.dataLabels !== undefined) {
224
+ assertChartOptions(false, `${path}.dataLabels is not supported for surface charts.`);
225
+ }
226
+ if (opts.dataLabels) {
227
+ // Chart-level data labels mirror the series-level ones at the
228
+ // `CT_*Chart/c:dLbls` slot (e.g. `CT_BarChart/c:dLbls`). Excel
229
+ // applies the same per-chart-type restrictions on `c:dLblPos`
230
+ // at this level, so run the same validator here.
231
+ validateDataLabelsOptions(opts.type, opts.dataLabels, `${path}.dataLabels`);
232
+ }
233
+ if (opts.holeSize !== undefined) {
234
+ assertChartOptions(opts.type === "doughnut", `${path}.holeSize is only valid for doughnut charts.`);
235
+ assertIntegerInRange(opts.holeSize, `${path}.holeSize`, 0, 90);
236
+ }
237
+ if (opts.firstSliceAng !== undefined) {
238
+ assertChartOptions(PIE_FAMILY_CHART_TYPES.has(opts.type), `${path}.firstSliceAng is only valid for pie, doughnut, and ofPie charts.`);
239
+ assertIntegerInRange(opts.firstSliceAng, `${path}.firstSliceAng`, 0, 360);
240
+ }
241
+ if (opts.gapWidth !== undefined) {
242
+ assertChartOptions(opts.type === "bar" || opts.type === "bar3D" || opts.type === "ofPie", `${path}.gapWidth is only valid for bar, bar3D, and ofPie charts.`);
243
+ assertIntegerInRange(opts.gapWidth, `${path}.gapWidth`, 0, 500);
244
+ }
245
+ if (opts.gapDepth !== undefined) {
246
+ // `c:gapDepth` is only declared on the 3-D chart types'
247
+ // `CT_*3DChart` definitions (bar3D, line3D, area3D). `pie3D`
248
+ // does NOT have it despite the type being 3-D.
249
+ assertChartOptions(opts.type === "bar3D" || opts.type === "line3D" || opts.type === "area3D", `${path}.gapDepth is only valid for bar3D, line3D, and area3D charts.`);
250
+ assertIntegerInRange(opts.gapDepth, `${path}.gapDepth`, 0, 500);
251
+ }
252
+ if (opts.overlap !== undefined) {
253
+ // `c:overlap` belongs to `CT_BarChart` only — `CT_Bar3DChart`
254
+ // omits it. The writer rejects it on bar3D (see
255
+ // `buildChartTypeGroup:case "bar3D"`); keep the two in sync so
256
+ // the rejection surfaces here at authoring time with a
257
+ // consistent error.
258
+ assertChartOptions(opts.type === "bar", `${path}.overlap is only valid for 2-D bar charts (bar3D rejects overlap per CT_Bar3DChart).`);
259
+ assertIntegerInRange(opts.overlap, `${path}.overlap`, -100, 100);
260
+ }
261
+ if (opts.bubbleScale !== undefined) {
262
+ assertChartOptions(opts.type === "bubble", `${path}.bubbleScale is only valid for bubble charts.`);
263
+ assertIntegerInRange(opts.bubbleScale, `${path}.bubbleScale`, 0, 300);
264
+ }
265
+ if (opts.showNegBubbles !== undefined) {
266
+ assertChartOptions(opts.type === "bubble", `${path}.showNegBubbles is only valid for bubble charts.`);
267
+ }
268
+ if (opts.sizeRepresents !== undefined) {
269
+ assertChartOptions(opts.type === "bubble", `${path}.sizeRepresents is only valid for bubble charts.`);
270
+ }
271
+ if (opts.splitPos !== undefined) {
272
+ assertChartOptions(opts.type === "ofPie", `${path}.splitPos is only valid for ofPie charts.`);
273
+ assertFiniteNumber(opts.splitPos, `${path}.splitPos`);
274
+ }
275
+ if (opts.secondPieSize !== undefined) {
276
+ assertChartOptions(opts.type === "ofPie", `${path}.secondPieSize is only valid for ofPie charts.`);
277
+ assertIntegerInRange(opts.secondPieSize, `${path}.secondPieSize`, 5, 200);
278
+ }
279
+ if (opts.shape !== undefined) {
280
+ assertChartOptions(opts.type === "bar3D", `${path}.shape is only valid for bar3D charts.`);
281
+ }
282
+ if (opts.showMarker !== undefined) {
283
+ assertChartOptions(opts.type === "line" || opts.type === "radar", `${path}.showMarker is only valid for line and radar charts (line3D does not support markers).`);
284
+ }
285
+ if (opts.smooth !== undefined) {
286
+ assertChartOptions(opts.type === "line" || opts.type === "scatter", `${path}.smooth is only valid for line and scatter charts (line3D does not support smooth).`);
287
+ }
288
+ if (opts.hiLowLines !== undefined) {
289
+ assertChartOptions(opts.type === "line" || opts.type === "stock", `${path}.hiLowLines is only valid for line and stock charts (line3D does not support hiLowLines).`);
290
+ }
291
+ if (opts.upDownBars !== undefined) {
292
+ assertChartOptions(opts.type === "line" || opts.type === "stock", `${path}.upDownBars is only valid for line and stock charts (line3D does not support upDownBars).`);
293
+ }
294
+ if (opts.dropLines !== undefined) {
295
+ assertChartOptions(opts.type === "line" ||
296
+ opts.type === "line3D" ||
297
+ opts.type === "area" ||
298
+ opts.type === "area3D" ||
299
+ opts.type === "stock", `${path}.dropLines is only valid for line, area, and stock charts.`);
300
+ }
301
+ if (opts.serLines !== undefined) {
302
+ assertChartOptions(opts.type === "bar" || opts.type === "ofPie", `${path}.serLines is only valid for bar and ofPie charts.`);
303
+ }
304
+ validateAxisOptions(opts.categoryAxis, `${path}.categoryAxis`);
305
+ validateAxisOptions(opts.valueAxis, `${path}.valueAxis`);
306
+ }
307
+ function validateSharedChartOptions(opts, path) {
308
+ if (opts.style !== undefined) {
309
+ assertIntegerInRange(opts.style, `${path}.style`, 1, 48);
310
+ }
311
+ }
312
+ function validateSeriesOptions(chartType, opts, path, flags = {}) {
313
+ const allowMissingRefs = flags.allowMissingRefs === true;
314
+ assertChartOptions(!!opts && typeof opts === "object", `${path} must be an object.`);
315
+ if (allowMissingRefs) {
316
+ if (opts.values !== undefined) {
317
+ assertChartOptions(typeof opts.values === "string" && opts.values.length > 0, `${path}.values must be a non-empty formula string.`);
318
+ }
319
+ }
320
+ else {
321
+ assertChartOptions(typeof opts.values === "string" && opts.values.length > 0, `${path}.values is required and must be a non-empty formula string.`);
322
+ }
323
+ if (opts.trendline !== undefined) {
324
+ assertChartOptions(!NO_TRENDLINE_CHART_TYPES.has(chartType), `${path}.trendline is not valid for ${chartType} charts.`);
325
+ const trendlines = Array.isArray(opts.trendline) ? opts.trendline : [opts.trendline];
326
+ for (let i = 0; i < trendlines.length; i++) {
327
+ validateTrendlineOptions(trendlines[i], `${path}.trendline${trendlines.length > 1 ? `[${i}]` : ""}`);
328
+ }
329
+ }
330
+ if (opts.marker?.size !== undefined) {
331
+ assertIntegerInRange(opts.marker.size, `${path}.marker.size`, 2, 72);
332
+ }
333
+ if (opts.explosion !== undefined) {
334
+ assertChartOptions(PIE_FAMILY_CHART_TYPES.has(chartType), `${path}.explosion is only valid for pie, doughnut, and ofPie charts.`);
335
+ assertIntegerInRange(opts.explosion, `${path}.explosion`, 0, 400);
336
+ }
337
+ if (opts.bubble3D !== undefined) {
338
+ assertChartOptions(chartType === "bubble", `${path}.bubble3D is only valid for bubble charts.`);
339
+ }
340
+ if (opts.bubbleSize !== undefined) {
341
+ assertChartOptions(chartType === "bubble", `${path}.bubbleSize is only valid for bubble charts.`);
342
+ }
343
+ if (chartType === "bubble" && !allowMissingRefs) {
344
+ assertChartOptions(opts.xValues !== undefined, `${path}.xValues is required for bubble charts. Use a numeric range for x-values.`);
345
+ assertChartOptions(opts.bubbleSize !== undefined, `${path}.bubbleSize is required for bubble charts. Use a numeric range for bubble sizes.`);
346
+ }
347
+ if (chartType === "scatter" && !allowMissingRefs) {
348
+ assertChartOptions(opts.xValues !== undefined, `${path}.xValues is required for scatter charts. Use a numeric range for x-values.`);
349
+ }
350
+ if (opts.xValues !== undefined) {
351
+ assertChartOptions(chartType === "scatter" || chartType === "bubble", `${path}.xValues is only valid for scatter and bubble charts.`);
352
+ }
353
+ // Note on `categories` for scatter / bubble: the field has no direct
354
+ // home on `ScatterSeries` / `BubbleSeries`, which use `xVal` for the
355
+ // numeric X axis. `buildScatterSeries` / `buildBubbleSeries` silently
356
+ // ignore `opts.categories` at create time (the `xVal` slot is already
357
+ // populated from `opts.xValues`). On the patch path
358
+ // (`applyChartSeriesOptionsPatch`), `options.categories` is routed to
359
+ // `xVal` so callers can switch a scatter's X source to a text axis
360
+ // via `{ categories, xValueType: "text" }`. Accepting the field on
361
+ // creation preserves API symmetry (users can pass the same option
362
+ // bundle across chart types in test fixtures) at the cost of a silent
363
+ // drop for this specific combination.
364
+ if (opts.dataPoints) {
365
+ for (let i = 0; i < opts.dataPoints.length; i++) {
366
+ validateDataPointOptions(chartType, opts.dataPoints[i], `${path}.dataPoints[${i}]`);
367
+ }
368
+ }
369
+ if (opts.dataLabels) {
370
+ validateDataLabelsOptions(chartType, opts.dataLabels, `${path}.dataLabels`);
371
+ }
372
+ if (opts.errorBars) {
373
+ assertChartOptions(!PIE_FAMILY_CHART_TYPES.has(chartType), `${path}.errorBars is not valid for ${chartType} charts.`);
374
+ const errorBars = Array.isArray(opts.errorBars) ? opts.errorBars : [opts.errorBars];
375
+ // Non-scatter/bubble series only support a single error-bar configuration
376
+ // (`ErrorBars`, not an array). Fail fast rather than silently keep only
377
+ // `errorBars[0]` and discard the rest.
378
+ if (Array.isArray(opts.errorBars) &&
379
+ opts.errorBars.length > 1 &&
380
+ chartType !== "scatter" &&
381
+ chartType !== "bubble") {
382
+ assertChartOptions(false, `${path}.errorBars must be a single configuration for ${chartType} charts; arrays are only valid for scatter and bubble.`);
383
+ }
384
+ // Scatter / bubble: CT_ScatterSer / CT_BubbleSer declare
385
+ // `errBars` as `maxOccurs="2"` — one X, one Y. Allowing more
386
+ // than two (or two with the same `c:errDir`) is an OOXML schema
387
+ // violation and causes Excel to repair the chart on open,
388
+ // silently dropping the extras. Fail the author up-front so
389
+ // mistakes like passing an array of "every error-bar type" on a
390
+ // single series are caught rather than producing a file that
391
+ // prompts a repair dialog.
392
+ if ((chartType === "scatter" || chartType === "bubble") &&
393
+ Array.isArray(opts.errorBars) &&
394
+ opts.errorBars.length > 2) {
395
+ assertChartOptions(false, `${path}.errorBars allows at most 2 entries on ${chartType} charts (one for direction "x", one for "y"). Split additional configurations across separate series.`);
396
+ }
397
+ if ((chartType === "scatter" || chartType === "bubble") &&
398
+ Array.isArray(opts.errorBars) &&
399
+ opts.errorBars.length === 2) {
400
+ const d0 = opts.errorBars[0]?.direction;
401
+ const d1 = opts.errorBars[1]?.direction;
402
+ assertChartOptions(d0 !== undefined && d1 !== undefined && d0 !== d1, `${path}.errorBars must use distinct directions ("x" and "y") when providing two entries on ${chartType} charts.`);
403
+ }
404
+ for (let i = 0; i < errorBars.length; i++) {
405
+ validateErrorBarsOptions(errorBars[i], `${path}.errorBars${errorBars.length > 1 ? `[${i}]` : ""}`);
406
+ }
407
+ }
408
+ }
409
+ function validateSeriesPatchOptions(chartType, opts, path) {
410
+ // Patch path: unlike series-creation validation we accept a partial
411
+ // options bag with no `values` / `xValues` / `bubbleSize`. The
412
+ // `allowMissingRefs` flag short-circuits the "required" assertions so we
413
+ // don't need to inject placeholder strings (previous implementation used
414
+ // an `__excelts_placeholder__` sentinel that would have triggered false
415
+ // positives if `values` ever gained a content-level check).
416
+ validateSeriesOptions(chartType, opts, path, { allowMissingRefs: true });
417
+ }
418
+ function validateDataPointOptions(chartType, opts, path) {
419
+ assertIntegerInRange(opts.index, `${path}.index`, 0, Number.MAX_SAFE_INTEGER);
420
+ if (opts.explosion !== undefined) {
421
+ assertChartOptions(PIE_FAMILY_CHART_TYPES.has(chartType), `${path}.explosion is only valid for pie, doughnut, and ofPie charts.`);
422
+ assertIntegerInRange(opts.explosion, `${path}.explosion`, 0, 400);
423
+ }
424
+ if (opts.marker?.size !== undefined) {
425
+ assertIntegerInRange(opts.marker.size, `${path}.marker.size`, 2, 72);
426
+ }
427
+ }
428
+ function validateTrendlineOptions(opts, path) {
429
+ assertChartOptions(!!opts && typeof opts === "object", `${path} must be an object.`);
430
+ assertChartOptions(!!opts.type, `${path}.type is required.`);
431
+ if (opts.type === "poly") {
432
+ assertIntegerInRange(opts.order, `${path}.order`, 2, 6);
433
+ }
434
+ else {
435
+ assertChartOptions(opts.order === undefined, `${path}.order is only valid for polynomial trendlines.`);
436
+ }
437
+ if (opts.type === "movingAvg") {
438
+ assertIntegerInRange(opts.period, `${path}.period`, 2, Number.MAX_SAFE_INTEGER);
439
+ }
440
+ else {
441
+ // `period` is only meaningful for moving-average trendlines (Excel
442
+ // silently ignores it on other types, which quickly devolves into
443
+ // phantom config bugs). Match the stricter `order` handling above.
444
+ assertChartOptions(opts.period === undefined, `${path}.period is only valid for movingAvg trendlines.`);
445
+ }
446
+ if (opts.forward !== undefined) {
447
+ assertNumberInRange(opts.forward, `${path}.forward`, 0, Number.MAX_SAFE_INTEGER);
448
+ }
449
+ if (opts.backward !== undefined) {
450
+ assertNumberInRange(opts.backward, `${path}.backward`, 0, Number.MAX_SAFE_INTEGER);
451
+ }
452
+ }
453
+ function validateErrorBarsOptions(opts, path) {
454
+ assertChartOptions(!!opts && typeof opts === "object", `${path} must be an object.`);
455
+ assertChartOptions(!!opts.type, `${path}.type is required.`);
456
+ if (opts.type === "cust") {
457
+ assertChartOptions(!!opts.plus && !!opts.minus, `${path}.plus and ${path}.minus are required when type is "cust".`);
458
+ }
459
+ else {
460
+ assertChartOptions(opts.plus === undefined && opts.minus === undefined, `${path}.plus and ${path}.minus are only valid when type is "cust".`);
461
+ }
462
+ if (opts.value !== undefined) {
463
+ assertNumberInRange(opts.value, `${path}.value`, 0, Number.MAX_SAFE_INTEGER);
464
+ }
465
+ }
466
+ /**
467
+ * Ensure every `dLblPos` value (group-level and per-entry overrides)
468
+ * is one that Excel will accept for the chart type — see the
469
+ * rationale on {@link VALID_DLBL_POSITIONS_BY_TYPE}. Writing an
470
+ * invalid position causes Excel to flag the drawing as corrupted
471
+ * ("Repaired Records" / "Removed Part") even though the OOXML
472
+ * schema would technically accept it.
473
+ *
474
+ * Rejects at author time so the caller gets a pointer to the exact
475
+ * offending field rather than debugging a Removed Part dialog.
476
+ */
477
+ function validateDataLabelsOptions(chartType, opts, path) {
478
+ const allowed = VALID_DLBL_POSITIONS_BY_TYPE[chartType];
479
+ const describeAllowed = () => {
480
+ if (!allowed) {
481
+ return "(unknown chart type)";
482
+ }
483
+ if (allowed.size === 0) {
484
+ return `(${chartType} does not support c:dLblPos — Excel rejects any value)`;
485
+ }
486
+ return [...allowed].sort().join(", ");
487
+ };
488
+ if (opts.position !== undefined) {
489
+ assertChartOptions(!!allowed && allowed.has(opts.position), `${path}.position="${opts.position}" is not valid for ${chartType} charts. Allowed: ${describeAllowed()}.`);
490
+ }
491
+ if (opts.entries) {
492
+ for (let i = 0; i < opts.entries.length; i++) {
493
+ const entry = opts.entries[i];
494
+ if (entry?.position !== undefined) {
495
+ assertChartOptions(!!allowed && allowed.has(entry.position), `${path}.entries[${i}].position="${entry.position}" is not valid for ${chartType} charts. Allowed: ${describeAllowed()}.`);
496
+ }
497
+ }
498
+ }
499
+ }
500
+ function validateAxisOptions(opts, path) {
501
+ if (!opts) {
502
+ return;
503
+ }
504
+ if (opts.min !== undefined) {
505
+ assertFiniteNumber(opts.min, `${path}.min`);
506
+ }
507
+ if (opts.max !== undefined) {
508
+ assertFiniteNumber(opts.max, `${path}.max`);
509
+ }
510
+ if (opts.min !== undefined && opts.max !== undefined) {
511
+ assertChartOptions(opts.min < opts.max, `${path}.min must be less than ${path}.max.`);
512
+ }
513
+ if (opts.majorUnit !== undefined) {
514
+ assertNumberInRange(opts.majorUnit, `${path}.majorUnit`, 0, Number.MAX_SAFE_INTEGER);
515
+ assertChartOptions(opts.majorUnit > 0, `${path}.majorUnit must be greater than 0.`);
516
+ }
517
+ if (opts.minorUnit !== undefined) {
518
+ assertNumberInRange(opts.minorUnit, `${path}.minorUnit`, 0, Number.MAX_SAFE_INTEGER);
519
+ assertChartOptions(opts.minorUnit > 0, `${path}.minorUnit must be greater than 0.`);
520
+ }
521
+ if (opts.majorUnit !== undefined && opts.minorUnit !== undefined) {
522
+ assertChartOptions(opts.minorUnit <= opts.majorUnit, `${path}.minorUnit must be less than or equal to ${path}.majorUnit.`);
523
+ }
524
+ if (opts.logBase !== undefined) {
525
+ assertNumberInRange(opts.logBase, `${path}.logBase`, 2, 1000);
526
+ }
527
+ if (opts.textRotation !== undefined) {
528
+ assertIntegerInRange(opts.textRotation, `${path}.textRotation`, -90, 90);
529
+ }
530
+ if (opts.lblOffset !== undefined) {
531
+ assertIntegerInRange(opts.lblOffset, `${path}.lblOffset`, 0, 1000);
532
+ }
533
+ if (opts.tickLblSkip !== undefined) {
534
+ assertIntegerInRange(opts.tickLblSkip, `${path}.tickLblSkip`, 1, Number.MAX_SAFE_INTEGER);
535
+ }
536
+ if (opts.tickMarkSkip !== undefined) {
537
+ assertIntegerInRange(opts.tickMarkSkip, `${path}.tickMarkSkip`, 1, Number.MAX_SAFE_INTEGER);
538
+ }
539
+ if (opts.crossesAt !== undefined) {
540
+ assertFiniteNumber(opts.crossesAt, `${path}.crossesAt`);
541
+ }
542
+ if (opts.customUnit !== undefined) {
543
+ assertNumberInRange(opts.customUnit, `${path}.customUnit`, 0, Number.MAX_SAFE_INTEGER);
544
+ assertChartOptions(opts.customUnit > 0, `${path}.customUnit must be greater than 0.`);
545
+ }
546
+ }
547
+ /**
548
+ * Normalise a user-facing hex colour into a structured {@link ChartColor}.
549
+ * Accepts `"#RRGGBB"` / `"RRGGBB"` and the optional 8-digit
550
+ * `"RRGGBBAA"` form. The alpha byte, when present, is decoded into
551
+ * `color.alpha` on the OOXML 0–100000 scale (0 = fully transparent,
552
+ * 100000 = fully opaque) rather than discarded. Throws
553
+ * `ChartOptionsError` when the input is not a valid hex triplet so the
554
+ * caller sees the mistake at the assignment site rather than via a
555
+ * downstream XML parser rejection.
556
+ */
557
+ function hexToColor(hex) {
558
+ const cleaned = hex.replace(/^#/, "").toUpperCase();
559
+ if (!/^[0-9A-F]{6}([0-9A-F]{2})?$/.test(cleaned)) {
560
+ throw new errors_1.ChartOptionsError(`Invalid hex colour: ${JSON.stringify(hex)}. Expected 6-digit (or 8-digit with alpha) hex like "#FF0000".`);
561
+ }
562
+ const color = { srgb: cleaned.slice(0, 6) };
563
+ if (cleaned.length === 8) {
564
+ // 8-digit form: trailing 2 bytes encode alpha on the 0–255 scale.
565
+ // `ChartColor.alpha` stores OOXML's 0–100000 integer; convert and
566
+ // round so the wire value is an integer, matching Excel's output.
567
+ const alphaByte = parseInt(cleaned.slice(6, 8), 16);
568
+ color.alpha = Math.round((alphaByte / 255) * 100000);
569
+ }
570
+ return color;
571
+ }
572
+ /**
573
+ * Escape XML text content while stripping characters forbidden by
574
+ * XML 1.0. Without the strip step, a chart built from user input
575
+ * containing `\b` / `\f` / other C0 control characters would produce
576
+ * an XML-invalid `<c:v>` or `<c:f>` payload that strict readers
577
+ * refuse to parse. Preserved: `\t`, `\n`, `\r` (the only C0 chars
578
+ * XML 1.0 allows in content).
579
+ */
580
+ function buildPivotSourceXml(source) {
581
+ const name = typeof source === "string" ? source : source.name;
582
+ const fmtId = typeof source === "string" ? 0 : (source.fmtId ?? 0);
583
+ if (!name) {
584
+ throw new errors_1.ChartOptionsError("Pivot chart source name is required.");
585
+ }
586
+ if (!Number.isInteger(fmtId) || fmtId < 0) {
587
+ throw new errors_1.ChartOptionsError("Pivot chart source fmtId must be a non-negative integer.");
588
+ }
589
+ // Pivot chart options used to be embedded inside `<c:pivotSource>` under a
590
+ // private `xmlns:excelts` namespace; Excel never recognised that and the
591
+ // parser never read it back. Options are now routed into
592
+ // `ChartModel.pivotOptions` (see {@link ChartModel.pivotOptions}) and
593
+ // serialised as MS standard `c14:pivotOptions` inside chartSpace's extLst.
594
+ return `<c:pivotSource><c:name>${(0, chart_utils_1.escapeXml)(name)}</c:name><c:fmtId val="${fmtId}"/></c:pivotSource>`;
595
+ }
596
+ /**
597
+ * Convert a simplified AddShapeFillOptions (or a pre-built ShapeProperties)
598
+ * into a structured ShapeProperties object. Returns undefined when input is
599
+ * undefined.
600
+ */
601
+ /**
602
+ * Normalise a user-facing shape-fill option bundle (hex-string fill,
603
+ * hex-string border, borderWidth in points, gradient, pattern, …) into a
604
+ * structured {@link ShapeProperties}. Passes through already-structured
605
+ * shapes unchanged so callers can mix the two forms freely.
606
+ *
607
+ * Exported so `chart-ex-builder` can reuse the exact same normalisation
608
+ * for ChartEx `spPr` options — previously ChartEx only accepted the
609
+ * fully-structured form, which was an API asymmetry.
610
+ */
611
+ function toShapeProperties(input) {
612
+ if (!input) {
613
+ return undefined;
614
+ }
615
+ // If it already looks like a ShapeProperties (has fill/line/effectList/_rawXml
616
+ // but no hex-string "fill" field), shallow-clone rather than return
617
+ // the caller's reference. Every downstream consumer treats the
618
+ // returned object as owned (e.g. `applyChartSeriesOptionsPatch`
619
+ // deletes `_rawXml` on it; combo-group builders overwrite inner
620
+ // fields), and leaking the caller's object into the model would
621
+ // mean subsequent patches on one chart silently mutate the
622
+ // caller's options blob — and if that blob was reused across
623
+ // multiple `addChart(...)` calls, every later chart would see the
624
+ // stripped / mutated state. The clone is shallow because `fill` /
625
+ // `line` sub-trees are themselves replaced wholesale by the
626
+ // downstream patchers when they change; deeper aliasing is not
627
+ // currently a hazard.
628
+ if (isShapeProperties(input)) {
629
+ return { ...input };
630
+ }
631
+ const opts = input;
632
+ const spPr = {};
633
+ if (opts.noFill) {
634
+ spPr.fill = { noFill: true };
635
+ }
636
+ else if (opts.fill) {
637
+ spPr.fill = { solid: hexToColor(opts.fill) };
638
+ }
639
+ else if (opts.gradient) {
640
+ spPr.fill = { gradient: opts.gradient };
641
+ }
642
+ else if (opts.pattern) {
643
+ spPr.fill = { pattern: opts.pattern };
644
+ }
645
+ if (opts.border || opts.borderWidth !== undefined) {
646
+ spPr.line = {};
647
+ if (opts.border) {
648
+ spPr.line.color = hexToColor(opts.border);
649
+ }
650
+ if (opts.borderWidth !== undefined) {
651
+ // OOXML `a:ln/@w` is `ST_LineWidth` = `xsd:int`. A fractional
652
+ // `borderWidth` (e.g. 0.825pt, or any point value that doesn't
653
+ // round-trip through `n / 12700` cleanly) would interpolate as
654
+ // `"10477.5"`, which strict readers reject. Rounding matches the
655
+ // sibling builders (`buildSeriesSpPr`, etc.).
656
+ spPr.line.width = Math.round(opts.borderWidth * EMU_PER_POINT);
657
+ }
658
+ else if (opts.border) {
659
+ // Mirror chart-ex-builder: when the caller sets a border colour
660
+ // without an explicit width, fall back to 9525 EMU (0.75pt).
661
+ // Without this DrawingML readers treat `<a:ln>` as hairline,
662
+ // which typically disappears on screen.
663
+ spPr.line.width = 9525;
664
+ }
665
+ }
666
+ return Object.keys(spPr).length > 0 ? spPr : undefined;
667
+ }
668
+ function isShapeProperties(v) {
669
+ if (!v || typeof v !== "object") {
670
+ return false;
671
+ }
672
+ const o = v;
673
+ // ShapeProperties has structured `fill` as an object or `line` or `_rawXml`,
674
+ // whereas AddShapeFillOptions.fill is a hex string.
675
+ if ("_rawXml" in o) {
676
+ return true;
677
+ }
678
+ if ("fill" in o && typeof o.fill === "object") {
679
+ return true;
680
+ }
681
+ if ("line" in o && typeof o.line === "object" && !Array.isArray(o.line)) {
682
+ // AddShapeFillOptions does not have `line`; ShapeProperties does.
683
+ return true;
684
+ }
685
+ if ("effectList" in o) {
686
+ return true;
687
+ }
688
+ // Check the remaining `ShapeProperties` fields that distinguish it
689
+ // from `AddShapeFillOptions`. `AddShapeFillOptions` has only
690
+ // `fill` (as hex-string) and `line` (as hex-string); anything else
691
+ // is a `ShapeProperties`-only field. Previously the sniffer missed
692
+ // the 3D/geometry fields entirely — a user passing
693
+ // `{ sp3d: {...} }` or `{ transform: {...} }` alone was
694
+ // misclassified and the fields silently dropped.
695
+ if ("scene3d" in o || "sp3d" in o) {
696
+ return true;
697
+ }
698
+ if ("transform" in o || "presetGeometry" in o || "customGeometry" in o) {
699
+ return true;
700
+ }
701
+ return false;
702
+ }
703
+ function makeSolidFill(hex) {
704
+ return { fill: { solid: hexToColor(hex) } };
705
+ }
706
+ function makeSeriesTx(name) {
707
+ if (name === undefined) {
708
+ return undefined;
709
+ }
710
+ if (typeof name === "string") {
711
+ return { value: name };
712
+ }
713
+ return { strRef: makeStrRef(name.formula) };
714
+ }
715
+ // ---------------------------------------------------------------------------
716
+ // Series-level option builders
717
+ // ---------------------------------------------------------------------------
718
+ function buildSeriesSpPr(opts) {
719
+ // Explicit `spPr` on the options object takes precedence over the sugared form.
720
+ const custom = toShapeProperties(opts.spPr);
721
+ if (custom) {
722
+ return custom;
723
+ }
724
+ let spPr;
725
+ if (opts.fill) {
726
+ spPr = makeSolidFill(opts.fill);
727
+ }
728
+ if (opts.line || opts.lineWidth !== undefined || opts.lineDash) {
729
+ const line = {};
730
+ if (opts.line) {
731
+ line.color = hexToColor(opts.line);
732
+ }
733
+ if (opts.lineWidth !== undefined) {
734
+ line.width = Math.round(opts.lineWidth * EMU_PER_POINT); // pt → EMU
735
+ }
736
+ else if (opts.line) {
737
+ // Mirror chart-ex-builder: when the caller sets a line colour
738
+ // without an explicit width, fall back to 9525 EMU (0.75pt —
739
+ // Excel's default for chart series borders). Without this
740
+ // DrawingML readers treat `<a:ln>` as hairline, which disappears
741
+ // at typical screen DPI and is never what the user means by
742
+ // `line: "#FF0000"`.
743
+ line.width = 9525;
744
+ }
745
+ if (opts.lineDash) {
746
+ line.dash = opts.lineDash;
747
+ }
748
+ spPr = { ...spPr, line };
749
+ }
750
+ return spPr;
751
+ }
752
+ function buildMarkerFromOpts(opts) {
753
+ const m = {};
754
+ if (opts.symbol) {
755
+ m.symbol = opts.symbol;
756
+ }
757
+ if (opts.size !== undefined) {
758
+ m.size = opts.size;
759
+ }
760
+ if (opts.fill || opts.border) {
761
+ const mSpPr = {};
762
+ if (opts.fill) {
763
+ mSpPr.fill = { solid: hexToColor(opts.fill) };
764
+ }
765
+ if (opts.border) {
766
+ // Default to 9525 EMU (0.75pt) — without an explicit width
767
+ // DrawingML treats the outline as hairline and the marker ring
768
+ // typically vanishes at on-screen DPI. Matches the other
769
+ // builder paths that default to the same width.
770
+ mSpPr.line = { color: hexToColor(opts.border), width: 9525 };
771
+ }
772
+ m.spPr = mSpPr;
773
+ }
774
+ return m;
775
+ }
776
+ function buildDataLabelsFromOpts(opts) {
777
+ const dl = {};
778
+ if (opts.showLegendKey !== undefined) {
779
+ dl.showLegendKey = opts.showLegendKey;
780
+ }
781
+ if (opts.showVal !== undefined) {
782
+ dl.showVal = opts.showVal;
783
+ }
784
+ if (opts.showCatName !== undefined) {
785
+ dl.showCatName = opts.showCatName;
786
+ }
787
+ if (opts.showSerName !== undefined) {
788
+ dl.showSerName = opts.showSerName;
789
+ }
790
+ if (opts.showPercent !== undefined) {
791
+ dl.showPercent = opts.showPercent;
792
+ }
793
+ if (opts.showBubbleSize !== undefined) {
794
+ dl.showBubbleSize = opts.showBubbleSize;
795
+ }
796
+ if (opts.showLeaderLines !== undefined) {
797
+ dl.showLeaderLines = opts.showLeaderLines;
798
+ }
799
+ if (opts.position) {
800
+ dl.position = opts.position;
801
+ }
802
+ if (opts.separator !== undefined) {
803
+ dl.separator = opts.separator;
804
+ }
805
+ if (opts.numFmt !== undefined) {
806
+ dl.numFmt = { formatCode: opts.numFmt, sourceLinked: opts.numFmtLinked };
807
+ }
808
+ else if (opts.numFmtLinked !== undefined) {
809
+ // Allow `numFmtLinked` without an explicit `numFmt` to re-link the
810
+ // data-label number format to the source cell. OOXML's `CT_NumFmt`
811
+ // requires `formatCode`, so default it to `General` (the Excel
812
+ // default when `sourceLinked="1"` is emitted without an author-
813
+ // specified format). Previously this branch silently dropped the
814
+ // flag: callers had no way to opt into source-linking on data
815
+ // labels without also supplying a redundant format code.
816
+ dl.numFmt = { formatCode: "General", sourceLinked: opts.numFmtLinked };
817
+ }
818
+ const spPr = toShapeProperties(opts.spPr);
819
+ if (spPr) {
820
+ dl.spPr = spPr;
821
+ }
822
+ if (opts.txPr) {
823
+ dl.txPr = opts.txPr;
824
+ }
825
+ if (opts.entries && opts.entries.length > 0) {
826
+ dl.entries = opts.entries.map(e => buildDataLabelEntryFromOpts(e));
827
+ }
828
+ if (opts.valueFromCells !== undefined) {
829
+ // "Value From Cells" (Excel 2013+). Accept either a bare formula or
830
+ // the full {formula, cache} shape. The cache is filled in later by
831
+ // `fillChartCaches` when the worksheet is available.
832
+ dl.dataLabelsRange =
833
+ typeof opts.valueFromCells === "string"
834
+ ? { formula: opts.valueFromCells }
835
+ : opts.valueFromCells;
836
+ }
837
+ return dl;
838
+ }
839
+ function buildDataLabelEntryFromOpts(opts) {
840
+ const entry = { index: opts.index };
841
+ if (opts.delete) {
842
+ entry.delete = true;
843
+ // OOXML: a deleted label carries only its index; skip other fields.
844
+ return entry;
845
+ }
846
+ if (opts.text !== undefined) {
847
+ if (typeof opts.text === "string") {
848
+ entry.text = {
849
+ paragraphs: [{ runs: [{ text: opts.text }] }]
850
+ };
851
+ }
852
+ else {
853
+ entry.text = opts.text;
854
+ }
855
+ }
856
+ if (opts.position) {
857
+ entry.position = opts.position;
858
+ }
859
+ if (opts.numFmt) {
860
+ entry.numFmt = { formatCode: opts.numFmt, sourceLinked: opts.numFmtLinked };
861
+ }
862
+ else if (opts.numFmtLinked !== undefined) {
863
+ // Allow standalone `numFmtLinked` — see `buildDataLabelsFromOpts`
864
+ // for the matching semantics.
865
+ entry.numFmt = { formatCode: "General", sourceLinked: opts.numFmtLinked };
866
+ }
867
+ const spPr = toShapeProperties(opts.spPr);
868
+ if (spPr) {
869
+ entry.spPr = spPr;
870
+ }
871
+ if (opts.txPr) {
872
+ entry.txPr = opts.txPr;
873
+ }
874
+ if (opts.showVal !== undefined) {
875
+ entry.showVal = opts.showVal;
876
+ }
877
+ if (opts.showCatName !== undefined) {
878
+ entry.showCatName = opts.showCatName;
879
+ }
880
+ if (opts.showSerName !== undefined) {
881
+ entry.showSerName = opts.showSerName;
882
+ }
883
+ if (opts.showPercent !== undefined) {
884
+ entry.showPercent = opts.showPercent;
885
+ }
886
+ if (opts.showBubbleSize !== undefined) {
887
+ entry.showBubbleSize = opts.showBubbleSize;
888
+ }
889
+ if (opts.showLegendKey !== undefined) {
890
+ entry.showLegendKey = opts.showLegendKey;
891
+ }
892
+ return entry;
893
+ }
894
+ function buildTrendlineFromOpts(opts) {
895
+ const t = { type: opts.type };
896
+ if (opts.name !== undefined) {
897
+ t.name = opts.name;
898
+ }
899
+ if (opts.order !== undefined) {
900
+ t.order = opts.order;
901
+ }
902
+ if (opts.period !== undefined) {
903
+ t.period = opts.period;
904
+ }
905
+ if (opts.forward !== undefined) {
906
+ t.forward = opts.forward;
907
+ }
908
+ if (opts.backward !== undefined) {
909
+ t.backward = opts.backward;
910
+ }
911
+ if (opts.intercept !== undefined) {
912
+ t.intercept = opts.intercept;
913
+ }
914
+ if (opts.displayRSqr !== undefined) {
915
+ t.displayRSqr = opts.displayRSqr;
916
+ }
917
+ if (opts.displayEq !== undefined) {
918
+ t.displayEq = opts.displayEq;
919
+ }
920
+ if (opts.line || opts.lineWidth !== undefined || opts.lineDash) {
921
+ const line = {};
922
+ if (opts.line) {
923
+ line.color = hexToColor(opts.line);
924
+ }
925
+ if (opts.lineWidth !== undefined) {
926
+ line.width = Math.round(opts.lineWidth * EMU_PER_POINT);
927
+ }
928
+ if (opts.lineDash) {
929
+ line.dash = opts.lineDash;
930
+ }
931
+ t.spPr = { line };
932
+ }
933
+ if (opts.label) {
934
+ t.trendlineLbl = buildTrendlineLabelFromOpts(opts.label);
935
+ }
936
+ return t;
937
+ }
938
+ function buildTrendlineLabelFromOpts(opts) {
939
+ const lbl = {};
940
+ if (opts.text !== undefined) {
941
+ lbl.text = opts.text;
942
+ }
943
+ if (opts.numFmt !== undefined) {
944
+ lbl.numFmt = { formatCode: opts.numFmt, sourceLinked: opts.numFmtLinked };
945
+ }
946
+ else if (opts.numFmtLinked !== undefined) {
947
+ // Allow standalone `numFmtLinked` — see `buildDataLabelsFromOpts`
948
+ // for the matching semantics.
949
+ lbl.numFmt = { formatCode: "General", sourceLinked: opts.numFmtLinked };
950
+ }
951
+ if (opts.layout) {
952
+ lbl.layout = opts.layout;
953
+ }
954
+ const spPr = toShapeProperties(opts.spPr);
955
+ if (spPr) {
956
+ lbl.spPr = spPr;
957
+ }
958
+ if (opts.txPr) {
959
+ lbl.txPr = opts.txPr;
960
+ }
961
+ return lbl;
962
+ }
963
+ function buildErrorBarsFromOpts(opts) {
964
+ const eb = {
965
+ barDir: opts.barDir ?? "both",
966
+ errValType: opts.type
967
+ };
968
+ if (opts.direction) {
969
+ eb.errDir = opts.direction;
970
+ }
971
+ if (opts.value !== undefined) {
972
+ eb.val = opts.value;
973
+ }
974
+ if (opts.noEndCap !== undefined) {
975
+ eb.noEndCap = opts.noEndCap;
976
+ }
977
+ if (opts.plus) {
978
+ eb.plus = makeNumData(opts.plus);
979
+ }
980
+ if (opts.minus) {
981
+ eb.minus = makeNumData(opts.minus);
982
+ }
983
+ // Line / shape styling
984
+ const customSpPr = toShapeProperties(opts.spPr);
985
+ if (customSpPr) {
986
+ eb.spPr = customSpPr;
987
+ }
988
+ else if (opts.line || opts.lineWidth !== undefined || opts.lineDash) {
989
+ const line = {};
990
+ if (opts.line) {
991
+ line.color = hexToColor(opts.line);
992
+ }
993
+ if (opts.lineWidth !== undefined) {
994
+ line.width = Math.round(opts.lineWidth * EMU_PER_POINT);
995
+ }
996
+ if (opts.lineDash) {
997
+ line.dash = opts.lineDash;
998
+ }
999
+ eb.spPr = { line };
1000
+ }
1001
+ return eb;
1002
+ }
1003
+ function buildDataPointFromOpts(opts) {
1004
+ const dp = { index: opts.index };
1005
+ if (opts.fill || opts.border) {
1006
+ const spPr = {};
1007
+ if (opts.fill) {
1008
+ spPr.fill = { solid: hexToColor(opts.fill) };
1009
+ }
1010
+ if (opts.border) {
1011
+ spPr.line = { color: hexToColor(opts.border), width: 9525 };
1012
+ }
1013
+ dp.spPr = spPr;
1014
+ }
1015
+ if (opts.explosion !== undefined) {
1016
+ dp.explosion = opts.explosion;
1017
+ }
1018
+ if (opts.bubble3D !== undefined) {
1019
+ dp.bubble3D = opts.bubble3D;
1020
+ }
1021
+ if (opts.marker) {
1022
+ dp.marker = buildMarkerFromOpts(opts.marker);
1023
+ }
1024
+ if (opts.invertIfNegative !== undefined) {
1025
+ dp.invertIfNegative = opts.invertIfNegative;
1026
+ }
1027
+ return dp;
1028
+ }
1029
+ function applySeriesOptions(s, opts, context = {}) {
1030
+ s.spPr = buildSeriesSpPr(opts);
1031
+ if (opts.marker) {
1032
+ s.marker = buildMarkerFromOpts(opts.marker);
1033
+ }
1034
+ if (opts.dataLabels) {
1035
+ s.dataLabels = buildDataLabelsFromOpts(opts.dataLabels);
1036
+ }
1037
+ if (opts.trendline) {
1038
+ const trendlineOpts = Array.isArray(opts.trendline) ? opts.trendline : [opts.trendline];
1039
+ s.trendlines = trendlineOpts.map(buildTrendlineFromOpts);
1040
+ }
1041
+ if (opts.dataPoints) {
1042
+ s.dataPoints = opts.dataPoints.map(buildDataPointFromOpts);
1043
+ }
1044
+ // NOTE: classic chart series have no `txPr` slot in OOXML, so the
1045
+ // field was removed from `AddChartSeriesOptions`. Trendline labels,
1046
+ // axis labels, data labels, and titles all have their own `txPr`
1047
+ // entry points — route run-level text styling through those.
1048
+ if (opts.pictureFill) {
1049
+ applyPictureFillToSeries(s, opts.pictureFill, {
1050
+ supportsPictureOptions: context.supportsPictureOptions
1051
+ });
1052
+ }
1053
+ }
1054
+ /**
1055
+ * Split an `AddShapeFillOptions`-style `pictureFill` option bundle into the
1056
+ * two OOXML artefacts that render the feature:
1057
+ * - `c:pictureOptions` (stretch/stack/apply-to-*) — stored on
1058
+ * `series.pictureOptions`
1059
+ * - `a:blipFill` (the actual image rel) — stored on
1060
+ * `series.spPr.fill.blip`
1061
+ *
1062
+ * Both are updated in a single place so the new-series path
1063
+ * ({@link applySeriesOptions}) and the patch path
1064
+ * ({@link applyChartSeriesOptionsPatch}) cannot diverge.
1065
+ */
1066
+ function applyPictureFillToSeries(series, pictureFill, options = {}) {
1067
+ // `c:pictureOptions` (stretch/stack/applyTo*/scale) is only declared
1068
+ // on `CT_BarSer` per ECMA-376 §21.2.2.162. Non-bar callers get the
1069
+ // `<a:blipFill>` on their `spPr.fill.blip` (which is legal on every
1070
+ // shape), but the caller-supplied `applyToFront` / `fillMode` /
1071
+ // `scale` hints are silently dropped — we would otherwise emit a
1072
+ // `<c:pictureOptions>` that schema validators reject. Surface the
1073
+ // mismatch if the caller set bar-only fields on a non-bar series
1074
+ // rather than letting the data quietly disappear.
1075
+ const barOnlyFieldsUsed = pictureFill.applyToFront !== undefined ||
1076
+ pictureFill.applyToSides !== undefined ||
1077
+ pictureFill.applyToEnd !== undefined ||
1078
+ pictureFill.scale !== undefined;
1079
+ if (options.supportsPictureOptions) {
1080
+ series.pictureOptions = {
1081
+ applyToFront: pictureFill.applyToFront,
1082
+ applyToSides: pictureFill.applyToSides,
1083
+ applyToEnd: pictureFill.applyToEnd,
1084
+ pictureFormat: pictureFill.fillMode,
1085
+ pictureStackUnit: pictureFill.scale
1086
+ };
1087
+ }
1088
+ else if (barOnlyFieldsUsed) {
1089
+ throw new errors_1.ChartOptionsError("pictureFill.applyToFront / applyToSides / applyToEnd / scale are only valid for bar / bar3D series (mapped to c:pictureOptions in CT_BarSer). Use the plain `fill` / `spPr.fill.blip` form for other series types, or omit the bar-only hints.");
1090
+ }
1091
+ if (pictureFill.image !== undefined || pictureFill.relationshipId) {
1092
+ // Parsed-from-XML series carry their `spPr` as a dual
1093
+ // representation: the structured `fill` / `line` slots are
1094
+ // populated AND `_rawXml` holds the original DrawingML bytes.
1095
+ // The writer short-circuits to `_rawXml` (see
1096
+ // `chart-space-xform._renderSpPr`) whenever it's present, which
1097
+ // means a downstream mutation like this one — which sets
1098
+ // `series.spPr.fill.blip` but can't touch the raw bytes — gets
1099
+ // silently overwritten at save time. The chart rel points at the
1100
+ // new image, the chart XML still carries the old fill. Strip
1101
+ // `_rawXml` here so the structured patch wins and the writer
1102
+ // emits the fresh `<a:blipFill>`.
1103
+ //
1104
+ // We also need to repopulate enough of the structured model that
1105
+ // the dropped `_rawXml` doesn't take authored line / geometry /
1106
+ // effect properties down with it. `parseSpPr` is already called
1107
+ // at load time and stores the structured fields alongside the
1108
+ // raw bytes, so the structured slots still carry whatever the
1109
+ // loaded file had. Nothing extra needed on the clone side.
1110
+ if (series.spPr && typeof series.spPr === "object") {
1111
+ delete series.spPr._rawXml;
1112
+ }
1113
+ series.spPr = series.spPr ?? {};
1114
+ series.spPr.fill = series.spPr.fill ?? {};
1115
+ // Also clear a raw representation that might live on the
1116
+ // existing `fill` object (rare — reserved for `<a:solidFill>`
1117
+ // / `<a:gradFill>` raw captures some parsers produce). The
1118
+ // writer emits a single `<a:*Fill>` child per `<a:spPr>`, so
1119
+ // the new blip must be the only fill in play.
1120
+ delete series.spPr.fill.solid;
1121
+ delete series.spPr.fill.gradient;
1122
+ delete series.spPr.fill.pattern;
1123
+ delete series.spPr.fill.noFill;
1124
+ series.spPr.fill.blip = {
1125
+ fillMode: pictureFill.fillMode === "stack" || pictureFill.fillMode === "stackScale"
1126
+ ? "tile"
1127
+ : "stretch",
1128
+ ...(pictureFill.relationshipId ? { relationshipId: pictureFill.relationshipId } : {}),
1129
+ ...(pictureFill.image !== undefined ? { _pendingImage: pictureFill.image } : {})
1130
+ };
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Populates common category-value series fields (tx, cat, val) shared by
1135
+ * bar, line, pie, area, radar, and surface series builders.
1136
+ */
1137
+ function populateCatValBase(s, opts) {
1138
+ s.tx = makeSeriesTx(opts.name);
1139
+ if (opts.categories) {
1140
+ s.cat = makeAxisData(opts.categories);
1141
+ }
1142
+ if (opts.values) {
1143
+ s.val = makeNumData(opts.values);
1144
+ }
1145
+ }
1146
+ /**
1147
+ * Build a single error-bars entry from options, normalising the
1148
+ * array-vs-single input shape used by non-scatter/bubble series.
1149
+ */
1150
+ function buildSingleErrorBars(opts) {
1151
+ if (!opts) {
1152
+ return undefined;
1153
+ }
1154
+ if (Array.isArray(opts)) {
1155
+ return opts.length > 0 ? buildErrorBarsFromOpts(opts[0]) : undefined;
1156
+ }
1157
+ return buildErrorBarsFromOpts(opts);
1158
+ }
1159
+ function buildBarSeries(opts, idx) {
1160
+ const s = { index: idx, order: idx };
1161
+ populateCatValBase(s, opts);
1162
+ applySeriesOptions(s, opts, { supportsPictureOptions: true });
1163
+ if (opts.invertIfNegative !== undefined) {
1164
+ s.invertIfNegative = opts.invertIfNegative;
1165
+ }
1166
+ s.errorBars = buildSingleErrorBars(opts.errorBars);
1167
+ return s;
1168
+ }
1169
+ function buildLineSeries(opts, idx) {
1170
+ const s = { index: idx, order: idx };
1171
+ populateCatValBase(s, opts);
1172
+ applySeriesOptions(s, opts);
1173
+ if (opts.smooth !== undefined) {
1174
+ s.smooth = opts.smooth;
1175
+ }
1176
+ s.errorBars = buildSingleErrorBars(opts.errorBars);
1177
+ return s;
1178
+ }
1179
+ function buildPieSeries(opts, idx) {
1180
+ const s = { index: idx, order: idx };
1181
+ populateCatValBase(s, opts);
1182
+ applySeriesOptions(s, opts);
1183
+ if (opts.explosion !== undefined) {
1184
+ s.explosion = opts.explosion;
1185
+ }
1186
+ return s;
1187
+ }
1188
+ function buildAreaSeries(opts, idx) {
1189
+ const s = { index: idx, order: idx };
1190
+ populateCatValBase(s, opts);
1191
+ applySeriesOptions(s, opts);
1192
+ s.errorBars = buildSingleErrorBars(opts.errorBars);
1193
+ return s;
1194
+ }
1195
+ function buildScatterSeries(opts, idx) {
1196
+ const s = { index: idx, order: idx };
1197
+ s.tx = makeSeriesTx(opts.name);
1198
+ if (opts.xValues) {
1199
+ s.xVal = makeXAxisData(opts.xValues, opts.xValueType);
1200
+ }
1201
+ if (opts.values) {
1202
+ s.yVal = makeNumData(opts.values);
1203
+ }
1204
+ applySeriesOptions(s, opts);
1205
+ if (opts.smooth !== undefined) {
1206
+ s.smooth = opts.smooth;
1207
+ }
1208
+ if (opts.errorBars) {
1209
+ const ebOpts = Array.isArray(opts.errorBars) ? opts.errorBars : [opts.errorBars];
1210
+ s.errorBars = ebOpts.map(buildErrorBarsFromOpts);
1211
+ }
1212
+ return s;
1213
+ }
1214
+ function buildBubbleSeries(opts, idx) {
1215
+ const s = { index: idx, order: idx };
1216
+ s.tx = makeSeriesTx(opts.name);
1217
+ if (opts.xValues) {
1218
+ s.xVal = makeXAxisData(opts.xValues, opts.xValueType);
1219
+ }
1220
+ if (opts.values) {
1221
+ s.yVal = makeNumData(opts.values);
1222
+ }
1223
+ if (opts.bubbleSize) {
1224
+ s.bubbleSize = makeNumData(opts.bubbleSize);
1225
+ }
1226
+ applySeriesOptions(s, opts);
1227
+ if (opts.invertIfNegative !== undefined) {
1228
+ s.invertIfNegative = opts.invertIfNegative;
1229
+ }
1230
+ if (opts.bubble3D !== undefined) {
1231
+ s.bubble3D = opts.bubble3D;
1232
+ }
1233
+ if (opts.errorBars) {
1234
+ const ebOpts = Array.isArray(opts.errorBars) ? opts.errorBars : [opts.errorBars];
1235
+ s.errorBars = ebOpts.map(buildErrorBarsFromOpts);
1236
+ }
1237
+ return s;
1238
+ }
1239
+ function buildRadarSeries(opts, idx) {
1240
+ const s = { index: idx, order: idx };
1241
+ populateCatValBase(s, opts);
1242
+ applySeriesOptions(s, opts);
1243
+ return s;
1244
+ }
1245
+ function buildSurfaceSeries(opts, idx) {
1246
+ const s = { index: idx, order: idx };
1247
+ populateCatValBase(s, opts);
1248
+ applySeriesOptions(s, opts);
1249
+ return s;
1250
+ }
1251
+ function buildChartSeriesForType(chartType, options, index) {
1252
+ validateSeriesOptions(chartType, options, "series");
1253
+ if (chartType === "bar" || chartType === "bar3D") {
1254
+ return buildBarSeries(options, index);
1255
+ }
1256
+ if (chartType === "line" || chartType === "line3D" || chartType === "stock") {
1257
+ return buildLineSeries(options, index);
1258
+ }
1259
+ if (chartType === "pie" ||
1260
+ chartType === "pie3D" ||
1261
+ chartType === "doughnut" ||
1262
+ chartType === "ofPie") {
1263
+ return buildPieSeries(options, index);
1264
+ }
1265
+ if (chartType === "area" || chartType === "area3D") {
1266
+ return buildAreaSeries(options, index);
1267
+ }
1268
+ if (chartType === "scatter") {
1269
+ return buildScatterSeries(options, index);
1270
+ }
1271
+ if (chartType === "bubble") {
1272
+ return buildBubbleSeries(options, index);
1273
+ }
1274
+ if (chartType === "radar") {
1275
+ return buildRadarSeries(options, index);
1276
+ }
1277
+ if (chartType === "surface" || chartType === "surface3D") {
1278
+ return buildSurfaceSeries(options, index);
1279
+ }
1280
+ // Exhaustiveness check: every value of `AddChartOptions["type"]` must be
1281
+ // handled above. Falling back to `buildBarSeries` silently would mis-map
1282
+ // any new chart type introduced in the future.
1283
+ const _exhaustive = chartType;
1284
+ throw new errors_1.ChartOptionsError(`Unsupported chart type: ${String(_exhaustive)}.`);
1285
+ }
1286
+ function applyChartSeriesOptionsPatch(series, options, chartType) {
1287
+ if (chartType) {
1288
+ validateSeriesPatchOptions(chartType, options, "series");
1289
+ }
1290
+ if (options.name !== undefined) {
1291
+ series.tx = makeSeriesTx(options.name);
1292
+ }
1293
+ if (options.categories !== undefined) {
1294
+ const target = series;
1295
+ // Scatter / bubble series have no category axis — their X axis is
1296
+ // `xVal`. When a patch targets such a series (identified by an
1297
+ // already-populated `xVal` and no `cat`), route `categories`
1298
+ // through `makeXAxisData` so `options.xValueType: "text"` flips
1299
+ // the series from a numeric `xVal` to a labelled one. For every
1300
+ // other series type the patch goes to the structural `cat` slot.
1301
+ if (target.xVal && !target.cat) {
1302
+ target.xVal = makeXAxisData(options.categories, options.xValueType);
1303
+ }
1304
+ else {
1305
+ target.cat = makeAxisData(options.categories);
1306
+ }
1307
+ }
1308
+ if (options.xValues !== undefined) {
1309
+ series.xVal = makeXAxisData(options.xValues, options.xValueType);
1310
+ }
1311
+ if (options.values !== undefined) {
1312
+ const target = series;
1313
+ if (target.yVal && !target.val) {
1314
+ target.yVal = makeNumData(options.values);
1315
+ }
1316
+ else {
1317
+ target.val = makeNumData(options.values);
1318
+ }
1319
+ }
1320
+ if (options.bubbleSize !== undefined) {
1321
+ series.bubbleSize = makeNumData(options.bubbleSize);
1322
+ }
1323
+ if (hasSeriesShapePatch(options)) {
1324
+ const patchShape = buildSeriesSpPr(options);
1325
+ if (options.spPr !== undefined) {
1326
+ // Explicit `spPr` replaces the whole shape — the caller opted in
1327
+ // to a full structured override.
1328
+ series.spPr = patchShape;
1329
+ }
1330
+ else {
1331
+ // Sugared patches (`fill` / `line` / `lineWidth` / `lineDash`)
1332
+ // should update only the affected sub-object AND merge inside the
1333
+ // sub-object so narrow patches (e.g. `lineDash` alone) don't wipe
1334
+ // out the adjacent fields.
1335
+ //
1336
+ // Previously the merge stopped at the top level (`{ ...existing,
1337
+ // line: patchShape.line }`) — so `updateSeries(0, { lineDash: "dash" })`
1338
+ // on a series with `{ line: "#FF0000", lineWidth: 2 }` dropped the
1339
+ // colour AND width because `buildSeriesSpPr({ lineDash: "dash" })`
1340
+ // only sets `line.dash`, and the top-level spread replaced the
1341
+ // whole `line` sub-object with `{ dash: "dash" }`. Deep-merge the
1342
+ // sub-objects so each field survives until the caller explicitly
1343
+ // overwrites it.
1344
+ const existing = series.spPr ?? {};
1345
+ const next = { ...existing };
1346
+ if (patchShape?.fill !== undefined) {
1347
+ next.fill = patchShape.fill;
1348
+ }
1349
+ if (patchShape?.line !== undefined) {
1350
+ next.line = { ...(existing.line ?? {}), ...patchShape.line };
1351
+ }
1352
+ series.spPr = next;
1353
+ }
1354
+ // CRITICAL: clear `_rawXml` so the writer serialises from the
1355
+ // structured fields we just patched. The chart-space writer emits
1356
+ // `_rawXml` verbatim when present (`_renderSpPr` at the top of the
1357
+ // function body in `chart-space-xform.ts`), which meant every
1358
+ // structured mutation was silently overridden by the stale raw
1359
+ // bytes captured at parse time. After this clear the next save
1360
+ // re-serialises the full shape tree from the structured fields.
1361
+ if (series.spPr && "_rawXml" in series.spPr) {
1362
+ delete series.spPr._rawXml;
1363
+ }
1364
+ }
1365
+ if (options.marker !== undefined) {
1366
+ series.marker = buildMarkerFromOpts(options.marker);
1367
+ }
1368
+ if (options.dataLabels !== undefined) {
1369
+ series.dataLabels = buildDataLabelsFromOpts(options.dataLabels);
1370
+ }
1371
+ if (options.trendline !== undefined) {
1372
+ const trendlineOpts = Array.isArray(options.trendline)
1373
+ ? options.trendline
1374
+ : [options.trendline];
1375
+ series.trendlines =
1376
+ trendlineOpts.map(buildTrendlineFromOpts);
1377
+ }
1378
+ if (options.dataPoints !== undefined) {
1379
+ series.dataPoints =
1380
+ options.dataPoints.map(buildDataPointFromOpts);
1381
+ }
1382
+ if (options.errorBars !== undefined) {
1383
+ const errorBars = Array.isArray(options.errorBars) ? options.errorBars : [options.errorBars];
1384
+ // Validate each error-bar config independently. Previously the
1385
+ // patch path relied on the outer `validateSeriesPatchOptions` call
1386
+ // at the top of this function, but that skip when `chartType` is
1387
+ // omitted. `CT_ErrBars` requires `errValType`, and without a
1388
+ // validator an options object missing `type` would silently emit
1389
+ // `<c:errValType/>` (no attribute) → schema-invalid output.
1390
+ for (const eb of errorBars) {
1391
+ validateErrorBarsOptions(eb, "series.errorBars");
1392
+ }
1393
+ const built = errorBars.map(buildErrorBarsFromOpts);
1394
+ series.errorBars =
1395
+ chartType === "scatter" || chartType === "bubble" ? built : built[0];
1396
+ }
1397
+ // NOTE: classic chart series have no `txPr` slot in OOXML — see the
1398
+ // `AddChartSeriesOptions` type comment. The field was removed from
1399
+ // the options bag so this patch branch is gone as well.
1400
+ if (options.pictureFill !== undefined) {
1401
+ applyPictureFillToSeries(series, options.pictureFill, {
1402
+ supportsPictureOptions: chartType === "bar" || chartType === "bar3D"
1403
+ });
1404
+ }
1405
+ if (options.smooth !== undefined) {
1406
+ series.smooth = options.smooth;
1407
+ }
1408
+ if (options.invertIfNegative !== undefined) {
1409
+ series.invertIfNegative =
1410
+ options.invertIfNegative;
1411
+ }
1412
+ if (options.explosion !== undefined) {
1413
+ series.explosion = options.explosion;
1414
+ }
1415
+ if (options.bubble3D !== undefined) {
1416
+ series.bubble3D = options.bubble3D;
1417
+ }
1418
+ }
1419
+ function hasSeriesShapePatch(options) {
1420
+ return (options.spPr !== undefined ||
1421
+ options.fill !== undefined ||
1422
+ options.line !== undefined ||
1423
+ options.lineWidth !== undefined ||
1424
+ options.lineDash !== undefined);
1425
+ }
1426
+ function buildTitle(input) {
1427
+ if (typeof input === "string") {
1428
+ return {
1429
+ text: {
1430
+ paragraphs: [{ runs: [{ text: input }] }]
1431
+ },
1432
+ overlay: false
1433
+ };
1434
+ }
1435
+ if ("formula" in input) {
1436
+ return {
1437
+ strRef: makeStrRef(input.formula),
1438
+ overlay: false
1439
+ };
1440
+ }
1441
+ // ChartRichText
1442
+ return {
1443
+ text: input,
1444
+ overlay: false
1445
+ };
1446
+ }
1447
+ function buildDataTableFromOpts(opts) {
1448
+ if (!opts) {
1449
+ return undefined;
1450
+ }
1451
+ if (opts === true) {
1452
+ return { showHorzBorder: true, showVertBorder: true, showOutline: true, showKeys: true };
1453
+ }
1454
+ return {
1455
+ showHorzBorder: opts.showHorzBorder,
1456
+ showVertBorder: opts.showVertBorder,
1457
+ showOutline: opts.showOutline,
1458
+ showKeys: opts.showKeys
1459
+ };
1460
+ }
1461
+ function buildUpDownBarsFromOpts(opts) {
1462
+ if (!opts) {
1463
+ return undefined;
1464
+ }
1465
+ if (opts === true) {
1466
+ return { gapWidth: 150 };
1467
+ }
1468
+ const udb = { gapWidth: opts.gapWidth ?? 150 };
1469
+ const upBars = toShapeProperties(opts.upBars);
1470
+ if (upBars) {
1471
+ udb.upBars = upBars;
1472
+ }
1473
+ const downBars = toShapeProperties(opts.downBars);
1474
+ if (downBars) {
1475
+ udb.downBars = downBars;
1476
+ }
1477
+ return udb;
1478
+ }
1479
+ function buildLegend(opts) {
1480
+ if (opts.showLegend === false) {
1481
+ return undefined;
1482
+ }
1483
+ return {
1484
+ legendPos: opts.legendPosition ?? "b",
1485
+ overlay: false
1486
+ };
1487
+ }
1488
+ /**
1489
+ * Apply user-specified axis options to a built axis.
1490
+ */
1491
+ function applyAxisOptions(axis, opts) {
1492
+ if (!opts) {
1493
+ return;
1494
+ }
1495
+ if (opts.title !== undefined) {
1496
+ // Replace the title text but preserve any previously-applied
1497
+ // `titleOptions` (layout, overlay, spPr, txPr) attached to
1498
+ // `axis.title`. Combo charts call `applyAxisOptions` repeatedly on
1499
+ // a shared axis (see `buildChartTypeGroup` reuse paths), and a
1500
+ // wholesale replacement here discarded every field except the new
1501
+ // text. We graft the new title runs onto the existing frame.
1502
+ const fresh = buildTitle(opts.title);
1503
+ axis.title = axis.title
1504
+ ? {
1505
+ ...axis.title,
1506
+ strRef: fresh.strRef,
1507
+ text: fresh.text,
1508
+ rawTx: fresh.rawTx
1509
+ }
1510
+ : fresh;
1511
+ }
1512
+ if (opts.titleOptions) {
1513
+ if (!axis.title) {
1514
+ axis.title = { overlay: false };
1515
+ }
1516
+ applyTitleOptions(axis.title, opts.titleOptions);
1517
+ }
1518
+ if (opts.numFmt !== undefined) {
1519
+ // Merge onto any prior `numFmt` so a later call that supplies
1520
+ // `opts.numFmt` without `opts.numFmtLinked` doesn't reset
1521
+ // `sourceLinked` back to `undefined`. Same class of bug as the
1522
+ // title replacement above — triggered when combo-chart flows
1523
+ // apply options to a shared axis in multiple passes.
1524
+ axis.numFmt = {
1525
+ ...axis.numFmt,
1526
+ formatCode: opts.numFmt,
1527
+ ...(opts.numFmtLinked !== undefined ? { sourceLinked: opts.numFmtLinked } : {})
1528
+ };
1529
+ }
1530
+ if (opts.min !== undefined || opts.max !== undefined || opts.orientation || opts.logBase) {
1531
+ if (!axis.scaling) {
1532
+ axis.scaling = {};
1533
+ }
1534
+ if (opts.min !== undefined) {
1535
+ axis.scaling.min = opts.min;
1536
+ }
1537
+ if (opts.max !== undefined) {
1538
+ axis.scaling.max = opts.max;
1539
+ }
1540
+ if (opts.orientation) {
1541
+ axis.scaling.orientation = opts.orientation;
1542
+ }
1543
+ if (opts.logBase !== undefined) {
1544
+ axis.scaling.logBase = opts.logBase;
1545
+ }
1546
+ }
1547
+ if (opts.majorUnit !== undefined && axis.axisType === "val") {
1548
+ axis.majorUnit = opts.majorUnit;
1549
+ }
1550
+ if (opts.minorUnit !== undefined && axis.axisType === "val") {
1551
+ axis.minorUnit = opts.minorUnit;
1552
+ }
1553
+ if (opts.majorTickMark) {
1554
+ axis.majorTickMark = opts.majorTickMark;
1555
+ }
1556
+ if (opts.minorTickMark) {
1557
+ axis.minorTickMark = opts.minorTickMark;
1558
+ }
1559
+ if (opts.tickLblPos) {
1560
+ axis.tickLblPos = opts.tickLblPos;
1561
+ }
1562
+ // Major gridlines: the explicit `majorGridlines` boolean is an on/off
1563
+ // switch that must win over any `majorGridlinesStyle`. Callers who
1564
+ // pass both `{ majorGridlines: false, majorGridlinesStyle: { … } }`
1565
+ // mean "hide them, even though I've authored a style for the ON
1566
+ // state" — dropping the style and emitting nothing is the right
1567
+ // call. The previous code checked the boolean in an `else if`, so
1568
+ // an explicit `false` was silently ignored whenever a style was
1569
+ // supplied and the gridlines stayed drawn.
1570
+ const majorGridlinesStyle = toShapeProperties(opts.majorGridlinesStyle);
1571
+ if (opts.majorGridlines === false) {
1572
+ axis.majorGridlines = undefined;
1573
+ }
1574
+ else if (majorGridlinesStyle) {
1575
+ axis.majorGridlines = majorGridlinesStyle;
1576
+ }
1577
+ else if (opts.majorGridlines === true) {
1578
+ axis.majorGridlines = {};
1579
+ }
1580
+ const minorGridlinesStyle = toShapeProperties(opts.minorGridlinesStyle);
1581
+ if (opts.minorGridlines === false) {
1582
+ axis.minorGridlines = undefined;
1583
+ }
1584
+ else if (minorGridlinesStyle) {
1585
+ axis.minorGridlines = minorGridlinesStyle;
1586
+ }
1587
+ else if (opts.minorGridlines === true) {
1588
+ axis.minorGridlines = {};
1589
+ }
1590
+ if (opts.hidden !== undefined) {
1591
+ axis.delete = opts.hidden;
1592
+ }
1593
+ if (opts.crossBetween !== undefined && axis.axisType === "val") {
1594
+ axis.crossBetween = opts.crossBetween;
1595
+ }
1596
+ // Text properties — structured txPr takes priority over textRotation
1597
+ if (opts.txPr) {
1598
+ axis.txPr = opts.txPr;
1599
+ }
1600
+ else if (opts.textRotation !== undefined) {
1601
+ // `a:bodyPr/@rot` is `ST_Angle` = `xsd:int`. Round so a caller
1602
+ // passing fractional degrees (or a value like 1.05° that IEEE 754
1603
+ // turns into 63000.000000000004) doesn't inject `"NaN"` /
1604
+ // `"63000.00000000001"` as an attribute value.
1605
+ axis.txPr = { rotation: Math.round(opts.textRotation * 60000) };
1606
+ }
1607
+ if (opts.lblAlgn !== undefined && axis.axisType === "cat") {
1608
+ axis.lblAlgn = opts.lblAlgn;
1609
+ }
1610
+ if (opts.lblOffset !== undefined && axis.axisType === "cat") {
1611
+ axis.lblOffset = opts.lblOffset;
1612
+ }
1613
+ if (opts.tickLblSkip !== undefined && axis.axisType === "cat") {
1614
+ axis.tickLblSkip = opts.tickLblSkip;
1615
+ }
1616
+ if (opts.tickMarkSkip !== undefined && axis.axisType === "cat") {
1617
+ axis.tickMarkSkip = opts.tickMarkSkip;
1618
+ }
1619
+ if (opts.crosses !== undefined) {
1620
+ axis.crosses = opts.crosses;
1621
+ }
1622
+ if (opts.crossesAt !== undefined) {
1623
+ axis.crossesAt = opts.crossesAt;
1624
+ }
1625
+ if (axis.axisType === "val") {
1626
+ const valAx = axis;
1627
+ if (opts.displayUnits !== undefined ||
1628
+ opts.customUnit !== undefined ||
1629
+ opts.displayUnitsLabel !== undefined) {
1630
+ valAx.dispUnits = valAx.dispUnits ?? {};
1631
+ if (opts.displayUnits !== undefined) {
1632
+ valAx.dispUnits.builtInUnit = opts.displayUnits;
1633
+ }
1634
+ if (opts.customUnit !== undefined) {
1635
+ valAx.dispUnits.custUnit = opts.customUnit;
1636
+ }
1637
+ if (opts.displayUnitsLabel !== undefined) {
1638
+ valAx.dispUnits.label = buildTitle(opts.displayUnitsLabel);
1639
+ }
1640
+ }
1641
+ }
1642
+ // Date-axis-specific units
1643
+ if (axis.axisType === "date") {
1644
+ const dateAx = axis;
1645
+ if (opts.baseTimeUnit !== undefined) {
1646
+ dateAx.baseTimeUnit = opts.baseTimeUnit;
1647
+ }
1648
+ if (opts.majorTimeUnit !== undefined) {
1649
+ dateAx.majorTimeUnit = opts.majorTimeUnit;
1650
+ }
1651
+ if (opts.minorTimeUnit !== undefined) {
1652
+ dateAx.minorTimeUnit = opts.minorTimeUnit;
1653
+ }
1654
+ }
1655
+ // Structured spPr takes priority over line-only shortcuts
1656
+ const customSpPr = toShapeProperties(opts.spPr);
1657
+ if (customSpPr) {
1658
+ axis.spPr = customSpPr;
1659
+ }
1660
+ else if (opts.lineColor || opts.lineWidth !== undefined || opts.lineDash) {
1661
+ const line = {};
1662
+ if (opts.lineColor) {
1663
+ line.color = hexToColor(opts.lineColor);
1664
+ }
1665
+ if (opts.lineWidth !== undefined) {
1666
+ line.width = Math.round(opts.lineWidth * EMU_PER_POINT); // pt to EMU
1667
+ }
1668
+ if (opts.lineDash) {
1669
+ line.dash = opts.lineDash;
1670
+ }
1671
+ if (!axis.spPr) {
1672
+ axis.spPr = {};
1673
+ }
1674
+ axis.spPr.line = line;
1675
+ }
1676
+ }
1677
+ function buildCatValAxes(axIds) {
1678
+ const catAxId = axIds.alloc();
1679
+ const valAxId = axIds.alloc();
1680
+ return {
1681
+ catAx: {
1682
+ axisType: "cat",
1683
+ axId: catAxId,
1684
+ scaling: { orientation: "minMax" },
1685
+ delete: false,
1686
+ axPos: "b",
1687
+ crossAx: valAxId,
1688
+ crosses: "autoZero",
1689
+ auto: true,
1690
+ lblAlgn: "ctr",
1691
+ lblOffset: 100
1692
+ },
1693
+ valAx: {
1694
+ axisType: "val",
1695
+ axId: valAxId,
1696
+ scaling: { orientation: "minMax" },
1697
+ delete: false,
1698
+ axPos: "l",
1699
+ crossAx: catAxId,
1700
+ crosses: "autoZero",
1701
+ crossBetween: "between",
1702
+ majorGridlines: {}
1703
+ }
1704
+ };
1705
+ }
1706
+ function buildValValAxes(axIds) {
1707
+ const xAxId = axIds.alloc();
1708
+ const yAxId = axIds.alloc();
1709
+ return {
1710
+ xAx: {
1711
+ axisType: "val",
1712
+ axId: xAxId,
1713
+ scaling: { orientation: "minMax" },
1714
+ delete: false,
1715
+ axPos: "b",
1716
+ crossAx: yAxId,
1717
+ crosses: "autoZero"
1718
+ },
1719
+ yAx: {
1720
+ axisType: "val",
1721
+ axId: yAxId,
1722
+ scaling: { orientation: "minMax" },
1723
+ delete: false,
1724
+ axPos: "l",
1725
+ crossAx: xAxId,
1726
+ crosses: "autoZero",
1727
+ majorGridlines: {}
1728
+ }
1729
+ };
1730
+ }
1731
+ function buildCatValSerAxes(axIds) {
1732
+ const { catAx, valAx } = buildCatValAxes(axIds);
1733
+ const serAxId = axIds.alloc();
1734
+ // serAx crosses the catAx
1735
+ const serAx = {
1736
+ axisType: "ser",
1737
+ axId: serAxId,
1738
+ scaling: { orientation: "minMax" },
1739
+ delete: false,
1740
+ axPos: "b",
1741
+ crossAx: catAx.axId,
1742
+ crosses: "autoZero"
1743
+ };
1744
+ return { catAx, valAx, serAx };
1745
+ }
1746
+ function buildChartTypeGroup(opts, seriesOpts, axIds) {
1747
+ const type = opts.type;
1748
+ let result;
1749
+ switch (type) {
1750
+ case "bar": {
1751
+ const { catAx, valAx } = buildCatValAxes(axIds);
1752
+ const barDir = opts.barDir ?? "col";
1753
+ // Horizontal bar charts (`barDir="bar"`) swap the axis
1754
+ // directions: the category axis is on the left (vertical),
1755
+ // value axis at the bottom (horizontal). Excel itself emits
1756
+ // `axPos="l"` / `axPos="b"` respectively in that case.
1757
+ // `buildCatValAxes` produces the column-chart defaults
1758
+ // (`catAx.axPos="b"`, `valAx.axPos="l"`), which were left
1759
+ // unchanged for horizontal bar charts — the resulting XML
1760
+ // still rendered in Excel because Excel infers orientation
1761
+ // from `c:barDir`, but the renderer's `pickAxis` (position-
1762
+ // based) picked the wrong axis for gridlines / tick labels on
1763
+ // horizontal bars built via `addBarChart`.
1764
+ //
1765
+ // We deliberately do NOT move `majorGridlines` between axes —
1766
+ // `<c:majorGridlines/>` on a value axis means "draw gridlines
1767
+ // perpendicular to the value axis at every tick". When the
1768
+ // value axis is horizontal (bottom), the renderer correctly
1769
+ // projects those as vertical strokes because it picks up
1770
+ // gridlines from the X-axis slot (by `axPos`), not by
1771
+ // axis-type.
1772
+ if (barDir === "bar") {
1773
+ catAx.axPos = "l";
1774
+ valAx.axPos = "b";
1775
+ }
1776
+ const group = {
1777
+ type,
1778
+ barDir,
1779
+ grouping: opts.grouping ?? "clustered",
1780
+ varyColors: opts.varyColors,
1781
+ series: seriesOpts.map(buildBarSeries),
1782
+ gapWidth: opts.gapWidth ?? 150,
1783
+ overlap: opts.overlap,
1784
+ serLines: opts.serLines ? {} : undefined,
1785
+ axisIds: [catAx.axId, valAx.axId]
1786
+ };
1787
+ result = { group, axes: [catAx, valAx] };
1788
+ break;
1789
+ }
1790
+ case "bar3D": {
1791
+ const { catAx, valAx, serAx } = buildCatValSerAxes(axIds);
1792
+ const barDir = opts.barDir ?? "col";
1793
+ if (barDir === "bar") {
1794
+ catAx.axPos = "l";
1795
+ valAx.axPos = "b";
1796
+ }
1797
+ // `CT_Bar3DChart` does NOT accept `overlap` or `serLines` — both
1798
+ // are 2-D-only. Reject them loud here so the options validator
1799
+ // catches the mistake before the writer silently drops them.
1800
+ if (opts.overlap !== undefined) {
1801
+ throw new errors_1.ChartOptionsError('bar3D charts do not support `overlap` (valid only on 2-D `bar`). Remove the field or switch to `type: "bar"`.');
1802
+ }
1803
+ if (opts.serLines !== undefined) {
1804
+ throw new errors_1.ChartOptionsError('bar3D charts do not support `serLines` (valid only on 2-D `bar`). Remove the field or switch to `type: "bar"`.');
1805
+ }
1806
+ const group = {
1807
+ type,
1808
+ barDir,
1809
+ grouping: opts.grouping ?? "clustered",
1810
+ varyColors: opts.varyColors,
1811
+ series: seriesOpts.map(buildBarSeries),
1812
+ gapWidth: opts.gapWidth ?? 150,
1813
+ gapDepth: opts.gapDepth,
1814
+ shape: opts.shape,
1815
+ axisIds: [catAx.axId, valAx.axId, serAx.axId]
1816
+ };
1817
+ result = { group, axes: [catAx, valAx, serAx] };
1818
+ break;
1819
+ }
1820
+ case "line": {
1821
+ const { catAx, valAx } = buildCatValAxes(axIds);
1822
+ const group = {
1823
+ type,
1824
+ grouping: opts.grouping ?? "standard",
1825
+ varyColors: opts.varyColors,
1826
+ series: seriesOpts.map(buildLineSeries),
1827
+ marker: opts.showMarker ?? true,
1828
+ smooth: opts.smooth,
1829
+ hiLowLines: opts.hiLowLines ? {} : undefined,
1830
+ upDownBars: buildUpDownBarsFromOpts(opts.upDownBars),
1831
+ dropLines: opts.dropLines ? {} : undefined,
1832
+ axisIds: [catAx.axId, valAx.axId]
1833
+ };
1834
+ result = { group, axes: [catAx, valAx] };
1835
+ break;
1836
+ }
1837
+ case "line3D": {
1838
+ const { catAx, valAx, serAx } = buildCatValSerAxes(axIds);
1839
+ // `CT_Line3DChart` does NOT accept `marker`, `smooth`,
1840
+ // `hiLowLines`, or `upDownBars` — all 2-D-only.
1841
+ // Rejected upstream in validateChartLevelOptions.
1842
+ const group = {
1843
+ type,
1844
+ grouping: opts.grouping ?? "standard",
1845
+ varyColors: opts.varyColors,
1846
+ series: seriesOpts.map(buildLineSeries),
1847
+ dropLines: opts.dropLines ? {} : undefined,
1848
+ gapDepth: opts.gapDepth,
1849
+ axisIds: [catAx.axId, valAx.axId, serAx.axId]
1850
+ };
1851
+ result = { group, axes: [catAx, valAx, serAx] };
1852
+ break;
1853
+ }
1854
+ case "pie":
1855
+ case "pie3D": {
1856
+ const group = {
1857
+ type,
1858
+ varyColors: opts.varyColors ?? true,
1859
+ series: seriesOpts.map(buildPieSeries),
1860
+ firstSliceAng: opts.firstSliceAng ?? 0
1861
+ };
1862
+ result = { group, axes: [] };
1863
+ break;
1864
+ }
1865
+ case "doughnut": {
1866
+ const group = {
1867
+ type: "doughnut",
1868
+ varyColors: opts.varyColors ?? true,
1869
+ series: seriesOpts.map(buildPieSeries),
1870
+ firstSliceAng: opts.firstSliceAng ?? 0,
1871
+ holeSize: opts.holeSize ?? 50
1872
+ };
1873
+ result = { group, axes: [] };
1874
+ break;
1875
+ }
1876
+ case "area": {
1877
+ const { catAx, valAx } = buildCatValAxes(axIds);
1878
+ const group = {
1879
+ type,
1880
+ grouping: opts.grouping ?? "standard",
1881
+ varyColors: opts.varyColors,
1882
+ series: seriesOpts.map(buildAreaSeries),
1883
+ dropLines: opts.dropLines ? {} : undefined,
1884
+ axisIds: [catAx.axId, valAx.axId]
1885
+ };
1886
+ result = { group, axes: [catAx, valAx] };
1887
+ break;
1888
+ }
1889
+ case "area3D": {
1890
+ const { catAx, valAx, serAx } = buildCatValSerAxes(axIds);
1891
+ const group = {
1892
+ type,
1893
+ grouping: opts.grouping ?? "standard",
1894
+ varyColors: opts.varyColors,
1895
+ series: seriesOpts.map(buildAreaSeries),
1896
+ dropLines: opts.dropLines ? {} : undefined,
1897
+ // `CT_Area3DChart` carries `gapDepth`; pass it through from
1898
+ // options. The equivalent lines for `bar3D` / `line3D` already
1899
+ // did this — the omission here silently dropped the option.
1900
+ gapDepth: opts.gapDepth,
1901
+ axisIds: [catAx.axId, valAx.axId, serAx.axId]
1902
+ };
1903
+ result = { group, axes: [catAx, valAx, serAx] };
1904
+ break;
1905
+ }
1906
+ case "scatter": {
1907
+ const { xAx, yAx } = buildValValAxes(axIds);
1908
+ const group = {
1909
+ type: "scatter",
1910
+ scatterStyle: opts.scatterStyle ?? "lineMarker",
1911
+ varyColors: opts.varyColors,
1912
+ series: seriesOpts.map(buildScatterSeries),
1913
+ axisIds: [xAx.axId, yAx.axId]
1914
+ };
1915
+ result = { group, axes: [xAx, yAx] };
1916
+ break;
1917
+ }
1918
+ case "bubble": {
1919
+ const { xAx, yAx } = buildValValAxes(axIds);
1920
+ const group = {
1921
+ type: "bubble",
1922
+ varyColors: opts.varyColors,
1923
+ series: seriesOpts.map(buildBubbleSeries),
1924
+ bubbleScale: opts.bubbleScale,
1925
+ showNegBubbles: opts.showNegBubbles,
1926
+ sizeRepresents: opts.sizeRepresents,
1927
+ axisIds: [xAx.axId, yAx.axId]
1928
+ };
1929
+ result = { group, axes: [xAx, yAx] };
1930
+ break;
1931
+ }
1932
+ case "radar": {
1933
+ const { catAx, valAx } = buildCatValAxes(axIds);
1934
+ const group = {
1935
+ type: "radar",
1936
+ radarStyle: opts.radarStyle ?? "marker",
1937
+ varyColors: opts.varyColors,
1938
+ series: seriesOpts.map(buildRadarSeries),
1939
+ axisIds: [catAx.axId, valAx.axId]
1940
+ };
1941
+ result = { group, axes: [catAx, valAx] };
1942
+ break;
1943
+ }
1944
+ case "stock": {
1945
+ // `CT_StockChart` has no `varyColors` attribute per schema — see
1946
+ // `StockChartGroup` in types.ts. Reject the option here rather
1947
+ // than silently dropping it at emit time so the mistake
1948
+ // surfaces at authoring.
1949
+ if (opts.varyColors !== undefined) {
1950
+ throw new errors_1.ChartOptionsError("stock charts do not support `varyColors` (not in CT_StockChart). Remove the field or switch to a line / bar / area chart.");
1951
+ }
1952
+ const { catAx, valAx } = buildCatValAxes(axIds);
1953
+ const group = {
1954
+ type: "stock",
1955
+ series: seriesOpts.map(buildLineSeries),
1956
+ hiLowLines: opts.hiLowLines ? {} : undefined,
1957
+ upDownBars: buildUpDownBarsFromOpts(opts.upDownBars),
1958
+ dropLines: opts.dropLines ? {} : undefined,
1959
+ axisIds: [catAx.axId, valAx.axId]
1960
+ };
1961
+ result = { group, axes: [catAx, valAx] };
1962
+ break;
1963
+ }
1964
+ case "surface":
1965
+ case "surface3D": {
1966
+ const { catAx, valAx, serAx } = buildCatValSerAxes(axIds);
1967
+ const group = {
1968
+ type,
1969
+ wireframe: opts.wireframe,
1970
+ series: seriesOpts.map(buildSurfaceSeries),
1971
+ axisIds: [catAx.axId, valAx.axId, serAx.axId]
1972
+ };
1973
+ if (opts.bandFormats && opts.bandFormats.length > 0) {
1974
+ group.bandFormats = opts.bandFormats.map(bf => {
1975
+ const spPr = toShapeProperties(bf.spPr);
1976
+ return { index: bf.index, spPr: spPr ?? {} };
1977
+ });
1978
+ }
1979
+ result = { group, axes: [catAx, valAx, serAx] };
1980
+ break;
1981
+ }
1982
+ case "ofPie": {
1983
+ const group = {
1984
+ type: "ofPie",
1985
+ ofPieType: opts.ofPieType ?? "pie",
1986
+ varyColors: opts.varyColors ?? true,
1987
+ series: seriesOpts.map(buildPieSeries),
1988
+ gapWidth: opts.gapWidth,
1989
+ splitType: opts.splitType,
1990
+ splitPos: opts.splitPos,
1991
+ secondPieSize: opts.secondPieSize,
1992
+ serLines: opts.serLines ? {} : undefined
1993
+ };
1994
+ result = { group, axes: [] };
1995
+ break;
1996
+ }
1997
+ default: {
1998
+ const _exhaustive = type;
1999
+ throw new errors_1.ChartOptionsError(`Unsupported chart type: ${String(_exhaustive)}.`);
2000
+ }
2001
+ }
2002
+ // Post-process: apply group-level data labels
2003
+ if (opts.dataLabels) {
2004
+ result.group.dataLabels = buildDataLabelsFromOpts(opts.dataLabels);
2005
+ }
2006
+ // Post-process: apply axis options
2007
+ if (result.axes.length > 0) {
2008
+ // For cat+val axes, apply categoryAxis options to first cat/date axis,
2009
+ // and valueAxis options to first val axis.
2010
+ // For scatter/bubble (val+val), categoryAxis → first val (x), valueAxis → second val (y).
2011
+ const catAx = result.axes.find(a => a.axisType === "cat" || a.axisType === "date");
2012
+ const valAx = result.axes.find(a => a.axisType === "val");
2013
+ if (catAx) {
2014
+ applyAxisOptions(catAx, opts.categoryAxis);
2015
+ const vAx = result.axes.find(a => a.axisType === "val");
2016
+ if (vAx) {
2017
+ applyAxisOptions(vAx, opts.valueAxis);
2018
+ }
2019
+ }
2020
+ else if (valAx) {
2021
+ // scatter/bubble: x axis = first val, y axis = second val
2022
+ applyAxisOptions(valAx, opts.categoryAxis);
2023
+ const secondVal = result.axes.find(a => a.axisType === "val" && a.axId !== valAx.axId);
2024
+ if (secondVal) {
2025
+ applyAxisOptions(secondVal, opts.valueAxis);
2026
+ }
2027
+ }
2028
+ }
2029
+ return result;
2030
+ }
2031
+ /**
2032
+ * Finalize a ChartModel from a PlotArea and shared options.
2033
+ */
2034
+ function finalizeChartModel(plotArea, opts) {
2035
+ const chart = {
2036
+ plotArea,
2037
+ plotVisOnly: opts.plotVisOnly ?? true,
2038
+ dispBlanksAs: opts.displayBlanksAs ?? "gap"
2039
+ };
2040
+ if (opts.showDLblsOverMax !== undefined) {
2041
+ chart.showDLblsOverMax = opts.showDLblsOverMax;
2042
+ }
2043
+ if (opts.pivotSource) {
2044
+ // Don't mutate caller-owned `opts.pivotSource` — `extractPivotOptions`
2045
+ // already handles the merge priority between
2046
+ // `opts.pivotChartOptions` (explicit) and `pivotSource.options`
2047
+ // (embedded). Writing back here produced surprising side-effects
2048
+ // when callers reused the same `pivotSource` object across charts.
2049
+ chart.pivotFormats = [{ index: 0 }];
2050
+ }
2051
+ // Title handling has three mutually exclusive shapes:
2052
+ //
2053
+ // 1. `title === null` → explicit suppression. Emit
2054
+ // `autoTitleDeleted="1"` so Excel records the user removed the
2055
+ // auto-title. Do NOT build a title frame even if `titleOptions`
2056
+ // was also provided — the explicit `null` wins over layout /
2057
+ // style hints.
2058
+ // 2. `title` truthy → build the title, optionally apply
2059
+ // `titleOptions` on top.
2060
+ // 3. `title` absent, `titleOptions` set → layout / style for the
2061
+ // auto-generated title. Uncommon but valid.
2062
+ // 4. Everything else → leave `autoTitleDeleted` undefined so
2063
+ // the writer omits it, matching Excel's behaviour for a fresh
2064
+ // unmodified chart.
2065
+ //
2066
+ // Checking `title === null` before `if (opts.title)` is important —
2067
+ // `if (null)` is falsy, so reversing the order landed an explicit
2068
+ // `null` in the `titleOptions`-only branch that built an empty title
2069
+ // frame.
2070
+ if (opts.title === null) {
2071
+ chart.autoTitleDeleted = true;
2072
+ }
2073
+ else if (opts.title) {
2074
+ chart.title = buildTitle(opts.title);
2075
+ if (opts.titleOptions) {
2076
+ applyTitleOptions(chart.title, opts.titleOptions);
2077
+ }
2078
+ chart.autoTitleDeleted = false;
2079
+ }
2080
+ else if (opts.titleOptions) {
2081
+ // Layout/style without title text is unusual but allowed
2082
+ chart.title = { overlay: false };
2083
+ applyTitleOptions(chart.title, opts.titleOptions);
2084
+ chart.autoTitleDeleted = false;
2085
+ }
2086
+ // else: leave autoTitleDeleted undefined so the writer omits it,
2087
+ // matching Excel's behaviour for a fresh unmodified chart — the
2088
+ // automatic title appears unless the user explicitly removes it.
2089
+ const legend = buildLegend(opts);
2090
+ if (legend) {
2091
+ chart.legend = legend;
2092
+ if (opts.legendOptions) {
2093
+ applyLegendOptions(legend, opts.legendOptions);
2094
+ }
2095
+ }
2096
+ // Plot area options (layout, background)
2097
+ if (opts.plotAreaOptions) {
2098
+ if (opts.plotAreaOptions.layout) {
2099
+ plotArea.layout = opts.plotAreaOptions.layout;
2100
+ }
2101
+ const plotSpPr = toShapeProperties(opts.plotAreaOptions.spPr);
2102
+ if (plotSpPr) {
2103
+ plotArea.spPr = plotSpPr;
2104
+ }
2105
+ }
2106
+ if (opts.view3D) {
2107
+ chart.view3D = opts.view3D;
2108
+ }
2109
+ // 3D walls / floor
2110
+ const floor = toShapeProperties(opts.floor);
2111
+ if (floor) {
2112
+ chart.floor = floor;
2113
+ }
2114
+ const sideWall = toShapeProperties(opts.sideWall);
2115
+ if (sideWall) {
2116
+ chart.sideWall = sideWall;
2117
+ }
2118
+ const backWall = toShapeProperties(opts.backWall);
2119
+ if (backWall) {
2120
+ chart.backWall = backWall;
2121
+ }
2122
+ return {
2123
+ chart,
2124
+ style: opts.style,
2125
+ roundedCorners: false,
2126
+ lang: "en-US",
2127
+ pivotSource: opts.pivotSource ? buildPivotSourceXml(opts.pivotSource) : undefined,
2128
+ pivotOptions: extractPivotOptions(opts.pivotSource, opts.pivotChartOptions)
2129
+ };
2130
+ }
2131
+ /**
2132
+ * Resolve the effective {@link PivotChartOptions} for a model built from
2133
+ * {@link AddChartOptions}.
2134
+ *
2135
+ * Accepts two redundant inputs so callers can pass the structured metadata
2136
+ * via either the top-level `pivotChartOptions` field or the `pivotSource`
2137
+ * object (its `options` sub-field, retained for ergonomic clustering).
2138
+ * When both are set the top-level value wins — this matches the precedence
2139
+ * used elsewhere in `chart-builder.ts` when the same setting has two
2140
+ * spellings.
2141
+ *
2142
+ * Returns `undefined` when no options are provided so the writer can skip
2143
+ * emitting an empty `c14:pivotOptions` element.
2144
+ */
2145
+ function extractPivotOptions(source, explicit) {
2146
+ if (explicit) {
2147
+ return explicit;
2148
+ }
2149
+ if (source && typeof source === "object" && source.options) {
2150
+ return source.options;
2151
+ }
2152
+ return undefined;
2153
+ }
2154
+ function applyTitleOptions(title, opts) {
2155
+ if (opts.layout) {
2156
+ title.layout = opts.layout;
2157
+ }
2158
+ if (opts.overlay !== undefined) {
2159
+ title.overlay = opts.overlay;
2160
+ }
2161
+ const spPr = toShapeProperties(opts.spPr);
2162
+ if (spPr) {
2163
+ title.spPr = spPr;
2164
+ }
2165
+ if (opts.txPr) {
2166
+ title.txPr = opts.txPr;
2167
+ }
2168
+ }
2169
+ function applyLegendOptions(legend, opts) {
2170
+ if (opts.layout) {
2171
+ legend.layout = opts.layout;
2172
+ }
2173
+ if (opts.overlay !== undefined) {
2174
+ legend.overlay = opts.overlay;
2175
+ }
2176
+ const spPr = toShapeProperties(opts.spPr);
2177
+ if (spPr) {
2178
+ legend.spPr = spPr;
2179
+ }
2180
+ if (opts.txPr) {
2181
+ legend.txPr = opts.txPr;
2182
+ }
2183
+ if (opts.entries && opts.entries.length > 0) {
2184
+ legend.legendEntries = opts.entries.map(e => {
2185
+ const entry = { index: e.index };
2186
+ if (e.hidden) {
2187
+ entry.delete = true;
2188
+ }
2189
+ if (e.txPr) {
2190
+ entry.txPr = e.txPr;
2191
+ }
2192
+ return entry;
2193
+ });
2194
+ }
2195
+ }
2196
+ /**
2197
+ * Build a full ChartModel from the simplified AddChartOptions.
2198
+ */
2199
+ function buildChartModel(opts) {
2200
+ validateChartOptions(opts);
2201
+ const seriesOpts = opts.series ?? [];
2202
+ const axIds = new AxIdAllocator();
2203
+ const { group: chartTypeGroup, axes } = buildChartTypeGroup(opts, seriesOpts, axIds);
2204
+ const plotArea = {
2205
+ chartTypes: [chartTypeGroup],
2206
+ axes,
2207
+ dataTable: buildDataTableFromOpts(opts.dataTable)
2208
+ };
2209
+ return finalizeChartModel(plotArea, opts);
2210
+ }
2211
+ /**
2212
+ * Build a combo chart model with multiple chart type groups.
2213
+ *
2214
+ * Each group can optionally be plotted on secondary axes.
2215
+ * The builder creates primary axes for the first group that needs
2216
+ * them, and secondary axes for any group with `useSecondaryAxis: true`.
2217
+ */
2218
+ function buildComboChartModel(opts) {
2219
+ validateComboChartOptions(opts);
2220
+ const axIds = new AxIdAllocator();
2221
+ const chartTypeGroups = [];
2222
+ const allAxes = [];
2223
+ // Create primary axes (shared by all groups without useSecondaryAxis)
2224
+ let primaryCatAx;
2225
+ let primaryValAx;
2226
+ let primarySerAx;
2227
+ let primaryXAx;
2228
+ let primaryYAx;
2229
+ // Create secondary axes (shared by all groups with useSecondaryAxis)
2230
+ let secondaryCatAx;
2231
+ let secondaryValAx;
2232
+ let secondarySerAx;
2233
+ let secondaryXAx;
2234
+ let secondaryYAx;
2235
+ for (const groupOpts of opts.groups) {
2236
+ const seriesOpts = groupOpts.series ?? [];
2237
+ const { group, axes } = buildChartTypeGroup(groupOpts, seriesOpts, axIds);
2238
+ // Detect serAx (3D chart types produce 3 axes: catAx + valAx + serAx)
2239
+ const hasSerAx = axes.length >= 3 && axes[2].axisType === "ser";
2240
+ if (axes.length > 0 && groupOpts.useSecondaryAxis) {
2241
+ // Secondary axis group: create secondary axes if not yet created
2242
+ const isCatVal = axes[0].axisType === "cat";
2243
+ if (isCatVal) {
2244
+ if (!secondaryCatAx) {
2245
+ const sCatId = axIds.alloc();
2246
+ const sValId = axIds.alloc();
2247
+ secondaryCatAx = {
2248
+ axisType: "cat",
2249
+ axId: sCatId,
2250
+ scaling: { orientation: "minMax" },
2251
+ delete: true, // secondary cat axis is typically hidden
2252
+ axPos: "b",
2253
+ crossAx: sValId,
2254
+ crosses: "autoZero",
2255
+ auto: true,
2256
+ lblAlgn: "ctr",
2257
+ lblOffset: 100
2258
+ };
2259
+ secondaryValAx = {
2260
+ axisType: "val",
2261
+ axId: sValId,
2262
+ scaling: { orientation: "minMax" },
2263
+ delete: false,
2264
+ axPos: "r", // right side
2265
+ crossAx: sCatId,
2266
+ crosses: "max", // cross at max of secondary cat axis
2267
+ crossBetween: "between"
2268
+ };
2269
+ allAxes.push(secondaryCatAx, secondaryValAx);
2270
+ }
2271
+ // Apply the group's axis options onto the shared secondary
2272
+ // axes. Without this, the `categoryAxis` / `valueAxis` fields
2273
+ // on a second (or third, …) secondary-axis group were silently
2274
+ // discarded along with the auto-built axes — `numFmt`,
2275
+ // `majorUnit`, `title`, `orientation`, etc. never reached the
2276
+ // shared axis object.
2277
+ applyAxisOptions(secondaryCatAx, groupOpts.categoryAxis);
2278
+ applyAxisOptions(secondaryValAx, groupOpts.valueAxis);
2279
+ if (hasSerAx) {
2280
+ // 3D secondary: create or reuse secondary serAx
2281
+ if (!secondarySerAx) {
2282
+ const sSerAxId = axIds.alloc();
2283
+ secondarySerAx = {
2284
+ axisType: "ser",
2285
+ axId: sSerAxId,
2286
+ scaling: { orientation: "minMax" },
2287
+ delete: false,
2288
+ axPos: "b",
2289
+ crossAx: secondaryCatAx.axId,
2290
+ crosses: "autoZero"
2291
+ };
2292
+ allAxes.push(secondarySerAx);
2293
+ }
2294
+ group.axisIds = [secondaryCatAx.axId, secondaryValAx.axId, secondarySerAx.axId];
2295
+ }
2296
+ else {
2297
+ group.axisIds = [secondaryCatAx.axId, secondaryValAx.axId];
2298
+ }
2299
+ }
2300
+ else {
2301
+ // Scatter/bubble secondary axes (valAx + valAx).
2302
+ //
2303
+ // `crossBetween` is only valid when the value axis crosses a
2304
+ // *category* axis — it specifies the tick-label alignment
2305
+ // relative to category boundaries (`between` / `midCat`). On a
2306
+ // val/val pair it has no defined meaning and strict OOXML
2307
+ // validators flag it. The primary scatter axes in
2308
+ // `buildValValAxes` deliberately omit it, so emit the secondary
2309
+ // scatter axes the same way to stay round-trip consistent.
2310
+ if (!secondaryXAx) {
2311
+ const sXId = axIds.alloc();
2312
+ const sYId = axIds.alloc();
2313
+ secondaryXAx = {
2314
+ axisType: "val",
2315
+ axId: sXId,
2316
+ scaling: { orientation: "minMax" },
2317
+ delete: true,
2318
+ axPos: "b",
2319
+ crossAx: sYId,
2320
+ crosses: "autoZero"
2321
+ };
2322
+ secondaryYAx = {
2323
+ axisType: "val",
2324
+ axId: sYId,
2325
+ scaling: { orientation: "minMax" },
2326
+ delete: false,
2327
+ axPos: "r",
2328
+ crossAx: sXId,
2329
+ crosses: "max"
2330
+ };
2331
+ allAxes.push(secondaryXAx, secondaryYAx);
2332
+ }
2333
+ // `categoryAxis` / `valueAxis` map to scatter x / y respectively
2334
+ // (mirroring the primary scatter path in `buildChartTypeGroup`).
2335
+ applyAxisOptions(secondaryXAx, groupOpts.categoryAxis);
2336
+ applyAxisOptions(secondaryYAx, groupOpts.valueAxis);
2337
+ group.axisIds = [secondaryXAx.axId, secondaryYAx.axId];
2338
+ }
2339
+ // Don't add the auto-generated axes from buildChartTypeGroup
2340
+ }
2341
+ else if (axes.length > 0) {
2342
+ // Primary axis group
2343
+ const isCatVal = axes[0].axisType === "cat";
2344
+ if (isCatVal) {
2345
+ if (!primaryCatAx) {
2346
+ primaryCatAx = axes[0];
2347
+ primaryValAx = axes[1];
2348
+ allAxes.push(primaryCatAx, primaryValAx);
2349
+ if (hasSerAx) {
2350
+ primarySerAx = axes[2];
2351
+ allAxes.push(primarySerAx);
2352
+ }
2353
+ }
2354
+ else {
2355
+ // Reuse primary axes — but apply the current group's axis
2356
+ // options onto the shared objects so its customisations
2357
+ // aren't silently discarded with the throw-away auto-built
2358
+ // axes. Previously only the FIRST group's `categoryAxis` /
2359
+ // `valueAxis` reached the output; every subsequent group's
2360
+ // overrides were dropped on the floor.
2361
+ applyAxisOptions(primaryCatAx, groupOpts.categoryAxis);
2362
+ applyAxisOptions(primaryValAx, groupOpts.valueAxis);
2363
+ if (hasSerAx) {
2364
+ // 3D group needs serAx — create one if the primary set didn't have it
2365
+ if (!primarySerAx) {
2366
+ const serAxId = axIds.alloc();
2367
+ primarySerAx = {
2368
+ axisType: "ser",
2369
+ axId: serAxId,
2370
+ scaling: { orientation: "minMax" },
2371
+ delete: false,
2372
+ axPos: "b",
2373
+ crossAx: primaryCatAx.axId,
2374
+ crosses: "autoZero"
2375
+ };
2376
+ allAxes.push(primarySerAx);
2377
+ }
2378
+ group.axisIds = [primaryCatAx.axId, primaryValAx.axId, primarySerAx.axId];
2379
+ }
2380
+ else {
2381
+ group.axisIds = [primaryCatAx.axId, primaryValAx.axId];
2382
+ }
2383
+ }
2384
+ }
2385
+ else {
2386
+ // Scatter/bubble
2387
+ if (!primaryXAx) {
2388
+ primaryXAx = axes[0];
2389
+ primaryYAx = axes[1];
2390
+ allAxes.push(primaryXAx, primaryYAx);
2391
+ }
2392
+ else {
2393
+ // Same rationale as the cat/val reuse path above — apply this
2394
+ // group's scatter axis options onto the shared val/val pair.
2395
+ applyAxisOptions(primaryXAx, groupOpts.categoryAxis);
2396
+ applyAxisOptions(primaryYAx, groupOpts.valueAxis);
2397
+ group.axisIds = [primaryXAx.axId, primaryYAx.axId];
2398
+ }
2399
+ }
2400
+ }
2401
+ chartTypeGroups.push(group);
2402
+ }
2403
+ // Renumber series index/order globally across all groups.
2404
+ // OOXML requires c:idx and c:order to be unique within the entire chart.
2405
+ // Only renumber if indices are the default per-group values (0, 1, 2...) —
2406
+ // i.e. they would collide across groups. If the user has already assigned
2407
+ // explicit globally-unique indices, leave them untouched (P4.2 fix).
2408
+ if (indicesWouldCollide(chartTypeGroups)) {
2409
+ let globalIdx = 0;
2410
+ for (const grp of chartTypeGroups) {
2411
+ for (const s of grp.series) {
2412
+ s.index = globalIdx;
2413
+ s.order = globalIdx;
2414
+ globalIdx++;
2415
+ }
2416
+ }
2417
+ }
2418
+ const plotArea = {
2419
+ chartTypes: chartTypeGroups,
2420
+ axes: allAxes,
2421
+ dataTable: buildDataTableFromOpts(opts.dataTable)
2422
+ };
2423
+ return finalizeChartModel(plotArea, opts);
2424
+ }
2425
+ /**
2426
+ * Check whether any two groups have colliding series indices.
2427
+ * When true, the combo builder renumbers all series to guarantee uniqueness.
2428
+ */
2429
+ function indicesWouldCollide(groups) {
2430
+ const seen = new Set();
2431
+ for (const g of groups) {
2432
+ for (const s of g.series) {
2433
+ if (seen.has(s.index)) {
2434
+ return true;
2435
+ }
2436
+ seen.add(s.index);
2437
+ }
2438
+ }
2439
+ return false;
2440
+ }