docx 9.7.2 → 9.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4800 @@
1
+ import { BuilderElement, Drawing, DrawingPatch, NextAttributeComponent, PackagePart, Run, StringContainer, XmlComponent, createTransformation, hexColorValue } from "docx";
2
+ //#region src/charts/chart-categories.ts
3
+ var isGroup$1 = (category) => typeof category === "object" && category !== null && !(category instanceof Date);
4
+ /**
5
+ * Whether the categories are groups of categories.
6
+ */
7
+ var isCategoryGroups = (categories) => categories.length > 0 && isGroup$1(categories[0]);
8
+ /**
9
+ * The rows of labels grouped categories are laid out in, one for each category, from the outermost group in.
10
+ */
11
+ var categoryRowsOf = (groups) => groups.flatMap(({ name, categories }) => {
12
+ return (isCategoryGroups(categories) ? categoryRowsOf(categories) : categories.map((one) => [one])).map((row, index) => [index === 0 ? name : void 0, ...row]);
13
+ });
14
+ /**
15
+ * The categories along the axis, without their groups: the categories of the innermost groups, in order.
16
+ */
17
+ var leafCategoriesOf = (categories) => isCategoryGroups(categories) ? categoryRowsOf(categories).map((row) => row[row.length - 1]) : categories;
18
+ /**
19
+ * Each category's label with its groups', from the outermost in, such as "2025 Q1", as a screen reader reads it.
20
+ */
21
+ var groupedCategoryLabelsOf = (groups) => groups.flatMap(({ name, categories }) => (isCategoryGroups(categories) ? groupedCategoryLabelsOf(categories) : categories.map(String)).map((label) => `${name} ${label}`));
22
+ //#endregion
23
+ //#region src/charts/chart-dates.ts
24
+ /**
25
+ * Dates as a chart's categories: Excel's serial numbers for them, and the unit a date axis spaces them by.
26
+ *
27
+ * @module
28
+ */
29
+ var MILLISECONDS_PER_DAY = 864e5;
30
+ var EXCEL_EPOCH = Date.UTC(1899, 11, 30);
31
+ var FIRST_DATE = Date.UTC(1900, 2, 1);
32
+ var LAST_DATE = Date.UTC(9999, 11, 31);
33
+ /**
34
+ * How dates are written in the sheet and on the axis, for each unit: unambiguous in any locale.
35
+ */
36
+ var DATE_FORMATS = {
37
+ days: "d mmm yyyy",
38
+ months: "mmm yyyy",
39
+ years: "yyyy"
40
+ };
41
+ /**
42
+ * Checks that a category is a date Excel can hold.
43
+ *
44
+ * @throws If it isn't a valid date from 1 March 1900 to 31 December 9999
45
+ */
46
+ var checkDate = (date) => {
47
+ const time = date.getTime();
48
+ if (!(time >= FIRST_DATE && time < LAST_DATE + MILLISECONDS_PER_DAY)) throw new Error(`Invalid category date ${String(date)}. Expected a date from 1900-03-01 to 9999-12-31`);
49
+ };
50
+ /**
51
+ * A date as Excel's serial number: days since 30 December 1899, with the time of day as a fraction. Dates are read in
52
+ * UTC, as `docx` writes every date, so `new Date("2025-01-31")` is 31 January 2025.
53
+ */
54
+ var serialDate = (date) => (date.getTime() - EXCEL_EPOCH) / MILLISECONDS_PER_DAY;
55
+ /**
56
+ * The unit dates are spaced by, as Excel chooses it: years when they are all the 1st of January, months when they are
57
+ * all the 1st of a month, and otherwise days.
58
+ */
59
+ var timeUnitOf = (dates) => {
60
+ const startsOf = (date) => date.getTime() % MILLISECONDS_PER_DAY === 0 && date.getUTCDate() === 1;
61
+ if (!dates.every(startsOf)) return "days";
62
+ return dates.every((date) => date.getUTCMonth() === 0) ? "years" : "months";
63
+ };
64
+ //#endregion
65
+ //#region src/charts/chart-stock.ts
66
+ var DEFAULT_NAMES = {
67
+ volume: "Volume",
68
+ open: "Open",
69
+ high: "High",
70
+ low: "Low",
71
+ close: "Close"
72
+ };
73
+ var ROLES = [
74
+ "volume",
75
+ "open",
76
+ "high",
77
+ "low",
78
+ "close"
79
+ ];
80
+ /**
81
+ * A stock chart's series, in Word's order, which is the order its sheet's columns are in and its series are plotted in:
82
+ * the volumes, the opening prices, the highs, the lows and the closing prices. Those not given are left out.
83
+ */
84
+ var stockSeriesOf = (options) => ROLES.flatMap((role) => {
85
+ var _options$names$role, _options$names;
86
+ const values = options[role];
87
+ return values === void 0 ? [] : [{
88
+ role,
89
+ name: (_options$names$role = (_options$names = options.names) === null || _options$names === void 0 ? void 0 : _options$names[role]) !== null && _options$names$role !== void 0 ? _options$names$role : DEFAULT_NAMES[role],
90
+ values
91
+ }];
92
+ });
93
+ //#endregion
94
+ //#region src/charts/chart-legend.ts
95
+ var TRENDLINE_NAMES = {
96
+ linear: "Linear",
97
+ exponential: "Expon.",
98
+ logarithmic: "Log.",
99
+ polynomial: "Poly.",
100
+ power: "Power"
101
+ };
102
+ /**
103
+ * A trendline's name in the legend: its own, or Office's, such as "Linear (Sales)" or "3 per. Mov. Avg. (Sales)".
104
+ *
105
+ * @param series - The series' name
106
+ */
107
+ var trendlineNameOf = (trendline, series) => {
108
+ var _trendline$period;
109
+ if (trendline.name !== void 0) return trendline.name;
110
+ return `${trendline.type === "movingAverage" ? `${(_trendline$period = trendline.period) !== null && _trendline$period !== void 0 ? _trendline$period : 2} per. Mov. Avg.` : TRENDLINE_NAMES[trendline.type]} (${series})`;
111
+ };
112
+ /**
113
+ * The legend's entries, in order. A pie's or doughnut's are its categories. Other charts' are their series, in order,
114
+ * then their trendlines, which Office numbers after every series.
115
+ */
116
+ var legendEntriesOf = (options) => {
117
+ switch (options.type) {
118
+ case "pie":
119
+ case "doughnut":
120
+ case "pieOfPie":
121
+ case "barOfPie": return options.categories.map((category, index) => ({
122
+ text: String(category),
123
+ index
124
+ }));
125
+ case "stock": return stockSeriesOf(options).map(({ name }, index) => ({
126
+ text: name,
127
+ index
128
+ }));
129
+ default: {
130
+ const { series } = options;
131
+ const trendlines = series.flatMap(({ name, trendlines: own = [] }) => own.map((trendline) => trendlineNameOf(trendline, name)));
132
+ return [...series.map(({ name }) => name), ...trendlines].map((text, index) => ({
133
+ text,
134
+ index
135
+ }));
136
+ }
137
+ }
138
+ };
139
+ //#endregion
140
+ //#region src/charts/chart-checks.ts
141
+ /**
142
+ * Checks a chart's options, so mistakes show up where the chart is made rather than when the document is opened.
143
+ *
144
+ * @module
145
+ */
146
+ /**
147
+ * Checks that an option is a number in a range, if it is given.
148
+ *
149
+ * @throws If it isn't
150
+ */
151
+ var checkRange = (value, option, minimum, maximum) => {
152
+ if (value !== void 0 && !(value >= minimum && value <= maximum)) throw new Error(`Invalid ${option} ${value}. Expected a number from ${minimum} to ${maximum}`);
153
+ };
154
+ /**
155
+ * A value as an error message writes it: text in quotes, so "5" isn't mistaken for a number.
156
+ */
157
+ var quoted$1 = (value) => typeof value === "string" ? `"${value}"` : String(value);
158
+ /**
159
+ * Checks that an option is a whole number in a range, if it is given.
160
+ */
161
+ var checkWholeNumber = (value, option, minimum, maximum) => {
162
+ if (value !== void 0 && !(Number.isInteger(value) && value >= minimum && value <= maximum)) throw new Error(`Invalid ${option} ${quoted$1(value)}. Expected a whole number from ${minimum} to ${maximum}`);
163
+ };
164
+ var checkSize$1 = ({ width, height }) => {
165
+ for (const [name, value] of [["width", width], ["height", height]]) if (!(value > 0 && Number.isFinite(value))) throw new Error(`Invalid chart ${name} ${value}. Expected a positive number of pixels`);
166
+ };
167
+ var checkFont = (font) => checkRange(font === null || font === void 0 ? void 0 : font.size, "font size", 1, 4e3);
168
+ var checkTitle = (title) => checkFont(typeof title === "object" ? title.font : void 0);
169
+ var checkLine = (line) => checkRange(line === null || line === void 0 ? void 0 : line.width, "line width", 0, 1584);
170
+ var checkArea = (area) => checkLine((area === null || area === void 0 ? void 0 : area.border) === "none" ? void 0 : area === null || area === void 0 ? void 0 : area.border);
171
+ var checkMarkers = (markers) => checkRange(typeof markers === "object" ? markers.size : void 0, "marker size", 2, 72);
172
+ var checkDataLabels = (labels) => checkFont(labels ? labels.font : void 0);
173
+ var SHOWN$1 = [
174
+ "value",
175
+ "category",
176
+ "seriesName",
177
+ "percentage",
178
+ "bubbleSize"
179
+ ];
180
+ /**
181
+ * Checks the labels of single points: no more than there are points, each a label's options, `false` or undefined, and
182
+ * a label with text showing nothing else.
183
+ *
184
+ * @param points - How many points the series has room for, and what they are, for messages
185
+ */
186
+ var checkPointLabels = (series, count, points) => {
187
+ const { name, pointLabels } = series;
188
+ if (pointLabels === void 0) return;
189
+ if (!Array.isArray(pointLabels)) throw new Error(`Invalid point labels ${quoted$1(pointLabels)} for series "${name}". Expected a label for each point, in order`);
190
+ if (pointLabels.length > count) throw new Error(`Series "${name}" has ${pointLabels.length} point labels, but there are ${count} ${points}`);
191
+ pointLabels.forEach((label, index) => {
192
+ if (label === void 0 || label === false) return;
193
+ if (typeof label !== "object" || label === null) throw new Error(`Invalid label ${quoted$1(label)} of point ${index + 1} of series "${name}". Expected a label's options, false or undefined`);
194
+ const { text, numberFormat, font } = label;
195
+ if (text !== void 0) {
196
+ if (typeof text !== "string") throw new Error(`Invalid text ${quoted$1(text)} of the label of point ${index + 1} of series "${name}". Expected text`);
197
+ const shown = [...SHOWN$1, "numberFormat"].find((option) => label[option] !== void 0);
198
+ if (shown !== void 0) throw new Error(`Invalid option ${shown} of the label of point ${index + 1} of series "${name}". A label with text shows only its text`);
199
+ }
200
+ if (numberFormat !== void 0 && typeof numberFormat !== "string") throw new Error(`Invalid number format ${quoted$1(numberFormat)} of the label of point ${index + 1} of series "${name}"`);
201
+ checkFont(font);
202
+ });
203
+ };
204
+ /**
205
+ * Checks where an axis crosses the other: a place, a finite number, or, on a value axis crossing categories that are
206
+ * dates, a date. A value axis crossing dates takes a date rather than a category's number.
207
+ *
208
+ * @param dates - Whether the axis crosses categories that are dates
209
+ */
210
+ var checkCrossing = (crossesAt, name, dates) => {
211
+ if (crossesAt instanceof Date) {
212
+ if (!dates) throw new Error(`Invalid ${name} crossing ${String(crossesAt)}. A date is only for a value axis crossing categories that are dates`);
213
+ checkDate(crossesAt);
214
+ return;
215
+ }
216
+ if (typeof crossesAt === "number" ? !Number.isFinite(crossesAt) : ![
217
+ void 0,
218
+ "auto",
219
+ "minimum",
220
+ "maximum"
221
+ ].includes(crossesAt)) throw new Error(`Invalid ${name} crossing ${crossesAt}. Expected "auto", "minimum", "maximum" or a finite number`);
222
+ if (dates && typeof crossesAt === "number") throw new Error(`Invalid ${name} crossing ${crossesAt}. The categories are dates, so expected a date`);
223
+ };
224
+ var checkAxis = (axis, name, dates = false) => {
225
+ checkTitle(axis === null || axis === void 0 ? void 0 : axis.title);
226
+ checkFont(axis === null || axis === void 0 ? void 0 : axis.font);
227
+ checkRange(axis === null || axis === void 0 ? void 0 : axis.labelRotation, `${name} label rotation`, -90, 90);
228
+ checkCrossing(axis === null || axis === void 0 ? void 0 : axis.crossesAt, name, dates);
229
+ };
230
+ var DISPLAY_UNITS = [
231
+ "hundreds",
232
+ "thousands",
233
+ "tenThousands",
234
+ "hundredThousands",
235
+ "millions",
236
+ "tenMillions",
237
+ "hundredMillions",
238
+ "billions",
239
+ "trillions"
240
+ ];
241
+ /**
242
+ * @param dates - Whether the axis crosses categories that are dates
243
+ */
244
+ var checkValueAxis = (axis, name, dates = false) => {
245
+ checkAxis(axis, name, dates);
246
+ if (axis === void 0) return;
247
+ const { minimum, maximum, interval, logarithmicBase, displayUnits } = axis;
248
+ if (displayUnits !== void 0 && !DISPLAY_UNITS.includes(displayUnits)) throw new Error(`Invalid ${name} display units "${displayUnits}". Expected one of ${DISPLAY_UNITS.join(", ")}`);
249
+ for (const [option, value] of [
250
+ ["minimum", minimum],
251
+ ["maximum", maximum],
252
+ ["interval", interval]
253
+ ]) if (value !== void 0 && !Number.isFinite(value)) throw new Error(`Invalid ${name} ${option} ${value}. Expected a finite number`);
254
+ if (minimum !== void 0 && maximum !== void 0 && !(minimum < maximum)) throw new Error(`Invalid ${name} range from ${minimum} to ${maximum}. Expected the minimum to be less than the maximum`);
255
+ if (interval !== void 0 && !(interval > 0)) throw new Error(`Invalid ${name} interval ${interval}. Expected a number greater than 0`);
256
+ checkRange(logarithmicBase, `${name} logarithmic base`, 2, 1e3);
257
+ if (logarithmicBase !== void 0) {
258
+ for (const [option, value] of [["minimum", minimum], ["maximum", maximum]]) if (value !== void 0 && !(value > 0)) throw new Error(`Invalid ${name} ${option} ${value}. A logarithmic axis' range is above 0`);
259
+ }
260
+ };
261
+ var checkValue = (value, series) => {
262
+ if (value !== null && !Number.isFinite(value)) throw new Error(`Invalid value ${quoted$1(value)} in series "${series}". Expected a finite number or null`);
263
+ };
264
+ var isGroup = (category) => typeof category === "object" && category !== null && !(category instanceof Date);
265
+ /**
266
+ * Checks groups of categories: each has a name and at least one category, holds categories or groups but not both, and
267
+ * every group at the same depth holds groups as deep.
268
+ *
269
+ * @returns How deep the groups are: 1 for groups of categories, 2 for groups of those, and so on
270
+ */
271
+ var checkGroups = (groups) => {
272
+ const depths = groups.map((group) => {
273
+ const { name, categories } = isGroup(group) ? group : {};
274
+ if (!isGroup(group) || typeof name !== "string" || !Array.isArray(categories)) throw new Error(`Invalid category group ${isGroup(group) ? JSON.stringify(group) : quoted$1(group)}. Expected { name, categories }, as every category is a group or none is`);
275
+ if (categories.length === 0) throw new Error(`Category group "${name}" has no categories`);
276
+ if (isGroup(categories[0])) return 1 + checkGroups(categories);
277
+ for (const category of categories) {
278
+ if (isGroup(category)) throw new Error(`Category group "${name}" holds categories and groups. A group holds one or the other`);
279
+ if (category instanceof Date) throw new Error(`Invalid category ${String(category)} in group "${name}". Categories in groups are text or numbers, not dates`);
280
+ if (typeof category !== "string" && !Number.isFinite(category)) throw new Error(`Invalid category ${quoted$1(category)} in group "${name}". Expected text or a finite number`);
281
+ }
282
+ return 1;
283
+ });
284
+ if (new Set(depths).size > 1) throw new Error("Invalid category groups. Every group at the same depth holds groups as deep, so every category has as many groups");
285
+ return depths[0];
286
+ };
287
+ /**
288
+ * Checks the categories: text or finite numbers, or on a chart with a category axis, all dates, or all groups.
289
+ */
290
+ var checkCategories = (categories, { dates, groups, type }) => {
291
+ if (!Array.isArray(categories)) throw new Error(`Invalid categories ${quoted$1(categories)}. Expected a list of them`);
292
+ if (categories.length === 0) throw new Error("A chart needs at least one category");
293
+ if (isCategoryGroups(categories)) {
294
+ if (!groups) throw new Error(`Invalid categories. A ${type} chart's categories can't be in groups`);
295
+ checkGroups(categories);
296
+ return;
297
+ }
298
+ const plain = categories;
299
+ if (plain.some(isGroup)) throw new Error("Invalid categories. Expected all of them to be groups, or none");
300
+ const dated = plain.filter((category) => category instanceof Date);
301
+ if (dates && dated.length > 0) {
302
+ if (dated.length < plain.length) throw new Error("Invalid categories. Expected all of them to be dates, or none");
303
+ dated.forEach(checkDate);
304
+ return;
305
+ }
306
+ for (const category of plain) if (typeof category !== "string" && !Number.isFinite(category)) throw new Error(`Invalid category ${String(category)}. Expected text or a finite number`);
307
+ };
308
+ var checkSeries = (series) => {
309
+ if (!Array.isArray(series) || series.length === 0) throw new Error("A chart needs at least one series");
310
+ };
311
+ var checkCategorySeries = ({ name, values, dataLabels }, categories) => {
312
+ if (values.length > categories) throw new Error(`Series "${name}" has ${values.length} values, but there are ${categories} categories`);
313
+ for (const value of values) checkValue(value, name);
314
+ checkDataLabels(dataLabels);
315
+ };
316
+ var checkColors = ({ name, colors }, categories) => {
317
+ if (colors && colors.length > categories) throw new Error(`Series "${name}" has ${colors.length} colors, but there are ${categories} categories`);
318
+ };
319
+ /**
320
+ * Checks how far a pie's slices are pulled out: one amount for all, or one for each slice.
321
+ */
322
+ var checkExplosion = ({ name, explosion }, categories) => {
323
+ if (explosion === void 0 || typeof explosion === "number") {
324
+ checkRange(explosion, `explosion of series "${name}"`, 0, 400);
325
+ return;
326
+ }
327
+ if (!Array.isArray(explosion)) throw new Error(`Invalid explosion ${quoted$1(explosion)} of series "${name}". Expected a percentage, or one for each slice`);
328
+ if (explosion.length > categories) throw new Error(`Series "${name}" has ${explosion.length} explosions, but there are ${categories} categories`);
329
+ for (const amount of explosion) {
330
+ if (amount !== void 0 && typeof amount !== "number") throw new Error(`Invalid explosion ${quoted$1(amount)} of series "${name}". Expected a percentage or undefined for each slice`);
331
+ checkRange(amount, `explosion of series "${name}"`, 0, 400);
332
+ }
333
+ };
334
+ var checkPieSeries = (series, categories, type) => {
335
+ checkCategorySeries(series, categories);
336
+ const negative = series.values.find((value) => value !== null && value < 0);
337
+ if (negative !== void 0) throw new Error(`Invalid value ${negative} in series "${series.name}". A ${type} chart's values can't be negative`);
338
+ checkColors(series, categories);
339
+ checkPointLabels(series, categories, "categories");
340
+ checkExplosion(series, categories);
341
+ };
342
+ /**
343
+ * Throws for an option a series has that it can't have, such as markers on a series drawn as columns.
344
+ */
345
+ var checkOptionsFor = (series, options, reason) => {
346
+ const given = options.find((option) => series[option] !== void 0);
347
+ if (given !== void 0) throw new Error(`Invalid option ${given} for series "${series.name}". ${reason}`);
348
+ };
349
+ /**
350
+ * Throws for an option a chart has that its type can't have, such as a data table on a pie chart.
351
+ */
352
+ var checkChartOptionsFor = (options, names, reason) => {
353
+ const given = names.find((option) => options[option] !== void 0);
354
+ if (given !== void 0) throw new Error(`Invalid option ${given}. ${reason}`);
355
+ };
356
+ var TRENDLINE_TYPES = [
357
+ "linear",
358
+ "exponential",
359
+ "logarithmic",
360
+ "polynomial",
361
+ "power",
362
+ "movingAverage"
363
+ ];
364
+ /**
365
+ * Checks a series' trendlines: their type, the options it has, and that the series' values are ones it can be fitted to.
366
+ */
367
+ var checkTrendlines = (series, trendlines, data) => {
368
+ if (trendlines === void 0) return;
369
+ if (!Array.isArray(trendlines)) throw new Error(`Invalid trendlines ${quoted$1(trendlines)} for series "${series}". Expected a list of them`);
370
+ for (const trendline of trendlines) {
371
+ var _trendline$label;
372
+ const { type } = trendline !== null && trendline !== void 0 ? trendline : {};
373
+ if (type === void 0 || !TRENDLINE_TYPES.includes(type)) throw new Error(`Invalid trendline type ${quoted$1(type)} for series "${series}". Expected one of ${TRENDLINE_TYPES.map((one) => `"${one}"`).join(", ")}`);
374
+ const name = `the ${type} trendline of series "${series}"`;
375
+ const invalid = (option, reason) => /* @__PURE__ */ new Error(`Invalid option ${option} for ${name}. ${reason}`);
376
+ if (type !== "polynomial" && trendline.order !== void 0) throw invalid("order", "Only a polynomial trendline has an order");
377
+ if (type !== "movingAverage" && trendline.period !== void 0) throw invalid("period", "Only a moving average has a period");
378
+ checkWholeNumber(trendline.order, `order of ${name}`, 2, 6);
379
+ if (type === "movingAverage") {
380
+ for (const option of [
381
+ "forecastForward",
382
+ "forecastBackward",
383
+ "intercept",
384
+ "equation",
385
+ "rSquared",
386
+ "label"
387
+ ]) if (trendline[option] !== void 0) throw invalid(option, "A moving average has no equation, so it has none");
388
+ const { period = 2 } = trendline;
389
+ if (!(Number.isInteger(period) && period >= 2 && period < data.length)) throw new Error(`Invalid period ${quoted$1(period)} of ${name}. Expected a whole number from 2 to one fewer than the series' ${data.length} values`);
390
+ }
391
+ for (const option of ["forecastForward", "forecastBackward"]) {
392
+ const value = trendline[option];
393
+ if (value !== void 0 && !(typeof value === "number" && value >= 0 && Number.isFinite(value))) throw new Error(`Invalid ${option} ${quoted$1(value)} of ${name}. Expected a finite number of 0 or more`);
394
+ }
395
+ if (trendline.intercept !== void 0) {
396
+ if (![
397
+ "linear",
398
+ "exponential",
399
+ "polynomial"
400
+ ].includes(type)) throw invalid("intercept", "Only linear, exponential and polynomial trendlines have one");
401
+ if (!Number.isFinite(trendline.intercept) || type === "exponential" && !(trendline.intercept > 0)) throw new Error(`Invalid intercept ${quoted$1(trendline.intercept)} of ${name}. Expected a finite number${type === "exponential" ? " above 0" : ""}`);
402
+ }
403
+ if (trendline.label !== void 0 && !trendline.equation && !trendline.rSquared) throw invalid("label", "It shows neither its equation nor its R² value");
404
+ checkFont((_trendline$label = trendline.label) === null || _trendline$label === void 0 ? void 0 : _trendline$label.font);
405
+ checkLine(trendline.line);
406
+ if (trendline.name !== void 0 && typeof trendline.name !== "string") throw new Error(`Invalid name ${quoted$1(trendline.name)} of ${name}. Expected text`);
407
+ const nonPositive = (axis) => {
408
+ var _data$find;
409
+ return (_data$find = data.find((point) => !(point[axis] > 0))) === null || _data$find === void 0 ? void 0 : _data$find[axis];
410
+ };
411
+ const needsPositive = type === "exponential" ? ["y"] : type === "power" ? ["x", "y"] : type === "logarithmic" ? ["x"] : [];
412
+ for (const axis of needsPositive) {
413
+ const value = nonPositive(axis);
414
+ if (value !== void 0) throw new Error(`Can't fit ${name} to the ${axis === "y" ? "value" : "x value"} ${value}. A ${type} trendline needs ${axis === "y" ? "values" : "x values"} above 0`);
415
+ }
416
+ }
417
+ };
418
+ var ERROR_BAR_TYPES = [
419
+ "fixed",
420
+ "percentage",
421
+ "standardDeviation",
422
+ "standardError",
423
+ "custom"
424
+ ];
425
+ /**
426
+ * Checks a series' error bars: their type and amounts, and for custom ones, no more amounts than there are points.
427
+ *
428
+ * @param which - Which error bars they are, for messages, such as "error bars" or "x error bars"
429
+ */
430
+ var checkErrorBars = (series, errorBars, count, which) => {
431
+ if (errorBars === void 0) return;
432
+ const { type } = typeof errorBars === "object" && errorBars !== null ? errorBars : {};
433
+ if (type === void 0 || !ERROR_BAR_TYPES.includes(type)) throw new Error(`Invalid ${which} type ${quoted$1(type)} for series "${series}". Expected one of ${ERROR_BAR_TYPES.map((one) => `"${one}"`).join(", ")}`);
434
+ const name = `the ${which} of series "${series}"`;
435
+ checkLine(errorBars.line);
436
+ if (errorBars.type === "custom") {
437
+ if ("direction" in errorBars && errorBars.direction !== void 0) throw new Error(`Invalid option direction for ${name}. Custom error bars go the ways their plus and minus amounts are given`);
438
+ if (errorBars.plus === void 0 && errorBars.minus === void 0) throw new Error(`Custom ${name} need plus or minus amounts, or both`);
439
+ for (const side of ["plus", "minus"]) {
440
+ const amounts = errorBars[side];
441
+ if (amounts === void 0) continue;
442
+ if (!Array.isArray(amounts)) throw new Error(`Invalid ${side} amounts ${quoted$1(amounts)} of ${name}. Expected one for each point`);
443
+ if (amounts.length > count) throw new Error(`The ${which} of series "${series}" have ${amounts.length} ${side} amounts, but there are ${count} points`);
444
+ const wrong = amounts.findIndex((amount) => amount !== null && !(typeof amount === "number" && amount >= 0 && Number.isFinite(amount)));
445
+ if (wrong !== -1) throw new Error(`Invalid ${side} amount ${quoted$1(amounts[wrong])} of ${name}. Expected a finite number of 0 or more, or null`);
446
+ }
447
+ return;
448
+ }
449
+ if (errorBars.direction !== void 0 && ![
450
+ "both",
451
+ "plus",
452
+ "minus"
453
+ ].includes(errorBars.direction)) throw new Error(`Invalid direction ${quoted$1(errorBars.direction)} of ${name}. Expected "both", "plus" or "minus"`);
454
+ const { value } = errorBars;
455
+ if (errorBars.type === "standardError") {
456
+ if (value !== void 0) throw new Error(`Invalid option value for ${name}. The standard error has no amount`);
457
+ return;
458
+ }
459
+ if (value === void 0 && errorBars.type !== "standardDeviation") throw new Error(`The ${errorBars.type} ${name} need a value`);
460
+ if (value !== void 0 && !(typeof value === "number" && value >= 0 && Number.isFinite(value))) throw new Error(`Invalid value ${quoted$1(value)} of ${name}. Expected a finite number of 0 or more`);
461
+ };
462
+ var DRAWN_AS = {
463
+ column: "columns",
464
+ bar: "bars",
465
+ line: "a line",
466
+ area: "an area"
467
+ };
468
+ /**
469
+ * The points of a series with a value for each category, numbered from 1 as a trendline numbers them. Gaps are left out.
470
+ */
471
+ var numbered = (values) => values.flatMap((value, index) => value === null ? [] : [{
472
+ x: index + 1,
473
+ y: value
474
+ }]);
475
+ /**
476
+ * Checks a series of a column, bar, line or area chart: how it's drawn, its axis, and that its options are ones the way
477
+ * it's drawn has.
478
+ *
479
+ * @param stacked - Whether the series is stacked: drawn as the chart's type, which is stacked
480
+ */
481
+ var checkComboSeries = (series, type, categories, stacked) => {
482
+ var _series$type;
483
+ checkCategorySeries(series, categories);
484
+ if (series.type !== void 0) {
485
+ if (type === "bar") throw new Error(`Invalid option type for series "${series.name}". A bar chart's series are all bars`);
486
+ if (![
487
+ "column",
488
+ "line",
489
+ "area"
490
+ ].includes(series.type)) throw new Error(`Invalid type "${series.type}" for series "${series.name}". Expected "column", "line" or "area"`);
491
+ }
492
+ if (series.axis !== void 0 && series.axis !== "primary" && series.axis !== "secondary") throw new Error(`Invalid axis "${series.axis}" for series "${series.name}". Expected "primary" or "secondary"`);
493
+ const drawnAs = (_series$type = series.type) !== null && _series$type !== void 0 ? _series$type : type;
494
+ if (drawnAs !== "line") checkOptionsFor(series, [
495
+ "markers",
496
+ "smooth",
497
+ "line"
498
+ ], `It is drawn as ${DRAWN_AS[drawnAs]}, and only a line has it`);
499
+ if (drawnAs !== "column" && drawnAs !== "bar") checkOptionsFor(series, ["colors"], `It is drawn as ${DRAWN_AS[drawnAs]}, and only bars have it`);
500
+ if (stacked && drawnAs === type) checkOptionsFor(series, ["trendlines"], "It is stacked, and a stacked series has no trendline");
501
+ checkColors(series, categories);
502
+ checkMarkers(series.markers);
503
+ checkLine(series.line);
504
+ checkPointLabels(series, categories, "categories");
505
+ checkTrendlines(series.name, series.trendlines, numbered(series.values));
506
+ checkErrorBars(series.name, series.errorBars, categories, "error bars");
507
+ };
508
+ var checkPoint = ({ x, y }, series) => {
509
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error(`Invalid point (${x}, ${y}) in series "${series}". Expected a finite x and y`);
510
+ };
511
+ var checkPoints = (series) => {
512
+ const { name, points, dataLabels } = series;
513
+ if (points.length === 0) throw new Error(`Series "${name}" has no points`);
514
+ for (const point of points) checkPoint(point, name);
515
+ checkDataLabels(dataLabels);
516
+ checkPointLabels(series, points.length, "points");
517
+ checkTrendlines(name, series.trendlines, points);
518
+ checkErrorBars(name, series.xErrorBars, points.length, "x error bars");
519
+ checkErrorBars(name, series.yErrorBars, points.length, "y error bars");
520
+ };
521
+ var checkBubbleSeries = (series) => {
522
+ checkPoints(series);
523
+ for (const { x, y, size } of series.points) if (!(size >= 0 && Number.isFinite(size))) throw new Error(`Invalid size ${size} of the bubble at (${x}, ${y}) in series "${series.name}". Expected a finite number of 0 or more`);
524
+ };
525
+ var EMPTY_VALUES$1 = [
526
+ "gap",
527
+ "zero",
528
+ "connect"
529
+ ];
530
+ /**
531
+ * Each type's name in messages, such as "pie of pie".
532
+ */
533
+ var TYPE_NAMES$1 = {
534
+ column: "column",
535
+ bar: "bar",
536
+ line: "line",
537
+ area: "area",
538
+ pie: "pie",
539
+ doughnut: "doughnut",
540
+ pieOfPie: "pie of pie",
541
+ barOfPie: "bar of pie",
542
+ radar: "radar",
543
+ scatter: "scatter",
544
+ bubble: "bubble",
545
+ stock: "stock"
546
+ };
547
+ /**
548
+ * Checks what every chart can have: its size, text, areas and legend.
549
+ */
550
+ var checkChartBase = (options) => {
551
+ if (options.transformation) checkSize$1(options.transformation);
552
+ checkTitle(options.title);
553
+ checkFont(options.font);
554
+ checkFont(options.legend ? options.legend.font : void 0);
555
+ checkArea(options.chartArea);
556
+ checkArea(options.plotArea);
557
+ const { emptyValues, dataTable } = options;
558
+ if (emptyValues !== void 0 && !EMPTY_VALUES$1.includes(emptyValues)) throw new Error(`Invalid option emptyValues ${quoted$1(emptyValues)}. Expected "gap", "zero" or "connect"`);
559
+ checkFont(typeof dataTable === "object" ? dataTable.font : void 0);
560
+ };
561
+ /**
562
+ * Checks the entries the legend hides: each is the text of an entry.
563
+ */
564
+ var checkHiddenEntries = (options) => {
565
+ const hidden = options.legend ? options.legend.hiddenEntries : void 0;
566
+ if (hidden === void 0) return;
567
+ if (!Array.isArray(hidden)) throw new Error(`Invalid hidden legend entries ${quoted$1(hidden)}. Expected a list of the entries' text`);
568
+ const entries = legendEntriesOf(options).map(({ text }) => text);
569
+ for (const entry of hidden) if (!entries.includes(String(entry))) {
570
+ const all = entries.map((one) => `"${one}"`);
571
+ throw new Error(`Invalid hidden legend entry ${quoted$1(entry)}. The legend's entries are ${all.length > 1 ? `${all.slice(0, -1).join(", ")} and ` : ""}${all[all.length - 1]}`);
572
+ }
573
+ };
574
+ /**
575
+ * Checks a pie of pie or bar of pie chart's split: the categories, value or percentage it splits the pie by.
576
+ */
577
+ var checkSplit = (split, categories) => {
578
+ if (split === void 0) return;
579
+ const { by } = typeof split === "object" && split !== null ? split : {};
580
+ switch (by) {
581
+ case "position":
582
+ checkWholeNumber(split.count, "split count", 1, categories.length);
583
+ if (split.count === void 0) throw new Error("Invalid split. Splitting by position needs the count of the last categories that go to the second plot");
584
+ return;
585
+ case "value":
586
+ case "percentage": {
587
+ const { lessThan } = split;
588
+ if (!(typeof lessThan === "number" && Number.isFinite(lessThan))) throw new Error(`Invalid split ${by === "value" ? "value" : "percentage"} ${quoted$1(lessThan)}. Expected a finite number`);
589
+ if (by === "percentage") checkRange(lessThan, "split percentage", 0, 100);
590
+ return;
591
+ }
592
+ case "categories": {
593
+ const chosen = split.categories;
594
+ if (!Array.isArray(chosen) || chosen.length === 0) throw new Error("Invalid split. Splitting by categories needs at least one category for the second plot");
595
+ const missing = chosen.find((category) => !categories.some((one) => String(one) === String(category)));
596
+ if (missing !== void 0) throw new Error(`Invalid split category ${quoted$1(missing)}. It isn't one of the chart's categories`);
597
+ return;
598
+ }
599
+ default: throw new Error(`Invalid split ${quoted$1(by)}. Expected { by: "position", "value", "percentage" or "categories", ... }`);
600
+ }
601
+ };
602
+ var checkSplitPie = (options) => {
603
+ checkChartOptionsFor(options, ["firstSliceAngle"], "A pie of pie or bar of pie chart's first slice always starts at 12 o'clock");
604
+ checkSplit(options.split, options.categories);
605
+ checkRange(options.secondPlotSize, "second plot size", 5, 200);
606
+ checkRange(options.gapWidth, "gap width", 0, 500);
607
+ checkLine(options.seriesLines);
608
+ };
609
+ /**
610
+ * Checks a stock chart: its prices and volumes, each a value for each category, with each high at least its low, and
611
+ * each open and close between them, and options that need opening prices or volumes only with them.
612
+ */
613
+ var checkStock = (options) => {
614
+ checkChartOptionsFor(options, ["series"], "A stock chart's data is its high, low and close, and its open and volume if given");
615
+ checkCategories(options.categories, {
616
+ dates: true,
617
+ groups: false,
618
+ type: "stock"
619
+ });
620
+ const count = options.categories.length;
621
+ for (const role of [
622
+ "high",
623
+ "low",
624
+ "close"
625
+ ]) if (options[role] === void 0) throw new Error(`A stock chart needs its ${role} prices`);
626
+ const series = stockSeriesOf(options);
627
+ for (const { role, name, values } of series) {
628
+ if (!Array.isArray(values)) throw new Error(`Invalid ${role} ${quoted$1(values)}. Expected a value for each category`);
629
+ if (typeof name !== "string") throw new Error(`Invalid name ${quoted$1(name)} of the ${role} series. Expected text`);
630
+ checkCategorySeries({
631
+ name,
632
+ values
633
+ }, count);
634
+ if (role === "volume") {
635
+ const negative = values.find((value) => value !== null && value < 0);
636
+ if (negative !== void 0) throw new Error(`Invalid volume ${negative}. Volumes can't be negative`);
637
+ }
638
+ }
639
+ const { open = [], high, low, close } = options;
640
+ const categories = options.categories.map((category) => category instanceof Date ? category.toISOString().slice(0, 10) : category);
641
+ for (let index = 0; index < count; index++) {
642
+ var _high$index, _low$index, _open$index, _close$index;
643
+ const [top, bottom] = [(_high$index = high[index]) !== null && _high$index !== void 0 ? _high$index : null, (_low$index = low[index]) !== null && _low$index !== void 0 ? _low$index : null];
644
+ if (top === null || bottom === null) continue;
645
+ if (top < bottom) throw new Error(`The high ${top} of ${quoted$1(categories[index])} is below its low ${bottom}`);
646
+ for (const [role, value] of [["open", (_open$index = open[index]) !== null && _open$index !== void 0 ? _open$index : null], ["close", (_close$index = close[index]) !== null && _close$index !== void 0 ? _close$index : null]]) if (value !== null && (value > top || value < bottom)) throw new Error(`The ${role} ${value} of ${quoted$1(categories[index])} isn't between its low ${bottom} and its high ${top}`);
647
+ }
648
+ if (options.open === void 0) checkChartOptionsFor(options, ["upBars", "downBars"], "The chart has no opening prices, so no bars from the open to the close");
649
+ if (options.volume === void 0) checkChartOptionsFor(options, ["volumeAxis"], "The chart has no volumes");
650
+ checkAxis(options.categoryAxis, "category axis");
651
+ checkValueAxis(options.valueAxis, "value axis");
652
+ checkValueAxis(options.volumeAxis, "volume axis");
653
+ checkLine(options.highLowLines);
654
+ checkArea(options.upBars);
655
+ checkArea(options.downBars);
656
+ };
657
+ /**
658
+ * Checks a chart's options, so mistakes show up where the chart is made.
659
+ *
660
+ * @throws If there are no series or categories, a value isn't a finite number or null, a series has more values than
661
+ * there are categories or an option its type doesn't have, a pie chart has more than one series or a pie or doughnut
662
+ * chart a negative value, a scatter or bubble point isn't finite numbers, a trendline can't be fitted to its series, a
663
+ * stock chart's high is below its low, or an option is out of its range
664
+ */
665
+ var checkChartOptions = (options) => {
666
+ checkChartBase(options);
667
+ if (options.type === "stock") {
668
+ checkStock(options);
669
+ checkHiddenEntries(options);
670
+ return;
671
+ }
672
+ checkSeries(options.series);
673
+ checkDataLabels(options.dataLabels);
674
+ const withoutDataTable = `A ${TYPE_NAMES$1[options.type]} chart has no data table. Column, bar, line, area and stock charts have one`;
675
+ if (options.type === "scatter" || options.type === "bubble") checkChartOptionsFor(options, ["emptyValues"], `A ${options.type} chart's points have no empty values`);
676
+ switch (options.type) {
677
+ case "scatter": {
678
+ checkChartOptionsFor(options, ["dataTable"], withoutDataTable);
679
+ const { lines = "none" } = options;
680
+ for (const series of options.series) {
681
+ checkPoints(series);
682
+ checkMarkers(series.markers);
683
+ checkLine(series.line);
684
+ if (lines === "none") checkOptionsFor(series, ["line"], `The chart's lines are "none"`);
685
+ }
686
+ checkMarkers(options.markers);
687
+ checkValueAxis(options.xAxis, "x axis");
688
+ checkValueAxis(options.yAxis, "y axis");
689
+ break;
690
+ }
691
+ case "bubble":
692
+ checkChartOptionsFor(options, ["dataTable"], withoutDataTable);
693
+ options.series.forEach(checkBubbleSeries);
694
+ checkRange(options.bubbleScale, "bubble scale", 0, 300);
695
+ checkValueAxis(options.xAxis, "x axis");
696
+ checkValueAxis(options.yAxis, "y axis");
697
+ break;
698
+ case "pie":
699
+ case "doughnut":
700
+ case "pieOfPie":
701
+ case "barOfPie": {
702
+ const type = TYPE_NAMES$1[options.type];
703
+ checkChartOptionsFor(options, ["dataTable"], withoutDataTable);
704
+ checkChartOptionsFor(options, ["emptyValues"], `A ${type} chart leaves out the slice of an empty value`);
705
+ checkCategories(options.categories, {
706
+ dates: false,
707
+ groups: false,
708
+ type
709
+ });
710
+ if (options.type !== "doughnut" && options.series.length > 1) throw new Error(`A ${type} chart has one series, but ${options.series.length} were given. A doughnut chart can have more`);
711
+ for (const series of options.series) {
712
+ checkPieSeries(series, options.categories.length, type);
713
+ checkOptionsFor(series, ["trendlines", "errorBars"], `A ${type} chart's series have neither`);
714
+ }
715
+ if (options.type === "pieOfPie" || options.type === "barOfPie") checkSplitPie(options);
716
+ else {
717
+ checkRange(options.firstSliceAngle, "first slice angle", 0, 360);
718
+ checkRange(options.type === "doughnut" ? options.holeSize : void 0, "hole size", 10, 90);
719
+ }
720
+ break;
721
+ }
722
+ case "radar":
723
+ checkChartOptionsFor(options, ["dataTable"], withoutDataTable);
724
+ checkCategories(options.categories, {
725
+ dates: false,
726
+ groups: false,
727
+ type: "radar"
728
+ });
729
+ for (const series of options.series) {
730
+ checkCategorySeries(series, options.categories.length);
731
+ checkMarkers(series.markers);
732
+ checkLine(series.line);
733
+ checkPointLabels(series, options.categories.length, "categories");
734
+ checkOptionsFor(series, ["trendlines", "errorBars"], "A radar chart's series have neither");
735
+ if (options.filled) checkOptionsFor(series, ["markers", "line"], "A filled radar chart's series have neither");
736
+ }
737
+ checkMarkers(options.markers);
738
+ if (options.filled && options.markers !== void 0) throw new Error("Invalid option markers. A filled radar chart's series have no markers");
739
+ checkAxis(options.categoryAxis, "category axis");
740
+ checkValueAxis(options.valueAxis, "value axis");
741
+ break;
742
+ default: {
743
+ var _options$stacking;
744
+ checkCategories(options.categories, {
745
+ dates: true,
746
+ groups: true,
747
+ type: options.type
748
+ });
749
+ const leaves = leafCategoriesOf(options.categories);
750
+ const dates = leaves.some((category) => category instanceof Date);
751
+ const stacked = ((_options$stacking = options.stacking) !== null && _options$stacking !== void 0 ? _options$stacking : "none") !== "none";
752
+ options.series.forEach((series) => checkComboSeries(series, options.type, leaves.length, stacked));
753
+ if (options.series.every(({ axis }) => axis === "secondary")) throw new Error("A chart needs at least one series on the primary axis");
754
+ checkAxis(options.categoryAxis, "category axis");
755
+ checkValueAxis(options.valueAxis, "value axis", dates);
756
+ checkValueAxis(options.secondaryValueAxis, "secondary value axis", dates);
757
+ if (options.type === "line") checkMarkers(options.markers);
758
+ if (options.type === "column" || options.type === "bar") {
759
+ checkRange(options.gapWidth, "gap width", 0, 500);
760
+ checkRange(options.overlap, "overlap", -100, 100);
761
+ }
762
+ }
763
+ }
764
+ checkHiddenEntries(options);
765
+ };
766
+ //#endregion
767
+ //#region src/charts/workbook/cell-reference.ts
768
+ /**
769
+ * References to the cells of the embedded workbook's sheet, as a chart's formulas and the sheet's cells write them.
770
+ *
771
+ * @module
772
+ */
773
+ /** The name of the workbook's only sheet, as Word names it */
774
+ var SHEET_NAME = "Sheet1";
775
+ /**
776
+ * The letters of a column, such as A for the first, Z for the 26th and AA for the 27th.
777
+ *
778
+ * @param column - The column's index, from 0
779
+ */
780
+ var columnName = (column) => (column >= 26 ? columnName(Math.floor(column / 26) - 1) : "") + String.fromCharCode(65 + column % 26);
781
+ /**
782
+ * A column's index, from 0, from its letters: 0 for A, 25 for Z and 26 for AA.
783
+ */
784
+ var columnIndexOf = (letters) => [...letters].reduce((index, letter) => index * 26 + letter.charCodeAt(0) - 64, 0) - 1;
785
+ /**
786
+ * A cell's name, such as B2.
787
+ *
788
+ * @param column - The column's index, from 0
789
+ * @param row - The row's index, from 0
790
+ */
791
+ var cellName = (column, row) => `${columnName(column)}${row + 1}`;
792
+ /**
793
+ * A formula for a cell, or for cells down a column, such as `Sheet1!$B$1` or `Sheet1!$B$2:$B$5`.
794
+ *
795
+ * @param column - The column's index, from 0
796
+ * @param firstRow - The first row's index, from 0
797
+ * @param rows - The number of rows
798
+ */
799
+ var sheetReference = (column, firstRow, rows = 1) => sheetRangeReference(column, column, firstRow, rows);
800
+ /**
801
+ * A formula for a block of cells, such as `Sheet1!$A$2:$B$9`, or for one cell.
802
+ *
803
+ * @param firstColumn - The first column's index, from 0
804
+ * @param lastColumn - The last column's index, from 0
805
+ * @param firstRow - The first row's index, from 0
806
+ * @param rows - The number of rows
807
+ */
808
+ var sheetRangeReference = (firstColumn, lastColumn, firstRow, rows = 1) => {
809
+ const first = `$${columnName(firstColumn)}$${firstRow + 1}`;
810
+ return rows === 1 && firstColumn === lastColumn ? `${SHEET_NAME}!${first}` : `${SHEET_NAME}!${first}:$${columnName(lastColumn)}$${firstRow + rows}`;
811
+ };
812
+ //#endregion
813
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
814
+ function _typeof(o) {
815
+ "@babel/helpers - typeof";
816
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
817
+ return typeof o;
818
+ } : function(o) {
819
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
820
+ }, _typeof(o);
821
+ }
822
+ //#endregion
823
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
824
+ function toPrimitive(t, r) {
825
+ if ("object" != _typeof(t) || !t) return t;
826
+ var e = t[Symbol.toPrimitive];
827
+ if (void 0 !== e) {
828
+ var i = e.call(t, r || "default");
829
+ if ("object" != _typeof(i)) return i;
830
+ throw new TypeError("@@toPrimitive must return a primitive value.");
831
+ }
832
+ return ("string" === r ? String : Number)(t);
833
+ }
834
+ //#endregion
835
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
836
+ function toPropertyKey(t) {
837
+ var i = toPrimitive(t, "string");
838
+ return "symbol" == _typeof(i) ? i : i + "";
839
+ }
840
+ //#endregion
841
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
842
+ function _defineProperty(e, r, t) {
843
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
844
+ value: t,
845
+ enumerable: !0,
846
+ configurable: !0,
847
+ writable: !0
848
+ }) : e[r] = t, e;
849
+ }
850
+ //#endregion
851
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
852
+ function ownKeys(e, r) {
853
+ var t = Object.keys(e);
854
+ if (Object.getOwnPropertySymbols) {
855
+ var o = Object.getOwnPropertySymbols(e);
856
+ r && (o = o.filter(function(r) {
857
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
858
+ })), t.push.apply(t, o);
859
+ }
860
+ return t;
861
+ }
862
+ function _objectSpread2(e) {
863
+ for (var r = 1; r < arguments.length; r++) {
864
+ var t = null != arguments[r] ? arguments[r] : {};
865
+ r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
866
+ _defineProperty(e, r, t[r]);
867
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
868
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
869
+ });
870
+ }
871
+ return e;
872
+ }
873
+ //#endregion
874
+ //#region src/charts/chart-data.ts
875
+ /**
876
+ * Lays a chart's data out as Word does in the embedded workbook's sheet: the cells, and the references to them that the
877
+ * chart's series are written with, with the values each holds. Plain data, not XML.
878
+ *
879
+ * @module
880
+ */
881
+ /** The size Word inserts a chart at: 6 by 3.5 inches */
882
+ var DEFAULT_CHART_SIZE = {
883
+ width: 576,
884
+ height: 336
885
+ };
886
+ /**
887
+ * The categories, as the sheet's first columns write them and the series refer to them: text, numbers, dates as numbers
888
+ * with a date format, or groups, a column for each level from the outermost in.
889
+ */
890
+ var createCategoryData = (categories) => {
891
+ if (isCategoryGroups(categories)) {
892
+ const rows = categoryRowsOf(categories);
893
+ const width = rows[0].length;
894
+ return {
895
+ width,
896
+ rows,
897
+ data: {
898
+ type: "levels",
899
+ formula: sheetRangeReference(0, width - 1, 1, rows.length),
900
+ count: rows.length,
901
+ levels: Array.from({ length: width }, (_, level) => rows.map((row) => {
902
+ const label = row[width - 1 - level];
903
+ return label === void 0 ? void 0 : String(label);
904
+ }))
905
+ }
906
+ };
907
+ }
908
+ const formula = sheetReference(0, 1, categories.length);
909
+ if (categories.every((category) => category instanceof Date)) {
910
+ const format = DATE_FORMATS[timeUnitOf(categories)];
911
+ const points = categories.map(serialDate);
912
+ return {
913
+ width: 1,
914
+ rows: points.map((value) => [{
915
+ value,
916
+ format
917
+ }]),
918
+ data: {
919
+ type: "number",
920
+ formula,
921
+ points,
922
+ format
923
+ }
924
+ };
925
+ }
926
+ if (categories.every((category) => typeof category === "number")) return {
927
+ width: 1,
928
+ rows: categories.map((category) => [category]),
929
+ data: {
930
+ type: "number",
931
+ formula,
932
+ points: categories
933
+ }
934
+ };
935
+ return {
936
+ width: 1,
937
+ rows: categories.map((category) => [typeof category === "number" ? category : String(category)]),
938
+ data: {
939
+ type: "text",
940
+ formula,
941
+ points: categories.map(String)
942
+ }
943
+ };
944
+ };
945
+ /**
946
+ * The columns of a series' custom error bars' amounts, with a name each, and where they are, from a column on.
947
+ */
948
+ var createErrorColumns = (errorBars, heading, rows, column) => {
949
+ if ((errorBars === null || errorBars === void 0 ? void 0 : errorBars.type) !== "custom") return { columns: [] };
950
+ const sides = [[
951
+ "plus",
952
+ "+",
953
+ errorBars.plus
954
+ ], [
955
+ "minus",
956
+ "-",
957
+ errorBars.minus
958
+ ]].flatMap(([side, sign, amounts]) => amounts === void 0 ? [] : [{
959
+ side,
960
+ sign,
961
+ amounts
962
+ }]);
963
+ const cellsOf = (amounts) => Array.from({ length: rows }, (_, row) => {
964
+ var _amounts$row;
965
+ return (_amounts$row = amounts[row]) !== null && _amounts$row !== void 0 ? _amounts$row : void 0;
966
+ });
967
+ const dataOf = (side) => {
968
+ const index = sides.findIndex((one) => one.side === side);
969
+ return index === -1 ? void 0 : {
970
+ type: "number",
971
+ formula: sheetReference(column + index, 1, rows),
972
+ points: cellsOf(sides[index].amounts)
973
+ };
974
+ };
975
+ const plus = dataOf("plus");
976
+ const minus = dataOf("minus");
977
+ return {
978
+ columns: sides.map(({ sign, amounts }) => ({
979
+ heading: `${heading} (${sign})`,
980
+ cells: cellsOf(amounts)
981
+ })),
982
+ data: _objectSpread2(_objectSpread2({}, plus === void 0 ? {} : { plus }), minus === void 0 ? {} : { minus })
983
+ };
984
+ };
985
+ /**
986
+ * The sheet with columns added on the right, their headings in row 1. The sheet has a row for every cell of theirs.
987
+ */
988
+ var withColumns = (sheet, columns) => sheet.map((row, index) => [...row, ...columns.map((column) => index === 0 ? column.heading : column.cells[index - 1])]);
989
+ /**
990
+ * Lays out a chart with categories as Word does: the series' names in row 1 after the categories' columns, the
991
+ * categories in column A from row 2, or in columns A, B and so on when they are in groups, and each series' values below
992
+ * its name. The top left cells are empty. Custom error bars' amounts are in columns after the series.
993
+ */
994
+ var createCategoryChartData = (categories, series) => {
995
+ const { width, rows, data: categoryData } = createCategoryData(categories);
996
+ const values = series.map((one) => rows.map((_, index) => {
997
+ var _one$values$index;
998
+ return (_one$values$index = one.values[index]) !== null && _one$values$index !== void 0 ? _one$values$index : void 0;
999
+ }));
1000
+ const sheet = [[...Array.from({ length: width }, () => void 0), ...series.map(({ name }) => name)], ...rows.map((category, row) => [...category, ...values.map((column) => column[row])])];
1001
+ const errors = series.reduce(({ next, all }, one) => {
1002
+ const columns = createErrorColumns(one.errorBars, one.name, rows.length, next);
1003
+ return {
1004
+ next: next + columns.columns.length,
1005
+ all: [...all, columns]
1006
+ };
1007
+ }, {
1008
+ next: width + series.length,
1009
+ all: []
1010
+ }).all;
1011
+ return {
1012
+ sheet: withColumns(sheet, errors.flatMap(({ columns }) => columns)),
1013
+ series: series.map(({ name }, index) => _objectSpread2({
1014
+ name: {
1015
+ type: "text",
1016
+ formula: sheetReference(width + index, 0),
1017
+ points: [name]
1018
+ },
1019
+ categories: categoryData,
1020
+ values: {
1021
+ type: "number",
1022
+ formula: sheetReference(width + index, 1, rows.length),
1023
+ points: values[index]
1024
+ }
1025
+ }, errors[index].data === void 0 ? {} : { errors: { y: errors[index].data } }))
1026
+ };
1027
+ };
1028
+ /**
1029
+ * Lays out a scatter or bubble chart. Word's scatter sheet shares one column of x values between its series, but each of
1030
+ * these series has points of its own, so each series has columns of its own: "X" above its x values, its name above its
1031
+ * y values, and for a bubble chart, "Size" above its sizes. Custom error bars' amounts are in columns after the series.
1032
+ */
1033
+ var createPointChartData = (series, bubbles) => {
1034
+ const width = bubbles ? 3 : 2;
1035
+ const rows = Math.max(...series.map(({ points }) => points.length));
1036
+ const sizeOf = (point) => point && "size" in point ? point.size : void 0;
1037
+ const sheet = [series.flatMap(({ name }) => bubbles ? [
1038
+ "X",
1039
+ name,
1040
+ "Size"
1041
+ ] : ["X", name]), ...Array.from({ length: rows }, (_, row) => series.flatMap(({ points }) => {
1042
+ const point = points[row];
1043
+ return bubbles ? [
1044
+ point === null || point === void 0 ? void 0 : point.x,
1045
+ point === null || point === void 0 ? void 0 : point.y,
1046
+ sizeOf(point)
1047
+ ] : [point === null || point === void 0 ? void 0 : point.x, point === null || point === void 0 ? void 0 : point.y];
1048
+ }))];
1049
+ const errors = series.reduce(({ next, all }, { name, points, xErrorBars, yErrorBars }) => {
1050
+ const x = createErrorColumns(xErrorBars, `${name} x`, points.length, next);
1051
+ const y = createErrorColumns(yErrorBars, `${name} y`, points.length, next + x.columns.length);
1052
+ return {
1053
+ next: next + x.columns.length + y.columns.length,
1054
+ all: [...all, {
1055
+ x,
1056
+ y
1057
+ }]
1058
+ };
1059
+ }, {
1060
+ next: series.length * width,
1061
+ all: []
1062
+ }).all;
1063
+ return {
1064
+ sheet: withColumns(sheet, errors.flatMap(({ x, y }) => [...x.columns, ...y.columns])),
1065
+ series: series.map(({ name, points }, index) => {
1066
+ const column = (offset, cells) => ({
1067
+ type: "number",
1068
+ formula: sheetReference(index * width + offset, 1, points.length),
1069
+ points: cells
1070
+ });
1071
+ const { x, y } = errors[index];
1072
+ const data = _objectSpread2({
1073
+ name: {
1074
+ type: "text",
1075
+ formula: sheetReference(index * width + 1, 0),
1076
+ points: [name]
1077
+ },
1078
+ categories: column(0, points.map((point) => point.x)),
1079
+ values: column(1, points.map((point) => point.y))
1080
+ }, x.data === void 0 && y.data === void 0 ? {} : { errors: _objectSpread2(_objectSpread2({}, x.data === void 0 ? {} : { x: x.data }), y.data === void 0 ? {} : { y: y.data }) });
1081
+ return bubbles ? _objectSpread2(_objectSpread2({}, data), {}, { sizes: column(2, points.map(sizeOf)) }) : data;
1082
+ })
1083
+ };
1084
+ };
1085
+ /**
1086
+ * Checks a chart's options and lays out its data.
1087
+ *
1088
+ * @throws If an option is wrong: see {@link checkChartOptions}
1089
+ */
1090
+ var createChartData = (options) => {
1091
+ checkChartOptions(options);
1092
+ switch (options.type) {
1093
+ case "scatter": return createPointChartData(options.series, false);
1094
+ case "bubble": return createPointChartData(options.series, true);
1095
+ case "stock": return createCategoryChartData(options.categories, stockSeriesOf(options));
1096
+ default: return createCategoryChartData(options.categories, options.series);
1097
+ }
1098
+ };
1099
+ //#endregion
1100
+ //#region src/charts/chart-elements.ts
1101
+ /**
1102
+ * Small builders for the elements charts are written with.
1103
+ *
1104
+ * @module
1105
+ */
1106
+ /**
1107
+ * An element with its attributes, in the order given, and its children. Undefined attributes are left out.
1108
+ */
1109
+ var createElement = (name, attributes = {}, children = []) => {
1110
+ const given = Object.entries(attributes).flatMap(([key, value]) => value === void 0 ? [] : [[key, {
1111
+ key,
1112
+ value
1113
+ }]]);
1114
+ return new BuilderElement({
1115
+ name,
1116
+ attributes: given.length === 0 ? void 0 : Object.fromEntries(given),
1117
+ children
1118
+ });
1119
+ };
1120
+ /**
1121
+ * An element whose value is its `val` attribute, such as `<c:gapWidth val="219"/>`. A boolean is written as 1 or 0, as
1122
+ * Office writes them, since Office doesn't always read a missing `val` as the schema's default.
1123
+ */
1124
+ var createValue = (name, value) => createElement(name, { val: typeof value === "boolean" ? Number(value) : value });
1125
+ /**
1126
+ * An element that holds text, such as `<c:v>Sales</c:v>`.
1127
+ */
1128
+ var createText = (name, text) => new StringContainer(name, text);
1129
+ //#endregion
1130
+ //#region src/charts/chart-color.ts
1131
+ /**
1132
+ * Colours for series, bars and slices.
1133
+ *
1134
+ * A copy of `src/shapes/preset-shape/shape-color.ts`, as `docx/charts` and `docx/shapes` are separate entries that
1135
+ * import only `docx`. Make a fix in both.
1136
+ *
1137
+ * @module
1138
+ */
1139
+ /**
1140
+ * Checks that a percentage option is between 0 and 100 and returns it.
1141
+ *
1142
+ * @throws If the value is outside 0 to 100
1143
+ */
1144
+ var percentageValue = (value, option) => {
1145
+ if (!(value >= 0 && value <= 100)) throw new Error(`Invalid ${option} ${value}. Expected a number from 0 to 100`);
1146
+ return value;
1147
+ };
1148
+ var THEME_COLOR_OOXML_NAMES = new Map(Object.entries({
1149
+ dark1: "dk1",
1150
+ light1: "lt1",
1151
+ dark2: "dk2",
1152
+ light2: "lt2",
1153
+ accent1: "accent1",
1154
+ accent2: "accent2",
1155
+ accent3: "accent3",
1156
+ accent4: "accent4",
1157
+ accent5: "accent5",
1158
+ accent6: "accent6",
1159
+ hyperlink: "hlink",
1160
+ followedHyperlink: "folHlink"
1161
+ }));
1162
+ var THEME_COLOR_SUGGESTIONS = new Map([
1163
+ ...[...THEME_COLOR_OOXML_NAMES].map(([name, ooxml]) => [ooxml, name]),
1164
+ ["text1", "dark1"],
1165
+ ["background1", "light1"],
1166
+ ["text2", "dark2"],
1167
+ ["background2", "light2"]
1168
+ ]);
1169
+ var createColorChange = ({ name, value }) => new BuilderElement({
1170
+ name,
1171
+ attributes: { value: {
1172
+ key: "val",
1173
+ value
1174
+ } }
1175
+ });
1176
+ /**
1177
+ * How a theme colour is made lighter or darker, as Word does it: by scaling its luminance (`lumMod`), and for a lighter
1178
+ * colour, adding to it (`lumOff`). Both are in thousandths of a percent.
1179
+ */
1180
+ var themeColorChanges = ({ lighter, darker }) => {
1181
+ if (lighter !== void 0 && darker !== void 0) throw new Error("Invalid theme colour. Expected lighter or darker, not both");
1182
+ if (lighter !== void 0) {
1183
+ const amount = percentageValue(lighter, "lighter");
1184
+ return [{
1185
+ name: "a:lumMod",
1186
+ value: Math.round((100 - amount) * 1e3)
1187
+ }, {
1188
+ name: "a:lumOff",
1189
+ value: Math.round(amount * 1e3)
1190
+ }];
1191
+ }
1192
+ return darker === void 0 ? [] : [{
1193
+ name: "a:lumMod",
1194
+ value: Math.round((100 - percentageValue(darker, "darker")) * 1e3)
1195
+ }];
1196
+ };
1197
+ var createThemeColor = (color, changes) => {
1198
+ const name = THEME_COLOR_OOXML_NAMES.get(color.theme);
1199
+ if (name === void 0) {
1200
+ const suggestion = THEME_COLOR_SUGGESTIONS.get(color.theme);
1201
+ throw new Error(`Invalid theme colour "${color.theme}". ${suggestion ? `Did you mean "${suggestion}"?` : `Expected one of ${[...THEME_COLOR_OOXML_NAMES.keys()].join(", ")}`}`);
1202
+ }
1203
+ return new BuilderElement({
1204
+ name: "a:schemeClr",
1205
+ attributes: { value: {
1206
+ key: "val",
1207
+ value: name
1208
+ } },
1209
+ children: [...themeColorChanges(color), ...changes].map(createColorChange)
1210
+ });
1211
+ };
1212
+ /**
1213
+ * Creates an `a:srgbClr` element from a hex colour, or an `a:schemeClr` element from a colour of the document's theme,
1214
+ * with an optional transparency.
1215
+ *
1216
+ * ## XSD Schema
1217
+ * ```xml
1218
+ * <xsd:complexType name="CT_SRgbColor">
1219
+ * <xsd:sequence>
1220
+ * <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
1221
+ * </xsd:sequence>
1222
+ * <xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
1223
+ * </xsd:complexType>
1224
+ *
1225
+ * <xsd:complexType name="CT_SchemeColor">
1226
+ * <xsd:sequence>
1227
+ * <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
1228
+ * </xsd:sequence>
1229
+ * <xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
1230
+ * </xsd:complexType>
1231
+ * ```
1232
+ *
1233
+ * @param color - A 6-digit hex colour such as `"FF0000"` or `"#FF0000"`, or a colour of the document's theme
1234
+ * @param transparency - From 0 (opaque) to 100 (invisible)
1235
+ * @throws If the colour is not a 6-digit hex value or a colour of the theme, or a percentage is outside 0 to 100
1236
+ *
1237
+ * @example
1238
+ * ```typescript
1239
+ * createChartColor("1F4E79", 25); // <a:srgbClr val="1F4E79"><a:alpha val="75000"/></a:srgbClr>
1240
+ * createChartColor({ theme: "accent1", darker: 25 }); // <a:schemeClr val="accent1"><a:lumMod val="75000"/></a:schemeClr>
1241
+ * ```
1242
+ */
1243
+ var createChartColor = (color, transparency) => {
1244
+ const changes = transparency ? [{
1245
+ name: "a:alpha",
1246
+ value: Math.round((100 - percentageValue(transparency, "transparency")) * 1e3)
1247
+ }] : [];
1248
+ if (typeof color !== "string") return createThemeColor(color, changes);
1249
+ if (color === "auto") throw new Error(`Invalid chart color 'auto'. Expected 6 digit hex value`);
1250
+ return new BuilderElement({
1251
+ name: "a:srgbClr",
1252
+ attributes: { value: {
1253
+ key: "val",
1254
+ value: hexColorValue(color)
1255
+ } },
1256
+ children: changes.map(createColorChange)
1257
+ });
1258
+ };
1259
+ //#endregion
1260
+ //#region src/charts/chart-style.ts
1261
+ var EMUS_PER_POINT = 12700;
1262
+ /**
1263
+ * A colour of the chart's theme, by the name Office's chart styles use (`tx1` for text, `bg1` for the background), as a
1264
+ * percentage of the way from the background to it: text at 65% is `tx1` with its luminance scaled to 65% and 35% added.
1265
+ */
1266
+ var createSchemeColor = (name, changes = []) => createElement("a:schemeClr", { val: name }, changes.map((change) => createValue(change.name, change.value)));
1267
+ var textColor = (percent) => createSchemeColor("tx1", [{
1268
+ name: "a:lumMod",
1269
+ value: percent * 1e3
1270
+ }, {
1271
+ name: "a:lumOff",
1272
+ value: (100 - percent) * 1e3
1273
+ }]);
1274
+ var ACCENT_VARIATIONS = [
1275
+ [],
1276
+ [{
1277
+ name: "a:lumMod",
1278
+ value: 6e4
1279
+ }],
1280
+ [{
1281
+ name: "a:lumMod",
1282
+ value: 8e4
1283
+ }, {
1284
+ name: "a:lumOff",
1285
+ value: 2e4
1286
+ }],
1287
+ [{
1288
+ name: "a:lumMod",
1289
+ value: 8e4
1290
+ }],
1291
+ [{
1292
+ name: "a:lumMod",
1293
+ value: 6e4
1294
+ }, {
1295
+ name: "a:lumOff",
1296
+ value: 4e4
1297
+ }],
1298
+ [{
1299
+ name: "a:lumMod",
1300
+ value: 5e4
1301
+ }],
1302
+ [{
1303
+ name: "a:lumMod",
1304
+ value: 7e4
1305
+ }, {
1306
+ name: "a:lumOff",
1307
+ value: 3e4
1308
+ }],
1309
+ [{
1310
+ name: "a:lumMod",
1311
+ value: 7e4
1312
+ }],
1313
+ [{
1314
+ name: "a:lumMod",
1315
+ value: 5e4
1316
+ }, {
1317
+ name: "a:lumOff",
1318
+ value: 5e4
1319
+ }]
1320
+ ];
1321
+ var LINE_DASH_OOXML_NAMES = {
1322
+ solid: "solid",
1323
+ dot: "dot",
1324
+ dash: "dash",
1325
+ longDash: "lgDash",
1326
+ dashDot: "dashDot",
1327
+ longDashDot: "lgDashDot",
1328
+ longDashDotDot: "lgDashDotDot",
1329
+ shortDash: "sysDash",
1330
+ shortDot: "sysDot",
1331
+ shortDashDot: "sysDashDot",
1332
+ shortDashDotDot: "sysDashDotDot"
1333
+ };
1334
+ var MARKER_SHAPES = [
1335
+ "circle",
1336
+ "square",
1337
+ "diamond",
1338
+ "triangle",
1339
+ "x",
1340
+ "star",
1341
+ "plus",
1342
+ "dash",
1343
+ "dot"
1344
+ ];
1345
+ /**
1346
+ * The colour of a series, or of a slice of a pie: the theme's accents 1 to 6, then the six again, darker or lighter, as
1347
+ * Office colours them. After 54 the colours repeat.
1348
+ *
1349
+ * @param index - The series' or slice's index, from 0
1350
+ * @param color - A colour given for it, which is used instead
1351
+ * @param transparency - From 0 (opaque) to 100 (invisible), as Office draws bubbles at 25%
1352
+ */
1353
+ var createSeriesColor = (index, color, transparency) => color === void 0 ? createSchemeColor(`accent${index % 6 + 1}`, [...ACCENT_VARIATIONS[Math.floor(index / 6) % ACCENT_VARIATIONS.length], ...transparency ? [{
1354
+ name: "a:alpha",
1355
+ value: (100 - transparency) * 1e3
1356
+ }] : []]) : createChartColor(color, transparency);
1357
+ var createSolidFill = (color) => createElement("a:solidFill", {}, [color]);
1358
+ var createNoFill = () => createElement("a:noFill");
1359
+ var createEffects = () => createElement("a:effectLst");
1360
+ var createDash = (dash) => {
1361
+ const name = LINE_DASH_OOXML_NAMES[dash];
1362
+ if (name === void 0) throw new Error(`Invalid line dash "${dash}". Expected one of ${Object.keys(LINE_DASH_OOXML_NAMES).join(", ")}`);
1363
+ return createValue("a:prstDash", name);
1364
+ };
1365
+ var createLine = ({ width, color, round, axis, dash }) => {
1366
+ const w = width === void 0 ? void 0 : Math.round(width * EMUS_PER_POINT);
1367
+ return createElement("a:ln", axis ? {
1368
+ w,
1369
+ cap: "flat",
1370
+ cmpd: "sng",
1371
+ algn: "ctr"
1372
+ } : {
1373
+ w,
1374
+ cap: round ? "rnd" : void 0
1375
+ }, [
1376
+ color ? createSolidFill(color) : createNoFill(),
1377
+ ...color && dash ? [createDash(dash)] : [],
1378
+ ...round || axis ? [createElement("a:round")] : []
1379
+ ]);
1380
+ };
1381
+ /**
1382
+ * Shape properties (`c:spPr`): an optional fill and a line, then no effects, as Office writes them.
1383
+ */
1384
+ var createShapeProperties = (fill, line) => createElement("c:spPr", {}, [
1385
+ ...fill ? [fill] : [],
1386
+ line,
1387
+ createEffects()
1388
+ ]);
1389
+ /**
1390
+ * No fill and no line, for titles, the legend and data labels.
1391
+ */
1392
+ var createNoShapeProperties = () => createShapeProperties(createNoFill(), createLine({}));
1393
+ /**
1394
+ * A border given as options, over a default width and colour.
1395
+ */
1396
+ var createBorder = (border, defaultColor) => {
1397
+ var _border$width;
1398
+ return createLine({
1399
+ width: (_border$width = border.width) !== null && _border$width !== void 0 ? _border$width : .75,
1400
+ color: border.color === void 0 ? defaultColor : createChartColor(border.color),
1401
+ dash: border.dash,
1402
+ axis: true
1403
+ });
1404
+ };
1405
+ var createAreaFill = (fill, defaultFill) => {
1406
+ if (fill === "none") return createNoFill();
1407
+ return fill === void 0 ? defaultFill : createSolidFill(createChartColor(fill));
1408
+ };
1409
+ /**
1410
+ * The chart area: filled with the background colour, with a thin light grey border, or as given.
1411
+ */
1412
+ var createChartAreaProperties = ({ fill, border } = {}) => createShapeProperties(createAreaFill(fill, createSolidFill(createSchemeColor("bg1"))), border === "none" ? createLine({}) : createBorder(border !== null && border !== void 0 ? border : {}, textColor(15)));
1413
+ /**
1414
+ * The plot area: no fill and no border, or as given.
1415
+ */
1416
+ var createPlotAreaProperties = ({ fill, border } = {}) => createShapeProperties(createAreaFill(fill, createNoFill()), border === void 0 || border === "none" ? createLine({}) : createBorder(border, textColor(15)));
1417
+ /**
1418
+ * A bar, column, area or slice of a series: a solid fill and no line.
1419
+ */
1420
+ var createFilledSeriesProperties = (color) => createShapeProperties(createSolidFill(color), createLine({}));
1421
+ /**
1422
+ * A slice of a pie or doughnut: a solid fill, with a border in the background colour between it and the next slice.
1423
+ */
1424
+ var createSliceProperties = (color) => createShapeProperties(createSolidFill(color), createLine({
1425
+ width: 1.5,
1426
+ color: createSchemeColor("lt1")
1427
+ }));
1428
+ /**
1429
+ * A series' line, over its default width, with round ends: 2.25 points for a line or radar series, and 1.5 for a
1430
+ * scatter series.
1431
+ *
1432
+ * @param color - The series' colour, which the line has unless it has a colour of its own
1433
+ */
1434
+ var createSeriesLine = (color, width, line = {}) => {
1435
+ var _line$width;
1436
+ return createLine({
1437
+ width: (_line$width = line.width) !== null && _line$width !== void 0 ? _line$width : width,
1438
+ color: line.color === void 0 ? color : createChartColor(line.color),
1439
+ dash: line.dash,
1440
+ round: true
1441
+ });
1442
+ };
1443
+ /**
1444
+ * The line of a line or radar chart's series, 2.25 points wide with round ends, or as given.
1445
+ */
1446
+ var createLineSeriesProperties = (color, line) => createShapeProperties(void 0, createSeriesLine(color, 2.25, line));
1447
+ /**
1448
+ * The line of a scatter chart's series, 1.5 points wide with round ends, or as given, or none.
1449
+ */
1450
+ var createScatterSeriesProperties = (color, line) => createShapeProperties(void 0, color ? createSeriesLine(color, 1.5, line) : createLine({
1451
+ width: 2,
1452
+ round: true
1453
+ }));
1454
+ /**
1455
+ * A bubble chart's series: bubbles filled with the series' colour at 75% opacity, with no line, as Office draws them.
1456
+ */
1457
+ var createBubbleSeriesProperties = (index, color) => createShapeProperties(createSolidFill(createSeriesColor(index, color, 25)), createLine({}));
1458
+ /**
1459
+ * A marker (`c:marker`): a circle of size 5, or the shape and size given, filled with the series' colour with a thin
1460
+ * outline in it, or none.
1461
+ *
1462
+ * @param seriesColor - Creates the series' colour, or undefined for no marker
1463
+ */
1464
+ var createMarker = (seriesColor, { shape = "circle", size = 5 } = {}) => {
1465
+ if (!seriesColor) return createElement("c:marker", {}, [createValue("c:symbol", "none")]);
1466
+ if (!MARKER_SHAPES.includes(shape)) throw new Error(`Invalid marker shape "${shape}". Expected one of ${MARKER_SHAPES.join(", ")}`);
1467
+ return createElement("c:marker", {}, [
1468
+ createValue("c:symbol", shape),
1469
+ createValue("c:size", Math.round(size)),
1470
+ createShapeProperties(createSolidFill(seriesColor()), createLine({
1471
+ width: .75,
1472
+ color: seriesColor()
1473
+ }))
1474
+ ]);
1475
+ };
1476
+ /**
1477
+ * A trendline: 1.5 points wide with round ends, in short dots of the series' colour, as Office draws them, or as given.
1478
+ *
1479
+ * @param color - The series' colour
1480
+ */
1481
+ var createTrendlineProperties = (color, line = {}) => {
1482
+ var _line$width2, _line$dash;
1483
+ return createShapeProperties(void 0, createLine({
1484
+ width: (_line$width2 = line.width) !== null && _line$width2 !== void 0 ? _line$width2 : 1.5,
1485
+ color: line.color === void 0 ? color : createChartColor(line.color),
1486
+ dash: (_line$dash = line.dash) !== null && _line$dash !== void 0 ? _line$dash : "shortDot",
1487
+ round: true
1488
+ }));
1489
+ };
1490
+ /**
1491
+ * A line drawn between a chart's points or plots, such as error bars, a stock chart's high-low lines, or the lines
1492
+ * joining a pie to its second plot: 0.75 points wide, with flat ends, a percentage of the way from the background to the
1493
+ * text colour, or as given.
1494
+ *
1495
+ * @param percent - How far from the background to the text colour the line is, from 0 to 100
1496
+ */
1497
+ var createChartLinesProperties = (line = {}, percent) => createShapeProperties(void 0, createBorder(line, textColor(percent)));
1498
+ /**
1499
+ * Error bars: dark grey lines 0.75 points wide, as Office draws them, or as given.
1500
+ */
1501
+ var createErrorBarsProperties = (line) => createShapeProperties(createNoFill(), createBorder(line !== null && line !== void 0 ? line : {}, textColor(65)));
1502
+ /**
1503
+ * The bars of a stock chart from each open to each close, as Office draws them: white where the price rose, and dark
1504
+ * grey where it fell, each with a thin grey border, or as given.
1505
+ *
1506
+ * @param rising - Whether they are the bars where the price rose
1507
+ */
1508
+ var createUpDownBarProperties = ({ fill, border } = {}, rising) => createShapeProperties(createAreaFill(fill, createSolidFill(rising ? createSchemeColor("lt1") : textColor(65))), border === "none" ? createLine({}) : createBorder(border !== null && border !== void 0 ? border : {}, textColor(65)));
1509
+ /**
1510
+ * The closing price of a stock chart without opening prices: a short dash across its high-low line, in its colour.
1511
+ */
1512
+ var createCloseMarker = () => {
1513
+ const color = () => textColor(75);
1514
+ return createElement("c:marker", {}, [
1515
+ createValue("c:symbol", "dash"),
1516
+ createValue("c:size", 7),
1517
+ createShapeProperties(createSolidFill(color()), createLine({
1518
+ width: .75,
1519
+ color: color()
1520
+ }))
1521
+ ]);
1522
+ };
1523
+ /**
1524
+ * A series drawn only by what joins its points, such as a stock chart's prices: no line.
1525
+ */
1526
+ var createHiddenSeriesProperties = () => createShapeProperties(void 0, createLine({
1527
+ width: 1.5,
1528
+ round: true
1529
+ }));
1530
+ /**
1531
+ * The data table: no fill, with light grey borders, as Office draws it.
1532
+ */
1533
+ var createDataTableProperties = () => createShapeProperties(createNoFill(), createBorder({}, textColor(15)));
1534
+ /**
1535
+ * Gridlines, or the line of an axis: 0.75 points wide, 15% of the way from the background to the text colour, or 25%
1536
+ * for a scatter chart's axes.
1537
+ */
1538
+ var createAxisLine = (percent = 15) => createLine({
1539
+ width: .75,
1540
+ color: textColor(percent),
1541
+ axis: true
1542
+ });
1543
+ /**
1544
+ * An axis' shape properties: no fill, and its line.
1545
+ */
1546
+ var createAxisProperties = (line) => createShapeProperties(createNoFill(), line !== null && line !== void 0 ? line : createLine({}));
1547
+ /**
1548
+ * Gridlines (`c:majorGridlines`).
1549
+ */
1550
+ var createGridlines = () => createElement("c:majorGridlines", {}, [createShapeProperties(void 0, createAxisLine())]);
1551
+ /**
1552
+ * The text body's properties (`a:bodyPr`), as Office writes them for a chart's text.
1553
+ */
1554
+ var createBodyProperties = ({ rotation = -6e7, labelMargins }) => createElement("a:bodyPr", _objectSpread2(_objectSpread2({
1555
+ rot: rotation,
1556
+ spcFirstLastPara: 1,
1557
+ vertOverflow: "ellipsis",
1558
+ vert: "horz",
1559
+ wrap: "square"
1560
+ }, labelMargins ? {
1561
+ lIns: 38100,
1562
+ tIns: 19050,
1563
+ rIns: 38100,
1564
+ bIns: 19050
1565
+ } : {}), {}, {
1566
+ anchor: "ctr",
1567
+ anchorCtr: 1
1568
+ }), labelMargins ? [createElement("a:spAutoFit")] : []);
1569
+ /**
1570
+ * The paragraph properties of a chart's text (`a:pPr` with `a:defRPr`): the theme's body font, in grey, or the font
1571
+ * given. A typeface given is for Latin and complex scripts, as Office sets it, and East Asian text keeps the theme's.
1572
+ */
1573
+ var createParagraphProperties = ({ size, color = 65, spacing, font = {} }) => {
1574
+ var _font$size, _font$bold, _font$italics, _font$name, _font$name2;
1575
+ return createElement("a:pPr", {}, [createElement("a:defRPr", {
1576
+ sz: Math.round(((_font$size = font.size) !== null && _font$size !== void 0 ? _font$size : size) * 100),
1577
+ b: Number((_font$bold = font.bold) !== null && _font$bold !== void 0 ? _font$bold : false),
1578
+ i: Number((_font$italics = font.italics) !== null && _font$italics !== void 0 ? _font$italics : false),
1579
+ u: "none",
1580
+ strike: "noStrike",
1581
+ kern: 1200,
1582
+ spc: spacing ? 0 : void 0,
1583
+ baseline: 0
1584
+ }, [
1585
+ createSolidFill(font.color === void 0 ? textColor(color) : createChartColor(font.color)),
1586
+ createElement("a:latin", { typeface: (_font$name = font.name) !== null && _font$name !== void 0 ? _font$name : "+mn-lt" }),
1587
+ createElement("a:ea", { typeface: "+mn-ea" }),
1588
+ createElement("a:cs", { typeface: (_font$name2 = font.name) !== null && _font$name2 !== void 0 ? _font$name2 : "+mn-cs" })
1589
+ ])]);
1590
+ };
1591
+ /**
1592
+ * The text properties (`c:txPr`) of an axis, the legend, a title or data labels.
1593
+ */
1594
+ var createTextProperties = (options) => createElement("c:txPr", {}, [
1595
+ createBodyProperties(options),
1596
+ createElement("a:lstStyle"),
1597
+ createElement("a:p", {}, [createParagraphProperties(options), createElement("a:endParaRPr", { lang: "en-US" })])
1598
+ ]);
1599
+ /**
1600
+ * The chart's own text properties, which Office writes empty.
1601
+ */
1602
+ var createChartTextProperties = () => createElement("c:txPr", {}, [
1603
+ createElement("a:bodyPr"),
1604
+ createElement("a:lstStyle"),
1605
+ createElement("a:p", {}, [createElement("a:pPr", {}, [createElement("a:defRPr")]), createElement("a:endParaRPr", { lang: "en-US" })])
1606
+ ]);
1607
+ //#endregion
1608
+ //#region src/charts/chart-text.ts
1609
+ /**
1610
+ * The font of a piece of the chart's text: its own, over the chart's.
1611
+ */
1612
+ var fontOf = (chartFont, font) => chartFont === void 0 ? font : _objectSpread2(_objectSpread2({}, chartFont), font);
1613
+ /**
1614
+ * A title given as text, or as text with a font.
1615
+ */
1616
+ var titleOf$1 = (title) => typeof title === "string" ? { text: title } : title;
1617
+ /**
1618
+ * A title, as Office writes a chart's or an axis' title: its text, not over the plot, with no fill or line. Each line of
1619
+ * the text is a paragraph.
1620
+ *
1621
+ * ## XSD Schema
1622
+ * ```xml
1623
+ * <xsd:complexType name="CT_Title">
1624
+ * <xsd:sequence>
1625
+ * <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
1626
+ * <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
1627
+ * <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
1628
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
1629
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
1630
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1631
+ * </xsd:sequence>
1632
+ * </xsd:complexType>
1633
+ * ```
1634
+ */
1635
+ var createTitle = (title, options) => {
1636
+ var _options$rotation;
1637
+ const { text, font } = titleOf$1(title);
1638
+ const textOptions = _objectSpread2(_objectSpread2({}, options), {}, {
1639
+ rotation: (_options$rotation = options.rotation) !== null && _options$rotation !== void 0 ? _options$rotation : 0,
1640
+ font: fontOf(options.font, font)
1641
+ });
1642
+ return createElement("c:title", {}, [
1643
+ createRichText(text, textOptions),
1644
+ createValue("c:overlay", false),
1645
+ createNoShapeProperties(),
1646
+ createTextProperties(textOptions)
1647
+ ]);
1648
+ };
1649
+ /**
1650
+ * Text of a title's or label's own (`c:tx` with `c:rich`), each line a paragraph, in the look given.
1651
+ *
1652
+ * ## XSD Schema
1653
+ * ```xml
1654
+ * <xsd:complexType name="CT_Tx">
1655
+ * <xsd:sequence>
1656
+ * <xsd:choice minOccurs="1" maxOccurs="1">
1657
+ * <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/>
1658
+ * <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/>
1659
+ * </xsd:choice>
1660
+ * </xsd:sequence>
1661
+ * </xsd:complexType>
1662
+ * ```
1663
+ */
1664
+ var createRichText = (text, options) => createElement("c:tx", {}, [createElement("c:rich", {}, [
1665
+ createBodyProperties(options),
1666
+ createElement("a:lstStyle"),
1667
+ ...text.split("\n").map((line) => createElement("a:p", {}, [createParagraphProperties(options), createElement("a:r", {}, [createElement("a:rPr", { lang: "en-US" }), createText("a:t", line)])]))
1668
+ ])]);
1669
+ /**
1670
+ * A chart's title, in 14 point text above the plot.
1671
+ */
1672
+ var createChartTitle = (title, font) => createTitle(title, {
1673
+ size: 14,
1674
+ spacing: true,
1675
+ font
1676
+ });
1677
+ /**
1678
+ * An axis' title, in 10 point text. A vertical axis' title reads from bottom to top.
1679
+ */
1680
+ var createAxisTitle = (title, vertical, font) => createTitle(title, {
1681
+ size: 10,
1682
+ rotation: vertical ? -54e5 : 0,
1683
+ font
1684
+ });
1685
+ var TYPE_NAMES = {
1686
+ column: "Column",
1687
+ bar: "Bar",
1688
+ line: "Line",
1689
+ area: "Area",
1690
+ pie: "Pie",
1691
+ doughnut: "Doughnut",
1692
+ pieOfPie: "Pie of pie",
1693
+ barOfPie: "Bar of pie",
1694
+ radar: "Radar",
1695
+ scatter: "Scatter",
1696
+ bubble: "Bubble",
1697
+ stock: "Stock"
1698
+ };
1699
+ var MONTHS = [
1700
+ "Jan",
1701
+ "Feb",
1702
+ "Mar",
1703
+ "Apr",
1704
+ "May",
1705
+ "Jun",
1706
+ "Jul",
1707
+ "Aug",
1708
+ "Sep",
1709
+ "Oct",
1710
+ "Nov",
1711
+ "Dec"
1712
+ ];
1713
+ /**
1714
+ * A date as the axis labels it by default, in UTC, as the chart reads it: "3 Jan 2025", "Jan 2025" or "2025", by the
1715
+ * unit the dates are spaced by.
1716
+ */
1717
+ var dateText = (date, unit) => {
1718
+ const year = String(date.getUTCFullYear());
1719
+ const month = `${MONTHS[date.getUTCMonth()]} ${year}`;
1720
+ switch (unit) {
1721
+ case "years": return year;
1722
+ case "months": return month;
1723
+ default: return `${date.getUTCDate()} ${month}`;
1724
+ }
1725
+ };
1726
+ /**
1727
+ * The categories as a screen reader reads them. A category in groups is read with its groups, such as "2025 Q1".
1728
+ */
1729
+ var categoryTexts = (categories) => {
1730
+ if (isCategoryGroups(categories)) return groupedCategoryLabelsOf(categories);
1731
+ const unit = timeUnitOf(categories.filter((category) => category instanceof Date));
1732
+ return categories.map((category) => category instanceof Date ? dateText(category, unit) : String(category));
1733
+ };
1734
+ var listOf = (name, items) => `${name}: ${items.length === 0 ? "no values" : items.join(", ")}.`;
1735
+ /**
1736
+ * A sentence for each series: its name, then each category's value, or each point. Gaps are left out.
1737
+ */
1738
+ var describeSeries = (options) => {
1739
+ switch (options.type) {
1740
+ case "scatter": return options.series.map(({ name, points }) => listOf(name, points.map(({ x, y }) => `(${x}, ${y})`)));
1741
+ case "bubble": return options.series.map(({ name, points }) => listOf(name, points.map(({ x, y, size }) => `(${x}, ${y}) size ${size}`)));
1742
+ default: {
1743
+ const categories = categoryTexts(options.categories);
1744
+ return (options.type === "stock" ? stockSeriesOf(options) : options.series).map(({ name, values }) => listOf(name, values.flatMap((value, index) => value === null ? [] : [`${categories[index]} ${value}`])));
1745
+ }
1746
+ }
1747
+ };
1748
+ /**
1749
+ * Cuts a description that is too long at the end of the last value that fits, or in a title too long to fit, and ends
1750
+ * it with an ellipsis.
1751
+ *
1752
+ * @param heading - The length of the chart's type and title, which start the description
1753
+ */
1754
+ var limitLength = (description, heading) => {
1755
+ if (description.length <= 1e3) return description;
1756
+ const start = description.slice(0, 999);
1757
+ const end = Math.max(start.lastIndexOf(", "), start.lastIndexOf(". "));
1758
+ return `${end >= heading ? start.slice(0, end) : start}…`;
1759
+ };
1760
+ /**
1761
+ * Describes a chart: its type and title, then each series' values, such as "Column chart, Sales. 2024: Jan 10, Feb 20,
1762
+ * Mar 30. 2025: Jan 15, Feb 25." It is at most {@link MAX_DESCRIPTION_LENGTH} characters long.
1763
+ */
1764
+ var describeChart = (options) => {
1765
+ const title = options.title === void 0 ? "" : titleOf$1(options.title).text.replace(/\s+/g, " ").trim();
1766
+ const heading = `${TYPE_NAMES[options.type]} chart${title ? `, ${title}` : ""}.`;
1767
+ return limitLength([heading, ...describeSeries(options)].join(" "), heading.length);
1768
+ };
1769
+ /**
1770
+ * The chart's alternative text: its own, with a description of the chart when it has none and isn't decorative.
1771
+ */
1772
+ var chartAltText = (options) => {
1773
+ const { altText, decorative } = options;
1774
+ if (decorative || (altText === null || altText === void 0 ? void 0 : altText.description)) return altText;
1775
+ const description = describeChart(options);
1776
+ return altText ? _objectSpread2(_objectSpread2({}, altText), {}, { description }) : {
1777
+ name: "",
1778
+ description,
1779
+ title: ""
1780
+ };
1781
+ };
1782
+ //#endregion
1783
+ //#region src/charts/chart-reference.ts
1784
+ /**
1785
+ * Elements that refer to a part of the package, and add it to the package when they are written.
1786
+ *
1787
+ * @module
1788
+ */
1789
+ /**
1790
+ * An element that refers to a part of the package by its relationship id (`r:id`), and adds the part, and the
1791
+ * relationship to it, when it is written: a chart in the document (`c:chart`), or the workbook of a chart
1792
+ * (`c:externalData`).
1793
+ */
1794
+ var PartReference = class extends XmlComponent {
1795
+ constructor(name, part, { namespaces = {}, children = [] } = {}) {
1796
+ super(name);
1797
+ _defineProperty(this, "part", void 0);
1798
+ this.part = part;
1799
+ this.root.push(new NextAttributeComponent(_objectSpread2(_objectSpread2({}, Object.fromEntries(Object.entries(namespaces).map(([prefix, uri]) => [prefix, {
1800
+ key: `xmlns:${prefix}`,
1801
+ value: uri
1802
+ }]))), {}, { id: {
1803
+ key: "r:id",
1804
+ value: part.relationshipId
1805
+ } })), ...children);
1806
+ }
1807
+ prepForXml(context) {
1808
+ this.part.addTo(context);
1809
+ return super.prepForXml(context);
1810
+ }
1811
+ };
1812
+ //#endregion
1813
+ //#region src/charts/plot-area/series.ts
1814
+ /**
1815
+ * A number as the chart's caches and the sheet's cells write it: JavaScript's shortest form that reads back as the same
1816
+ * number.
1817
+ */
1818
+ var formatNumber = (value) => String(value);
1819
+ /**
1820
+ * A reference to text (`c:strRef`) with its cache (`c:strCache`), from which applications draw the chart without
1821
+ * opening the workbook.
1822
+ *
1823
+ * ## XSD Schema
1824
+ * ```xml
1825
+ * <xsd:complexType name="CT_StrRef">
1826
+ * <xsd:sequence>
1827
+ * <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
1828
+ * <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/>
1829
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1830
+ * </xsd:sequence>
1831
+ * </xsd:complexType>
1832
+ * ```
1833
+ */
1834
+ var createTextReference = ({ formula, points }) => createElement("c:strRef", {}, [createText("c:f", formula), createElement("c:strCache", {}, [createValue("c:ptCount", points.length), ...points.map((point, index) => createElement("c:pt", { idx: index }, [createText("c:v", point)]))])]);
1835
+ /**
1836
+ * A reference to numbers (`c:numRef`) with its cache (`c:numCache`), in the cells' number format. The cache leaves out
1837
+ * empty cells, so they are gaps, and counts every cell.
1838
+ *
1839
+ * ## XSD Schema
1840
+ * ```xml
1841
+ * <xsd:complexType name="CT_NumRef">
1842
+ * <xsd:sequence>
1843
+ * <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
1844
+ * <xsd:element name="numCache" type="CT_NumData" minOccurs="0" maxOccurs="1"/>
1845
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1846
+ * </xsd:sequence>
1847
+ * </xsd:complexType>
1848
+ * ```
1849
+ */
1850
+ var createNumberReference = ({ formula, points, format = "General" }) => createElement("c:numRef", {}, [createText("c:f", formula), createElement("c:numCache", {}, [
1851
+ createText("c:formatCode", format),
1852
+ createValue("c:ptCount", points.length),
1853
+ ...points.flatMap((point, index) => point === void 0 ? [] : [createElement("c:pt", { idx: index }, [createText("c:v", formatNumber(point))])])
1854
+ ])]);
1855
+ /**
1856
+ * A reference to categories in groups (`c:multiLvlStrRef`), with its cache: a level of labels (`c:lvl`) for the
1857
+ * categories, then one for each level of their groups, out to the outermost. A group's label is at its first category.
1858
+ *
1859
+ * ## XSD Schema
1860
+ * ```xml
1861
+ * <xsd:complexType name="CT_MultiLvlStrRef">
1862
+ * <xsd:sequence>
1863
+ * <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/>
1864
+ * <xsd:element name="multiLvlStrCache" type="CT_MultiLvlStrData" minOccurs="0" maxOccurs="1"/>
1865
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1866
+ * </xsd:sequence>
1867
+ * </xsd:complexType>
1868
+ *
1869
+ * <xsd:complexType name="CT_MultiLvlStrData">
1870
+ * <xsd:sequence>
1871
+ * <xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/>
1872
+ * <xsd:element name="lvl" type="CT_Lvl" minOccurs="0" maxOccurs="unbounded"/>
1873
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
1874
+ * </xsd:sequence>
1875
+ * </xsd:complexType>
1876
+ * ```
1877
+ */
1878
+ var createLevelsReference = ({ formula, count, levels }) => createElement("c:multiLvlStrRef", {}, [createText("c:f", formula), createElement("c:multiLvlStrCache", {}, [createValue("c:ptCount", count), ...levels.map((level) => createElement("c:lvl", {}, level.flatMap((label, index) => label === void 0 ? [] : [createElement("c:pt", { idx: index }, [createText("c:v", label)])])))])]);
1879
+ /**
1880
+ * A series' data (`c:cat`, `c:val`, `c:xVal`, `c:yVal`, `c:bubbleSize`, or an error bar's `c:plus` or `c:minus`): a
1881
+ * reference to text, numbers, or categories in groups.
1882
+ */
1883
+ var createDataSource = (name, data) => {
1884
+ switch (data.type) {
1885
+ case "text": return createElement(name, {}, [createTextReference(data)]);
1886
+ case "levels": return createElement(name, {}, [createLevelsReference(data)]);
1887
+ default: return createElement(name, {}, [createNumberReference(data)]);
1888
+ }
1889
+ };
1890
+ /**
1891
+ * A series' name (`c:tx`): a reference to the cell it is in.
1892
+ */
1893
+ var createSeriesName = (name) => createElement("c:tx", {}, [createTextReference(name)]);
1894
+ /**
1895
+ * The start of a series (`c:ser`): its index and order, both unique in the chart, and its name (`c:tx`).
1896
+ *
1897
+ * ## XSD Schema
1898
+ * ```xml
1899
+ * <xsd:group name="EG_SerShared">
1900
+ * <xsd:sequence>
1901
+ * <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/>
1902
+ * <xsd:element name="order" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/>
1903
+ * <xsd:element name="tx" type="CT_SerTx" minOccurs="0" maxOccurs="1"/>
1904
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
1905
+ * </xsd:sequence>
1906
+ * </xsd:group>
1907
+ * ```
1908
+ */
1909
+ var createSeriesStart = (index, data) => [
1910
+ createValue("c:idx", index),
1911
+ createValue("c:order", index),
1912
+ createSeriesName(data.name)
1913
+ ];
1914
+ /**
1915
+ * A series' categories and values (`c:cat` and `c:val`).
1916
+ */
1917
+ var createCategoriesAndValues = (data) => [createDataSource("c:cat", data.categories), createDataSource("c:val", data.values)];
1918
+ //#endregion
1919
+ //#region src/charts/plot-area/axes.ts
1920
+ /** The primary axes, which every chart with axes has */
1921
+ var PRIMARY_AXES = {
1922
+ category: 1,
1923
+ value: 2
1924
+ };
1925
+ /** The secondary axes: a value axis on the right, and a hidden category axis for it to cross */
1926
+ var SECONDARY_AXES = {
1927
+ category: 3,
1928
+ value: 4
1929
+ };
1930
+ var CROSSINGS = {
1931
+ auto: "autoZero",
1932
+ minimum: "min",
1933
+ maximum: "max"
1934
+ };
1935
+ var isVertical = (position) => position === "l" || position === "r";
1936
+ /**
1937
+ * The start of every axis (`EG_AxShared`), up to its title. The schema puts the logarithmic base first, and the maximum
1938
+ * before the minimum.
1939
+ */
1940
+ var createAxisStart = ({ id, position, font }, { title, visible = true, reverseOrder = false }, { logarithmicBase, maximum, minimum }, gridlines) => [
1941
+ createValue("c:axId", id),
1942
+ createElement("c:scaling", {}, [
1943
+ ...logarithmicBase === void 0 ? [] : [createValue("c:logBase", formatNumber(logarithmicBase))],
1944
+ createValue("c:orientation", reverseOrder ? "maxMin" : "minMax"),
1945
+ ...maximum === void 0 ? [] : [createValue("c:max", maximum)],
1946
+ ...minimum === void 0 ? [] : [createValue("c:min", minimum)]
1947
+ ]),
1948
+ createValue("c:delete", !visible),
1949
+ createValue("c:axPos", position),
1950
+ ...gridlines ? [createGridlines()] : [],
1951
+ ...title === void 0 ? [] : [createAxisTitle(title, isVertical(position), font)]
1952
+ ];
1953
+ /**
1954
+ * Where an axis crosses the other: a place on it (`c:crosses`), or a value (`c:crossesAt`), which for a 100% stacked
1955
+ * chart's values is a fraction of 1, and for a date axis, a date's serial number.
1956
+ */
1957
+ var createCrossing = (crossesAt, percent) => {
1958
+ if (crossesAt instanceof Date) return createValue("c:crossesAt", formatNumber(serialDate(crossesAt)));
1959
+ return typeof crossesAt === "number" ? createValue("c:crossesAt", formatNumber(percent ? crossesAt / 100 : crossesAt)) : createValue("c:crosses", CROSSINGS[crossesAt]);
1960
+ };
1961
+ /**
1962
+ * The end of every axis (`EG_AxShared`), after its number format: no tick marks, labels next to the axis in 9 point
1963
+ * text, turned as asked or as Office chooses, and where it crosses the other axis.
1964
+ */
1965
+ var createAxisEnd = (placement, axis, line) => {
1966
+ var _ref, _axis$crossesAt, _placement$crossesPer;
1967
+ return [
1968
+ createValue("c:majorTickMark", placement.radar ? "cross" : "none"),
1969
+ createValue("c:minorTickMark", "none"),
1970
+ createValue("c:tickLblPos", "nextTo"),
1971
+ createAxisProperties(line),
1972
+ createTextProperties({
1973
+ size: 9,
1974
+ rotation: axis.labelRotation === void 0 ? void 0 : Math.round(axis.labelRotation * 6e4),
1975
+ font: fontOf(placement.font, axis.font)
1976
+ }),
1977
+ createValue("c:crossAx", placement.crossAxisId),
1978
+ createCrossing((_ref = (_axis$crossesAt = axis.crossesAt) !== null && _axis$crossesAt !== void 0 ? _axis$crossesAt : placement.crosses) !== null && _ref !== void 0 ? _ref : "auto", (_placement$crossesPer = placement.crossesPercent) !== null && _placement$crossesPer !== void 0 ? _placement$crossesPer : false)
1979
+ ];
1980
+ };
1981
+ /**
1982
+ * The labels' number format: the one given, written as it is, or the sheet's (`sourceLinked`).
1983
+ */
1984
+ var createNumberFormat = (given, linked) => given === void 0 ? createElement("c:numFmt", {
1985
+ formatCode: linked,
1986
+ sourceLinked: 1
1987
+ }) : createElement("c:numFmt", {
1988
+ formatCode: given,
1989
+ sourceLinked: 0
1990
+ });
1991
+ /**
1992
+ * A category axis, with a line, and gridlines if asked for. Categories that are dates are on a date axis, which spaces
1993
+ * them by date, as Excel does when a chart's categories are dates.
1994
+ *
1995
+ * ## XSD Schema
1996
+ * ```xml
1997
+ * <xsd:complexType name="CT_CatAx">
1998
+ * <xsd:sequence>
1999
+ * <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
2000
+ * <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2001
+ * <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/>
2002
+ * <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
2003
+ * <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
2004
+ * <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/>
2005
+ * <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2006
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2007
+ * </xsd:sequence>
2008
+ * </xsd:complexType>
2009
+ *
2010
+ * <xsd:complexType name="CT_DateAx">
2011
+ * <xsd:sequence>
2012
+ * <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
2013
+ * <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2014
+ * <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/>
2015
+ * <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/>
2016
+ * ...
2017
+ * </xsd:sequence>
2018
+ * </xsd:complexType>
2019
+ * ```
2020
+ *
2021
+ * @param dates - The categories' dates, when they are dates
2022
+ * @param byDate - Whether dates are spaced by date, on a date axis, or evenly, one for each category, on a text axis
2023
+ */
2024
+ var createCategoryAxis = (placement, axis = {}, dates, byDate = true) => {
2025
+ var _ref2, _axis$gridlines, _dates$format;
2026
+ const start = createAxisStart(placement, axis, {}, (_ref2 = (_axis$gridlines = axis.gridlines) !== null && _axis$gridlines !== void 0 ? _axis$gridlines : placement.radar) !== null && _ref2 !== void 0 ? _ref2 : false);
2027
+ const end = createAxisEnd(placement, axis, createAxisLine());
2028
+ return dates && byDate ? createElement("c:dateAx", {}, [
2029
+ ...start,
2030
+ createNumberFormat(axis.numberFormat, dates.format),
2031
+ ...end,
2032
+ createValue("c:auto", true),
2033
+ createValue("c:lblOffset", 100),
2034
+ createValue("c:baseTimeUnit", dates.unit)
2035
+ ]) : createElement("c:catAx", {}, [
2036
+ ...start,
2037
+ createNumberFormat(axis.numberFormat, (_dates$format = dates === null || dates === void 0 ? void 0 : dates.format) !== null && _dates$format !== void 0 ? _dates$format : "General"),
2038
+ ...end,
2039
+ createValue("c:auto", dates === void 0),
2040
+ createValue("c:lblAlgn", "ctr"),
2041
+ createValue("c:lblOffset", 100),
2042
+ createValue("c:noMultiLvlLbl", false)
2043
+ ]);
2044
+ };
2045
+ /**
2046
+ * The units a value axis' labels are in, with the label that names them ("Thousands"), which Office writes, beside the
2047
+ * axis.
2048
+ *
2049
+ * ## XSD Schema
2050
+ * ```xml
2051
+ * <xsd:complexType name="CT_DispUnits">
2052
+ * <xsd:sequence>
2053
+ * <xsd:choice>
2054
+ * <xsd:element name="custUnit" type="CT_Double" minOccurs="1" maxOccurs="1"/>
2055
+ * <xsd:element name="builtInUnit" type="CT_BuiltInUnit" minOccurs="1" maxOccurs="1"/>
2056
+ * </xsd:choice>
2057
+ * <xsd:element name="dispUnitsLbl" type="CT_DispUnitsLbl" minOccurs="0" maxOccurs="1"/>
2058
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2059
+ * </xsd:sequence>
2060
+ * </xsd:complexType>
2061
+ * ```
2062
+ */
2063
+ var createDisplayUnits = (units, vertical, font) => createElement("c:dispUnits", {}, [createValue("c:builtInUnit", units), createElement("c:dispUnitsLbl", {}, [
2064
+ createElement("c:layout"),
2065
+ createNoShapeProperties(),
2066
+ createTextProperties({
2067
+ size: 9,
2068
+ rotation: vertical ? -54e5 : 0,
2069
+ font
2070
+ })
2071
+ ])]);
2072
+ /**
2073
+ * A value axis, with gridlines unless asked not to. Its range and interval are written as given, or for a 100% stacked
2074
+ * chart, as fractions of 1.
2075
+ *
2076
+ * ## XSD Schema
2077
+ * ```xml
2078
+ * <xsd:complexType name="CT_ValAx">
2079
+ * <xsd:sequence>
2080
+ * <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
2081
+ * <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/>
2082
+ * <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
2083
+ * <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/>
2084
+ * <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/>
2085
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2086
+ * </xsd:sequence>
2087
+ * </xsd:complexType>
2088
+ * ```
2089
+ */
2090
+ var createValueAxis = (placement, axis = {}) => {
2091
+ var _ref3, _axis$gridlines2;
2092
+ const { crossBetween, percent, scatter, radar } = placement;
2093
+ const { minimum, maximum, interval, numberFormat, logarithmicBase, displayUnits } = axis;
2094
+ const scale = (value) => formatNumber(percent ? value / 100 : value);
2095
+ return createElement("c:valAx", {}, [
2096
+ ...createAxisStart(placement, axis, {
2097
+ logarithmicBase,
2098
+ maximum: maximum === void 0 ? void 0 : scale(maximum),
2099
+ minimum: minimum === void 0 ? void 0 : scale(minimum)
2100
+ }, (_ref3 = (_axis$gridlines2 = axis.gridlines) !== null && _axis$gridlines2 !== void 0 ? _axis$gridlines2 : placement.gridlines) !== null && _ref3 !== void 0 ? _ref3 : true),
2101
+ createNumberFormat(numberFormat, percent ? "0%" : "General"),
2102
+ ...createAxisEnd(placement, axis, scatter ? createAxisLine(25) : radar ? createAxisLine() : void 0),
2103
+ createValue("c:crossBetween", crossBetween),
2104
+ ...interval === void 0 ? [] : [createValue("c:majorUnit", scale(interval))],
2105
+ ...displayUnits === void 0 ? [] : [createDisplayUnits(displayUnits, isVertical(placement.position), fontOf(placement.font, axis.font))]
2106
+ ]);
2107
+ };
2108
+ /**
2109
+ * A scatter or bubble chart's axes: two value axes, the x axis along the bottom and the y axis on the left, each with
2110
+ * gridlines and a line of its own.
2111
+ */
2112
+ var createPointAxes = (options, font) => [createValueAxis({
2113
+ id: PRIMARY_AXES.category,
2114
+ crossAxisId: PRIMARY_AXES.value,
2115
+ position: "b",
2116
+ crossBetween: "midCat",
2117
+ scatter: true,
2118
+ font
2119
+ }, options.xAxis), createValueAxis({
2120
+ id: PRIMARY_AXES.value,
2121
+ crossAxisId: PRIMARY_AXES.category,
2122
+ position: "l",
2123
+ crossBetween: "midCat",
2124
+ scatter: true,
2125
+ font
2126
+ }, options.yAxis)];
2127
+ //#endregion
2128
+ //#region src/charts/plot-area/chart-group.ts
2129
+ /**
2130
+ * How line and area charts' series are grouped (`ST_Grouping`). Bar charts call `"none"` `clustered`.
2131
+ */
2132
+ var GROUPINGS = {
2133
+ none: "standard",
2134
+ stacked: "stacked",
2135
+ percent: "percentStacked"
2136
+ };
2137
+ /**
2138
+ * A series' labels: its own, or the chart's.
2139
+ */
2140
+ var labelsOf = (own, chart) => own === void 0 ? chart : own;
2141
+ /**
2142
+ * The series of a chart, each with its index and data.
2143
+ */
2144
+ var groupSeries = (series, data) => series.map((options, index) => ({
2145
+ index,
2146
+ options,
2147
+ data: data[index]
2148
+ }));
2149
+ //#endregion
2150
+ //#region src/charts/plot-area/data-labels.ts
2151
+ var BESIDE_POINTS = [
2152
+ "center",
2153
+ "left",
2154
+ "right",
2155
+ "above",
2156
+ "below"
2157
+ ];
2158
+ var LABEL_PLACEMENTS = {
2159
+ bars: {
2160
+ default: "outsideEnd",
2161
+ allowed: [
2162
+ "center",
2163
+ "insideEnd",
2164
+ "insideBase",
2165
+ "outsideEnd"
2166
+ ],
2167
+ name: "bars"
2168
+ },
2169
+ stackedBars: {
2170
+ default: "center",
2171
+ allowed: [
2172
+ "center",
2173
+ "insideEnd",
2174
+ "insideBase"
2175
+ ],
2176
+ name: "stacked bars"
2177
+ },
2178
+ line: {
2179
+ default: "right",
2180
+ allowed: BESIDE_POINTS,
2181
+ name: "a line"
2182
+ },
2183
+ points: {
2184
+ default: "right",
2185
+ allowed: BESIDE_POINTS,
2186
+ name: "points"
2187
+ },
2188
+ pie: {
2189
+ default: "bestFit",
2190
+ allowed: [
2191
+ "center",
2192
+ "insideEnd",
2193
+ "outsideEnd",
2194
+ "bestFit"
2195
+ ],
2196
+ name: "a pie"
2197
+ },
2198
+ area: {
2199
+ allowed: [],
2200
+ name: "an area"
2201
+ },
2202
+ doughnut: {
2203
+ allowed: [],
2204
+ name: "a doughnut"
2205
+ },
2206
+ radar: {
2207
+ allowed: [],
2208
+ name: "a radar chart"
2209
+ }
2210
+ };
2211
+ var POSITION_OOXML_NAMES = {
2212
+ center: "ctr",
2213
+ insideEnd: "inEnd",
2214
+ insideBase: "inBase",
2215
+ outsideEnd: "outEnd",
2216
+ left: "l",
2217
+ right: "r",
2218
+ above: "t",
2219
+ below: "b",
2220
+ bestFit: "bestFit"
2221
+ };
2222
+ /**
2223
+ * Where a series' labels go: the position given, or Office's.
2224
+ *
2225
+ * @throws If the position given isn't one the labelled shape can have
2226
+ */
2227
+ var positionOf = (position, shape, series) => {
2228
+ const placement = LABEL_PLACEMENTS[shape];
2229
+ if (position === void 0) return placement.default && POSITION_OOXML_NAMES[placement.default];
2230
+ if (placement.allowed.length === 0) throw new Error(`Invalid data label position "${position}" for series "${series}". Labels on ${placement.name} have no position`);
2231
+ if (!placement.allowed.includes(position)) {
2232
+ const allowed = placement.allowed.map((one) => `"${one}"`);
2233
+ throw new Error(`Invalid data label position "${position}" for series "${series}". Labels on ${placement.name} can be at ${allowed.slice(0, -1).join(", ")} or ${allowed[allowed.length - 1]}`);
2234
+ }
2235
+ return POSITION_OOXML_NAMES[position];
2236
+ };
2237
+ var SHOWN = [
2238
+ "value",
2239
+ "category",
2240
+ "seriesName",
2241
+ "percentage",
2242
+ "bubbleSize"
2243
+ ];
2244
+ var showsSomething = (labels) => SHOWN.some((option) => labels[option]);
2245
+ var createShown = ({ value, category, seriesName, percentage, bubbleSize }, leaderLines) => [
2246
+ createValue("c:showLegendKey", false),
2247
+ createValue("c:showVal", value !== null && value !== void 0 ? value : false),
2248
+ createValue("c:showCatName", category !== null && category !== void 0 ? category : false),
2249
+ createValue("c:showSerName", seriesName !== null && seriesName !== void 0 ? seriesName : false),
2250
+ createValue("c:showPercent", percentage !== null && percentage !== void 0 ? percentage : false),
2251
+ createValue("c:showBubbleSize", bubbleSize !== null && bubbleSize !== void 0 ? bubbleSize : false),
2252
+ ...leaderLines ? [createValue("c:showLeaderLines", true)] : []
2253
+ ];
2254
+ /**
2255
+ * How labels look (`EG_DLblShared`): their number format, no fill or line, 9 point text, their position and what they
2256
+ * show.
2257
+ *
2258
+ * @throws If the labels' position isn't one the labelled shape can have
2259
+ */
2260
+ var createLabelLook = (labels, { shape, series, font }) => {
2261
+ const position = positionOf(labels.position, shape, series);
2262
+ return [
2263
+ ...labels.numberFormat === void 0 ? [] : [createElement("c:numFmt", {
2264
+ formatCode: labels.numberFormat,
2265
+ sourceLinked: 0
2266
+ })],
2267
+ createNoShapeProperties(),
2268
+ createTextProperties(labelTextOptions(labels, font)),
2269
+ ...position ? [createValue("c:dLblPos", position)] : []
2270
+ ];
2271
+ };
2272
+ var labelTextOptions = (labels, font) => ({
2273
+ size: 9,
2274
+ color: 75,
2275
+ rotation: 0,
2276
+ labelMargins: true,
2277
+ font: fontOf(font, labels.font)
2278
+ });
2279
+ /**
2280
+ * The label of one point (`c:dLbl`), over its series' labels: its own text, or what it shows, and its position, number
2281
+ * format and font, or its series'. A point whose series' labels show something, and whose own shows nothing, has its
2282
+ * label deleted.
2283
+ *
2284
+ * ## XSD Schema
2285
+ * ```xml
2286
+ * <xsd:complexType name="CT_DLbl">
2287
+ * <xsd:sequence>
2288
+ * <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/>
2289
+ * <xsd:choice>
2290
+ * <xsd:element name="delete" type="CT_Boolean" minOccurs="1" maxOccurs="1"/>
2291
+ * <xsd:group ref="Group_DLbl" minOccurs="1" maxOccurs="1"/>
2292
+ * </xsd:choice>
2293
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2294
+ * </xsd:sequence>
2295
+ * </xsd:complexType>
2296
+ *
2297
+ * <xsd:group name="Group_DLbl">
2298
+ * <xsd:sequence>
2299
+ * <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
2300
+ * <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
2301
+ * <xsd:group ref="EG_DLblShared" minOccurs="1" maxOccurs="1"/>
2302
+ * </xsd:sequence>
2303
+ * </xsd:group>
2304
+ * ```
2305
+ */
2306
+ var createPointLabel = (point, index, labels, options) => {
2307
+ var _own$position, _own$numberFormat, _own$font;
2308
+ if (point === void 0 || point === false && labels === void 0) return [];
2309
+ const own = point === false ? {} : point;
2310
+ const ownShows = own.text !== void 0 || SHOWN.some((option) => own[option] !== void 0);
2311
+ const merged = _objectSpread2(_objectSpread2({}, ownShows ? {} : labels), {}, {
2312
+ position: (_own$position = own.position) !== null && _own$position !== void 0 ? _own$position : labels === null || labels === void 0 ? void 0 : labels.position,
2313
+ numberFormat: (_own$numberFormat = own.numberFormat) !== null && _own$numberFormat !== void 0 ? _own$numberFormat : labels === null || labels === void 0 ? void 0 : labels.numberFormat,
2314
+ font: (_own$font = own.font) !== null && _own$font !== void 0 ? _own$font : labels === null || labels === void 0 ? void 0 : labels.font
2315
+ }, ownShows ? Object.fromEntries(SHOWN.map((option) => [option, own[option]])) : {});
2316
+ if (point === false || own.text === void 0 && !showsSomething(merged)) return labels === void 0 ? [] : [createElement("c:dLbl", {}, [createValue("c:idx", index), createValue("c:delete", true)])];
2317
+ return [createElement("c:dLbl", {}, [createValue("c:idx", index), ...own.text === void 0 ? [...createLabelLook(merged, options), ...createShown(merged)] : [
2318
+ createRichText(own.text, _objectSpread2(_objectSpread2({}, labelTextOptions(merged, options.font)), {}, { rotation: 0 })),
2319
+ ...createLabelLook(merged, options),
2320
+ ...createShown({ value: true })
2321
+ ]])];
2322
+ };
2323
+ /**
2324
+ * A series' labels, in 9 point text, and the labels of its single points, or none when neither shows anything. A number
2325
+ * format given is written as it is, not linked to the sheet's.
2326
+ *
2327
+ * ## XSD Schema
2328
+ * ```xml
2329
+ * <xsd:complexType name="CT_DLbls">
2330
+ * <xsd:sequence>
2331
+ * <xsd:element name="dLbl" type="CT_DLbl" minOccurs="0" maxOccurs="unbounded"/>
2332
+ * <xsd:choice>
2333
+ * <xsd:element name="delete" type="CT_Boolean" minOccurs="1" maxOccurs="1"/>
2334
+ * <xsd:group ref="Group_DLbls" minOccurs="1" maxOccurs="1"/>
2335
+ * </xsd:choice>
2336
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2337
+ * </xsd:sequence>
2338
+ * </xsd:complexType>
2339
+ *
2340
+ * <xsd:group name="EG_DLblShared">
2341
+ * <xsd:sequence>
2342
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
2343
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2344
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
2345
+ * <xsd:element name="dLblPos" type="CT_DLblPos" minOccurs="0" maxOccurs="1"/>
2346
+ * <xsd:element name="showLegendKey" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2347
+ * <xsd:element name="showVal" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2348
+ * <xsd:element name="showCatName" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2349
+ * <xsd:element name="showSerName" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2350
+ * <xsd:element name="showPercent" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2351
+ * <xsd:element name="showBubbleSize" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2352
+ * <xsd:element name="separator" type="xsd:string" minOccurs="0" maxOccurs="1"/>
2353
+ * </xsd:sequence>
2354
+ * </xsd:group>
2355
+ * ```
2356
+ *
2357
+ * @throws If a position isn't one the labelled shape can have
2358
+ */
2359
+ var createSeriesDataLabels = (labels, options) => {
2360
+ var _options$pointLabels;
2361
+ const shown = labels && showsSomething(labels) ? labels : void 0;
2362
+ const points = ((_options$pointLabels = options.pointLabels) !== null && _options$pointLabels !== void 0 ? _options$pointLabels : []).flatMap((point, index) => createPointLabel(point, index, shown, options));
2363
+ if (shown === void 0 && points.length === 0) return [];
2364
+ return [createElement("c:dLbls", {}, [...points, ...shown === void 0 ? createShown({}, options.leaderLines) : [...createLabelLook(shown, options), ...createShown(shown, options.leaderLines)]])];
2365
+ };
2366
+ /**
2367
+ * A chart group's labels, which show nothing, as Word writes them. Each series' own labels come first.
2368
+ */
2369
+ var createGroupDataLabels = (leaderLines) => createElement("c:dLbls", {}, createShown({}, leaderLines));
2370
+ //#endregion
2371
+ //#region src/charts/plot-area/error-bars.ts
2372
+ var VALUE_TYPES = {
2373
+ fixed: "fixedVal",
2374
+ percentage: "percentage",
2375
+ standardDeviation: "stdDev",
2376
+ standardError: "stdErr",
2377
+ custom: "cust"
2378
+ };
2379
+ /**
2380
+ * Which way custom error bars go: the ways their amounts are given.
2381
+ */
2382
+ var customDirectionOf = ({ plus, minus }) => {
2383
+ if (plus !== void 0 && minus !== void 0) return "both";
2384
+ return plus === void 0 ? "minus" : "plus";
2385
+ };
2386
+ /**
2387
+ * Error bars, as Office writes them: in a direction, which is `y` for a chart with categories, whichever way its bars
2388
+ * go, as Excel has it, with end caps unless asked not to. A custom one's amounts are references to its cells.
2389
+ *
2390
+ * ## XSD Schema
2391
+ * ```xml
2392
+ * <xsd:complexType name="CT_ErrBars">
2393
+ * <xsd:sequence>
2394
+ * <xsd:element name="errDir" type="CT_ErrDir" minOccurs="0" maxOccurs="1"/>
2395
+ * <xsd:element name="errBarType" type="CT_ErrBarType" minOccurs="1" maxOccurs="1"/>
2396
+ * <xsd:element name="errValType" type="CT_ErrValType" minOccurs="1" maxOccurs="1"/>
2397
+ * <xsd:element name="noEndCap" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2398
+ * <xsd:element name="plus" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2399
+ * <xsd:element name="minus" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2400
+ * <xsd:element name="val" type="CT_Double" minOccurs="0" maxOccurs="1"/>
2401
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2402
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2403
+ * </xsd:sequence>
2404
+ * </xsd:complexType>
2405
+ * ```
2406
+ *
2407
+ * @param direction - The axis the bars go along
2408
+ * @param data - Where custom error bars' amounts are in the sheet
2409
+ */
2410
+ var createErrorBars = (errorBars, direction, data) => {
2411
+ var _errorBars$value, _errorBars$direction, _errorBars$endCaps;
2412
+ if (errorBars === void 0) return [];
2413
+ const custom = errorBars.type === "custom" ? data : void 0;
2414
+ const value = errorBars.type === "standardDeviation" ? (_errorBars$value = errorBars.value) !== null && _errorBars$value !== void 0 ? _errorBars$value : 1 : "value" in errorBars ? errorBars.value : void 0;
2415
+ return [createElement("c:errBars", {}, [
2416
+ createValue("c:errDir", direction),
2417
+ createValue("c:errBarType", errorBars.type === "custom" ? customDirectionOf(custom) : (_errorBars$direction = errorBars.direction) !== null && _errorBars$direction !== void 0 ? _errorBars$direction : "both"),
2418
+ createValue("c:errValType", VALUE_TYPES[errorBars.type]),
2419
+ createValue("c:noEndCap", !((_errorBars$endCaps = errorBars.endCaps) !== null && _errorBars$endCaps !== void 0 ? _errorBars$endCaps : true)),
2420
+ ...(custom === null || custom === void 0 ? void 0 : custom.plus) ? [createDataSource("c:plus", custom.plus)] : [],
2421
+ ...(custom === null || custom === void 0 ? void 0 : custom.minus) ? [createDataSource("c:minus", custom.minus)] : [],
2422
+ ...value === void 0 ? [] : [createValue("c:val", formatNumber(value))],
2423
+ createErrorBarsProperties(errorBars.line)
2424
+ ])];
2425
+ };
2426
+ //#endregion
2427
+ //#region src/charts/plot-area/trendline.ts
2428
+ var TRENDLINE_OOXML_NAMES = {
2429
+ linear: "linear",
2430
+ exponential: "exp",
2431
+ logarithmic: "log",
2432
+ polynomial: "poly",
2433
+ power: "power",
2434
+ movingAverage: "movingAvg"
2435
+ };
2436
+ /**
2437
+ * The label of a trendline's equation and R² value, in 9 point text, as Office writes it.
2438
+ *
2439
+ * ## XSD Schema
2440
+ * ```xml
2441
+ * <xsd:complexType name="CT_TrendlineLbl">
2442
+ * <xsd:sequence>
2443
+ * <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
2444
+ * <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/>
2445
+ * <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/>
2446
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2447
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
2448
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2449
+ * </xsd:sequence>
2450
+ * </xsd:complexType>
2451
+ * ```
2452
+ */
2453
+ var createTrendlineLabel = ({ label = {} }, font) => {
2454
+ var _label$numberFormat;
2455
+ return createElement("c:trendlineLbl", {}, [
2456
+ createElement("c:layout"),
2457
+ createElement("c:numFmt", {
2458
+ formatCode: (_label$numberFormat = label.numberFormat) !== null && _label$numberFormat !== void 0 ? _label$numberFormat : "General",
2459
+ sourceLinked: 0
2460
+ }),
2461
+ createNoShapeProperties(),
2462
+ createTextProperties({
2463
+ size: 9,
2464
+ rotation: 0,
2465
+ font: fontOf(font, label.font)
2466
+ })
2467
+ ]);
2468
+ };
2469
+ /**
2470
+ * A series' trendlines, each a dotted line in the series' colour, with its equation and R² value if asked for. A
2471
+ * trendline without a name of its own is named in the legend by the application, as Office names it, such as "Linear
2472
+ * (Sales)", in its own language.
2473
+ *
2474
+ * ## XSD Schema
2475
+ * ```xml
2476
+ * <xsd:complexType name="CT_Trendline">
2477
+ * <xsd:sequence>
2478
+ * <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1"/>
2479
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
2480
+ * <xsd:element name="trendlineType" type="CT_TrendlineType" minOccurs="1" maxOccurs="1"/>
2481
+ * <xsd:element name="order" type="CT_Order" minOccurs="0" maxOccurs="1"/>
2482
+ * <xsd:element name="period" type="CT_Period" minOccurs="0" maxOccurs="1"/>
2483
+ * <xsd:element name="forward" type="CT_Double" minOccurs="0" maxOccurs="1"/>
2484
+ * <xsd:element name="backward" type="CT_Double" minOccurs="0" maxOccurs="1"/>
2485
+ * <xsd:element name="intercept" type="CT_Double" minOccurs="0" maxOccurs="1"/>
2486
+ * <xsd:element name="dispRSqr" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2487
+ * <xsd:element name="dispEq" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2488
+ * <xsd:element name="trendlineLbl" type="CT_TrendlineLbl" minOccurs="0" maxOccurs="1"/>
2489
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2490
+ * </xsd:sequence>
2491
+ * </xsd:complexType>
2492
+ * ```
2493
+ *
2494
+ * @param seriesColor - Creates the series' colour
2495
+ * @param font - The chart's font
2496
+ */
2497
+ var createTrendlines = (trendlines = [], seriesColor, font) => trendlines.map((trendline) => {
2498
+ var _trendline$order, _trendline$period;
2499
+ const { type, name, forecastForward, forecastBackward, intercept, equation = false, rSquared = false } = trendline;
2500
+ const numbers = [
2501
+ ["c:forward", forecastForward],
2502
+ ["c:backward", forecastBackward],
2503
+ ["c:intercept", intercept]
2504
+ ];
2505
+ return createElement("c:trendline", {}, [
2506
+ ...name === void 0 ? [] : [createText("c:name", name)],
2507
+ createTrendlineProperties(seriesColor(), trendline.line),
2508
+ createValue("c:trendlineType", TRENDLINE_OOXML_NAMES[type]),
2509
+ ...type === "polynomial" ? [createValue("c:order", (_trendline$order = trendline.order) !== null && _trendline$order !== void 0 ? _trendline$order : 2)] : [],
2510
+ ...type === "movingAverage" ? [createValue("c:period", (_trendline$period = trendline.period) !== null && _trendline$period !== void 0 ? _trendline$period : 2)] : [],
2511
+ ...numbers.flatMap(([element, value]) => value === void 0 ? [] : [createValue(element, formatNumber(value))]),
2512
+ createValue("c:dispRSqr", rSquared),
2513
+ createValue("c:dispEq", equation),
2514
+ ...equation || rSquared ? [createTrendlineLabel(trendline, font)] : []
2515
+ ]);
2516
+ });
2517
+ //#endregion
2518
+ //#region src/charts/plot-area/bubble-chart.ts
2519
+ /**
2520
+ * A bubble chart, with two value axes. Each bubble is filled with its series' colour at 75% opacity, as Office draws
2521
+ * them, so the bubbles behind show through.
2522
+ *
2523
+ * ## XSD Schema
2524
+ * ```xml
2525
+ * <xsd:complexType name="CT_BubbleChart">
2526
+ * <xsd:sequence>
2527
+ * <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2528
+ * <xsd:element name="ser" type="CT_BubbleSer" minOccurs="0" maxOccurs="unbounded"/>
2529
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2530
+ * <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2531
+ * <xsd:element name="bubbleScale" type="CT_BubbleScale" minOccurs="0" maxOccurs="1"/>
2532
+ * <xsd:element name="showNegBubbles" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2533
+ * <xsd:element name="sizeRepresents" type="CT_SizeRepresents" minOccurs="0" maxOccurs="1"/>
2534
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
2535
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2536
+ * </xsd:sequence>
2537
+ * </xsd:complexType>
2538
+ *
2539
+ * <xsd:complexType name="CT_BubbleSer">
2540
+ * <xsd:sequence>
2541
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
2542
+ * <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2543
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
2544
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2545
+ * <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/>
2546
+ * <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/>
2547
+ * <xsd:element name="xVal" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
2548
+ * <xsd:element name="yVal" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2549
+ * <xsd:element name="bubbleSize" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2550
+ * <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2551
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2552
+ * </xsd:sequence>
2553
+ * </xsd:complexType>
2554
+ * ```
2555
+ */
2556
+ var createBubbleChart = (options, data, font) => {
2557
+ var _options$bubbleScale;
2558
+ return {
2559
+ groups: [createElement("c:bubbleChart", {}, [
2560
+ createValue("c:varyColors", false),
2561
+ ...data.series.map((series, index) => {
2562
+ var _series$errors, _series$errors2;
2563
+ const own = options.series[index];
2564
+ return createElement("c:ser", {}, [
2565
+ ...createSeriesStart(index, series),
2566
+ createBubbleSeriesProperties(index, own.color),
2567
+ createValue("c:invertIfNegative", false),
2568
+ ...createSeriesDataLabels(labelsOf(own.dataLabels, options.dataLabels), {
2569
+ shape: "points",
2570
+ series: own.name,
2571
+ font,
2572
+ pointLabels: own.pointLabels
2573
+ }),
2574
+ ...createTrendlines(own.trendlines, () => createSeriesColor(index, own.color), font),
2575
+ ...createErrorBars(own.xErrorBars, "x", (_series$errors = series.errors) === null || _series$errors === void 0 ? void 0 : _series$errors.x),
2576
+ ...createErrorBars(own.yErrorBars, "y", (_series$errors2 = series.errors) === null || _series$errors2 === void 0 ? void 0 : _series$errors2.y),
2577
+ createDataSource("c:xVal", series.categories),
2578
+ createDataSource("c:yVal", series.values),
2579
+ createDataSource("c:bubbleSize", series.sizes),
2580
+ createValue("c:bubble3D", false)
2581
+ ]);
2582
+ }),
2583
+ createGroupDataLabels(),
2584
+ createValue("c:bubbleScale", Math.round((_options$bubbleScale = options.bubbleScale) !== null && _options$bubbleScale !== void 0 ? _options$bubbleScale : 100)),
2585
+ createValue("c:showNegBubbles", false),
2586
+ createValue("c:sizeRepresents", options.sizeRepresents === "width" ? "w" : "area"),
2587
+ createValue("c:axId", PRIMARY_AXES.category),
2588
+ createValue("c:axId", PRIMARY_AXES.value)
2589
+ ])],
2590
+ axes: createPointAxes(options, font)
2591
+ };
2592
+ };
2593
+ //#endregion
2594
+ //#region src/charts/plot-area/area-chart.ts
2595
+ /**
2596
+ * A group of areas.
2597
+ *
2598
+ * ## XSD Schema
2599
+ * ```xml
2600
+ * <xsd:complexType name="CT_AreaChart">
2601
+ * <xsd:sequence>
2602
+ * <xsd:group ref="EG_AreaChartShared" minOccurs="1" maxOccurs="1"/>
2603
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
2604
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2605
+ * </xsd:sequence>
2606
+ * </xsd:complexType>
2607
+ *
2608
+ * <xsd:complexType name="CT_AreaSer">
2609
+ * <xsd:sequence>
2610
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
2611
+ * <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/>
2612
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
2613
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2614
+ * <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/>
2615
+ * <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/>
2616
+ * <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
2617
+ * <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2618
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2619
+ * </xsd:sequence>
2620
+ * </xsd:complexType>
2621
+ * ```
2622
+ */
2623
+ var createAreaChart = ({ series, stacking, axes, dataLabels, font }) => createElement("c:areaChart", {}, [
2624
+ createValue("c:grouping", GROUPINGS[stacking]),
2625
+ createValue("c:varyColors", false),
2626
+ ...series.map(({ index, options, data }) => {
2627
+ var _data$errors;
2628
+ return createElement("c:ser", {}, [
2629
+ ...createSeriesStart(index, data),
2630
+ createFilledSeriesProperties(createSeriesColor(index, options.color)),
2631
+ ...createSeriesDataLabels(labelsOf(options.dataLabels, dataLabels), {
2632
+ shape: "area",
2633
+ series: options.name,
2634
+ font,
2635
+ pointLabels: options.pointLabels
2636
+ }),
2637
+ ...createTrendlines(options.trendlines, () => createSeriesColor(index, options.color), font),
2638
+ ...createErrorBars(options.errorBars, "y", (_data$errors = data.errors) === null || _data$errors === void 0 ? void 0 : _data$errors.y),
2639
+ ...createCategoriesAndValues(data)
2640
+ ]);
2641
+ }),
2642
+ createGroupDataLabels(),
2643
+ createValue("c:axId", axes.category),
2644
+ createValue("c:axId", axes.value)
2645
+ ]);
2646
+ //#endregion
2647
+ //#region src/charts/plot-area/bar-chart.ts
2648
+ /**
2649
+ * A bar's own colour (`c:dPt`), as Word writes it when one bar of a series is given a colour of its own.
2650
+ */
2651
+ var createBarColors = (colors = []) => colors.flatMap((color, point) => color === void 0 ? [] : [createElement("c:dPt", {}, [
2652
+ createValue("c:idx", point),
2653
+ createValue("c:invertIfNegative", false),
2654
+ createValue("c:bubble3D", false),
2655
+ createFilledSeriesProperties(createChartColor(color))
2656
+ ])]);
2657
+ /**
2658
+ * A group of columns or bars. A bar chart's categories are on the left and its values along the bottom.
2659
+ *
2660
+ * ## XSD Schema
2661
+ * ```xml
2662
+ * <xsd:complexType name="CT_BarChart">
2663
+ * <xsd:sequence>
2664
+ * <xsd:group ref="EG_BarChartShared" minOccurs="1" maxOccurs="1"/>
2665
+ * <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/>
2666
+ * <xsd:element name="overlap" type="CT_Overlap" minOccurs="0" maxOccurs="1"/>
2667
+ * <xsd:element name="serLines" type="CT_ChartLines" minOccurs="0" maxOccurs="unbounded"/>
2668
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
2669
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2670
+ * </xsd:sequence>
2671
+ * </xsd:complexType>
2672
+ *
2673
+ * <xsd:group name="EG_BarChartShared">
2674
+ * <xsd:sequence>
2675
+ * <xsd:element name="barDir" type="CT_BarDir" minOccurs="1" maxOccurs="1"/>
2676
+ * <xsd:element name="grouping" type="CT_BarGrouping" minOccurs="0" maxOccurs="1"/>
2677
+ * <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2678
+ * <xsd:element name="ser" type="CT_BarSer" minOccurs="0" maxOccurs="unbounded"/>
2679
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2680
+ * </xsd:sequence>
2681
+ * </xsd:group>
2682
+ *
2683
+ * <xsd:complexType name="CT_BarSer">
2684
+ * <xsd:sequence>
2685
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
2686
+ * <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2687
+ * <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/>
2688
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
2689
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2690
+ * ...
2691
+ * <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
2692
+ * <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2693
+ * ...
2694
+ * </xsd:sequence>
2695
+ * </xsd:complexType>
2696
+ * ```
2697
+ */
2698
+ var createBarChart = ({ series, stacking, axes, dataLabels, font, horizontal, gapWidth, overlap }) => {
2699
+ const stacked = stacking !== "none";
2700
+ const gap = gapWidth !== null && gapWidth !== void 0 ? gapWidth : stacked ? 150 : horizontal ? 182 : 219;
2701
+ const overlapping = stacked ? 100 : overlap !== null && overlap !== void 0 ? overlap : horizontal ? 0 : -27;
2702
+ return createElement("c:barChart", {}, [
2703
+ createValue("c:barDir", horizontal ? "bar" : "col"),
2704
+ createValue("c:grouping", stacked ? GROUPINGS[stacking] : "clustered"),
2705
+ createValue("c:varyColors", false),
2706
+ ...series.map(({ index, options, data }) => {
2707
+ var _data$errors;
2708
+ return createElement("c:ser", {}, [
2709
+ ...createSeriesStart(index, data),
2710
+ createFilledSeriesProperties(createSeriesColor(index, options.color)),
2711
+ createValue("c:invertIfNegative", false),
2712
+ ...createBarColors(options.colors),
2713
+ ...createSeriesDataLabels(labelsOf(options.dataLabels, dataLabels), {
2714
+ shape: stacked ? "stackedBars" : "bars",
2715
+ series: options.name,
2716
+ font,
2717
+ pointLabels: options.pointLabels
2718
+ }),
2719
+ ...createTrendlines(options.trendlines, () => createSeriesColor(index, options.color), font),
2720
+ ...createErrorBars(options.errorBars, "y", (_data$errors = data.errors) === null || _data$errors === void 0 ? void 0 : _data$errors.y),
2721
+ ...createCategoriesAndValues(data)
2722
+ ]);
2723
+ }),
2724
+ createGroupDataLabels(),
2725
+ createValue("c:gapWidth", Math.round(gap)),
2726
+ createValue("c:overlap", Math.round(overlapping)),
2727
+ createValue("c:axId", axes.category),
2728
+ createValue("c:axId", axes.value)
2729
+ ]);
2730
+ };
2731
+ //#endregion
2732
+ //#region src/charts/plot-area/line-chart.ts
2733
+ /**
2734
+ * A marker for each point of a series, or none: the series' own markers, or the chart's.
2735
+ *
2736
+ * @param seriesColor - Creates the series' colour
2737
+ */
2738
+ var createSeriesMarker = (markers, seriesColor) => createMarker(markers ? seriesColor : void 0, typeof markers === "object" ? markers : void 0);
2739
+ /**
2740
+ * A group of lines. Its lines are 2.25 points wide, with a circle at each point when they have markers, unless asked
2741
+ * otherwise.
2742
+ *
2743
+ * ## XSD Schema
2744
+ * ```xml
2745
+ * <xsd:complexType name="CT_LineChart">
2746
+ * <xsd:sequence>
2747
+ * <xsd:group ref="EG_LineChartShared" minOccurs="1" maxOccurs="1"/>
2748
+ * <xsd:element name="hiLowLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
2749
+ * <xsd:element name="upDownBars" type="CT_UpDownBars" minOccurs="0" maxOccurs="1"/>
2750
+ * <xsd:element name="marker" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2751
+ * <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2752
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
2753
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2754
+ * </xsd:sequence>
2755
+ * </xsd:complexType>
2756
+ *
2757
+ * <xsd:complexType name="CT_LineSer">
2758
+ * <xsd:sequence>
2759
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
2760
+ * <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/>
2761
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
2762
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
2763
+ * <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/>
2764
+ * <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="1"/>
2765
+ * <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
2766
+ * <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
2767
+ * <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
2768
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2769
+ * </xsd:sequence>
2770
+ * </xsd:complexType>
2771
+ * ```
2772
+ */
2773
+ var createLineChart = ({ series, stacking, axes, dataLabels, font, markers, smooth }) => {
2774
+ const markersOf = (options) => {
2775
+ var _options$markers;
2776
+ return (_options$markers = options.markers) !== null && _options$markers !== void 0 ? _options$markers : markers;
2777
+ };
2778
+ return createElement("c:lineChart", {}, [
2779
+ createValue("c:grouping", GROUPINGS[stacking]),
2780
+ createValue("c:varyColors", false),
2781
+ ...series.map(({ index, options, data }) => {
2782
+ var _data$errors, _ref, _options$smooth;
2783
+ const seriesColor = () => createSeriesColor(index, options.color);
2784
+ return createElement("c:ser", {}, [
2785
+ ...createSeriesStart(index, data),
2786
+ createLineSeriesProperties(seriesColor(), options.line),
2787
+ createSeriesMarker(markersOf(options), seriesColor),
2788
+ ...createSeriesDataLabels(labelsOf(options.dataLabels, dataLabels), {
2789
+ shape: "line",
2790
+ series: options.name,
2791
+ font,
2792
+ pointLabels: options.pointLabels
2793
+ }),
2794
+ ...createTrendlines(options.trendlines, seriesColor, font),
2795
+ ...createErrorBars(options.errorBars, "y", (_data$errors = data.errors) === null || _data$errors === void 0 ? void 0 : _data$errors.y),
2796
+ ...createCategoriesAndValues(data),
2797
+ createValue("c:smooth", (_ref = (_options$smooth = options.smooth) !== null && _options$smooth !== void 0 ? _options$smooth : smooth) !== null && _ref !== void 0 ? _ref : false)
2798
+ ]);
2799
+ }),
2800
+ createGroupDataLabels(),
2801
+ ...series.some(({ options }) => markersOf(options)) ? [createValue("c:marker", true)] : [],
2802
+ createValue("c:axId", axes.category),
2803
+ createValue("c:axId", axes.value)
2804
+ ]);
2805
+ };
2806
+ //#endregion
2807
+ //#region src/charts/plot-area/category-chart.ts
2808
+ var KINDS = [
2809
+ "area",
2810
+ "bars",
2811
+ "line"
2812
+ ];
2813
+ var kindOf$1 = (type) => {
2814
+ switch (type) {
2815
+ case "line": return "line";
2816
+ case "area": return "area";
2817
+ default: return "bars";
2818
+ }
2819
+ };
2820
+ /**
2821
+ * The group of series drawn one way against one pair of axes.
2822
+ */
2823
+ var createGroup = (options, kind, group) => {
2824
+ switch (kind) {
2825
+ case "area": return createAreaChart(group);
2826
+ case "line": return createLineChart(_objectSpread2(_objectSpread2({}, group), {}, {
2827
+ markers: options.type === "line" ? options.markers : void 0,
2828
+ smooth: options.type === "line" ? options.smooth : void 0
2829
+ }));
2830
+ default: return createBarChart(_objectSpread2(_objectSpread2({}, group), {}, {
2831
+ horizontal: options.type === "bar",
2832
+ gapWidth: options.type === "column" || options.type === "bar" ? options.gapWidth : void 0,
2833
+ overlap: options.type === "column" || options.type === "bar" ? options.overlap : void 0
2834
+ }));
2835
+ }
2836
+ };
2837
+ /**
2838
+ * The categories' dates, when they are dates: the unit to space them by, and how they are written.
2839
+ */
2840
+ var datesOf = (categories) => {
2841
+ const dates = leafCategoriesOf(categories).filter((category) => category instanceof Date);
2842
+ if (dates.length === 0) return;
2843
+ const unit = timeUnitOf(dates);
2844
+ return {
2845
+ unit,
2846
+ format: DATE_FORMATS[unit]
2847
+ };
2848
+ };
2849
+ /**
2850
+ * A column, bar, line or area chart: a group for each way its series are drawn against each value axis, then its axes.
2851
+ *
2852
+ * - Groups are written areas first, then bars, then lines, and those against the primary axis before those against the
2853
+ * secondary, so each is drawn in front of the one before, as Office draws them.
2854
+ * - `stacking` stacks the groups drawn as the chart's `type`, and the chart's label position is for them. The others
2855
+ * aren't stacked, and keep Office's label positions.
2856
+ * - The secondary value axis is on the right (or for a bar chart, at the top), with no gridlines. It crosses a hidden
2857
+ * secondary category axis, which is in the same order as the primary one, so each series lines up with its category,
2858
+ * at its end away from the primary value axis.
2859
+ * - The value axes cross at the categories (`midCat`) only when every series is an area, so the areas reach both sides of
2860
+ * the plot, as in Word's and Excel's area charts, and the categories line up for every group.
2861
+ */
2862
+ var createCategoryCharts = (options, data, font) => {
2863
+ var _options$stacking, _options$categoryAxis, _options$categoryAxis2;
2864
+ const series = groupSeries(options.series, data.series);
2865
+ const stacking = (_options$stacking = options.stacking) !== null && _options$stacking !== void 0 ? _options$stacking : "none";
2866
+ const ownKind = kindOf$1(options.type);
2867
+ const horizontal = options.type === "bar";
2868
+ const kindOfSeries = ({ options: one }) => {
2869
+ var _one$type;
2870
+ return kindOf$1((_one$type = one.type) !== null && _one$type !== void 0 ? _one$type : options.type);
2871
+ };
2872
+ const axisOf = ({ options: one }) => {
2873
+ var _one$axis;
2874
+ return (_one$axis = one.axis) !== null && _one$axis !== void 0 ? _one$axis : "primary";
2875
+ };
2876
+ const groupsOn = (axis, ids) => KINDS.flatMap((kind) => {
2877
+ const members = series.filter((one) => axisOf(one) === axis && kindOfSeries(one) === kind);
2878
+ return members.length === 0 ? [] : [createGroup(options, kind, {
2879
+ series: members,
2880
+ stacking: kind === ownKind ? stacking : "none",
2881
+ axes: ids,
2882
+ dataLabels: kind === ownKind || !options.dataLabels ? options.dataLabels : _objectSpread2(_objectSpread2({}, options.dataLabels), {}, { position: void 0 }),
2883
+ font
2884
+ })];
2885
+ });
2886
+ const percentOn = (axis) => stacking === "percent" && series.some((one) => axisOf(one) === axis && kindOfSeries(one) === ownKind);
2887
+ const secondary = series.some((one) => axisOf(one) === "secondary");
2888
+ const dates = datesOf(options.categories);
2889
+ const crossBetween = series.every((one) => kindOfSeries(one) === "area") ? "midCat" : "between";
2890
+ return {
2891
+ groups: [...groupsOn("primary", PRIMARY_AXES), ...secondary ? groupsOn("secondary", SECONDARY_AXES) : []],
2892
+ axes: [
2893
+ createCategoryAxis({
2894
+ id: PRIMARY_AXES.category,
2895
+ crossAxisId: PRIMARY_AXES.value,
2896
+ position: horizontal ? "l" : "b",
2897
+ crossesPercent: percentOn("primary"),
2898
+ font
2899
+ }, options.categoryAxis, dates),
2900
+ createValueAxis({
2901
+ id: PRIMARY_AXES.value,
2902
+ crossAxisId: PRIMARY_AXES.category,
2903
+ position: horizontal ? "b" : "l",
2904
+ crossBetween,
2905
+ percent: percentOn("primary"),
2906
+ font
2907
+ }, options.valueAxis),
2908
+ ...secondary ? [createValueAxis({
2909
+ id: SECONDARY_AXES.value,
2910
+ crossAxisId: SECONDARY_AXES.category,
2911
+ position: horizontal ? "t" : "r",
2912
+ crosses: ((_options$categoryAxis = options.categoryAxis) === null || _options$categoryAxis === void 0 ? void 0 : _options$categoryAxis.reverseOrder) ? "minimum" : "maximum",
2913
+ crossBetween,
2914
+ percent: percentOn("secondary"),
2915
+ gridlines: false,
2916
+ font
2917
+ }, options.secondaryValueAxis), createCategoryAxis({
2918
+ id: SECONDARY_AXES.category,
2919
+ crossAxisId: SECONDARY_AXES.value,
2920
+ position: horizontal ? "l" : "b",
2921
+ crossesPercent: percentOn("secondary")
2922
+ }, {
2923
+ visible: false,
2924
+ reverseOrder: (_options$categoryAxis2 = options.categoryAxis) === null || _options$categoryAxis2 === void 0 ? void 0 : _options$categoryAxis2.reverseOrder
2925
+ }, dates)] : []
2926
+ ]
2927
+ };
2928
+ };
2929
+ //#endregion
2930
+ //#region src/charts/plot-area/pie-chart.ts
2931
+ var SPLIT_TYPES = {
2932
+ position: "pos",
2933
+ value: "val",
2934
+ percentage: "percent",
2935
+ categories: "cust"
2936
+ };
2937
+ /**
2938
+ * How a pie of pie or bar of pie chart splits its pie, written out, so every application splits it the same way: as
2939
+ * given, or by default, the last third of the categories, rounded up, go to the second plot.
2940
+ *
2941
+ * ## XSD Schema
2942
+ * ```xml
2943
+ * <xsd:complexType name="CT_OfPieChart">
2944
+ * <xsd:sequence>
2945
+ * <xsd:element name="ofPieType" type="CT_OfPieType" minOccurs="1" maxOccurs="1"/>
2946
+ * <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/>
2947
+ * <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/>
2948
+ * <xsd:element name="splitType" type="CT_SplitType" minOccurs="0" maxOccurs="1"/>
2949
+ * <xsd:element name="splitPos" type="CT_Double" minOccurs="0" maxOccurs="1"/>
2950
+ * <xsd:element name="custSplit" type="CT_CustSplit" minOccurs="0" maxOccurs="1"/>
2951
+ * <xsd:element name="secondPieSize" type="CT_SecondPieSize" minOccurs="0" maxOccurs="1"/>
2952
+ * <xsd:element name="serLines" type="CT_ChartLines" minOccurs="0" maxOccurs="unbounded"/>
2953
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
2954
+ * </xsd:sequence>
2955
+ * </xsd:complexType>
2956
+ * ```
2957
+ */
2958
+ var createSplit = (options) => {
2959
+ var _options$split, _options$gapWidth, _options$secondPlotSi;
2960
+ const split = (_options$split = options.split) !== null && _options$split !== void 0 ? _options$split : {
2961
+ by: "position",
2962
+ count: Math.max(1, Math.ceil(options.categories.length / 3))
2963
+ };
2964
+ const position = (() => {
2965
+ switch (split.by) {
2966
+ case "categories": {
2967
+ const chosen = split.categories.map(String);
2968
+ return [createElement("c:custSplit", {}, options.categories.flatMap((category, index) => chosen.includes(String(category)) ? [index] : []).map((point) => createValue("c:secondPiePt", point)))];
2969
+ }
2970
+ case "position": return [createValue("c:splitPos", split.count)];
2971
+ default: return [createValue("c:splitPos", formatNumber(split.lessThan))];
2972
+ }
2973
+ })();
2974
+ return [
2975
+ createValue("c:gapWidth", Math.round((_options$gapWidth = options.gapWidth) !== null && _options$gapWidth !== void 0 ? _options$gapWidth : 100)),
2976
+ createValue("c:splitType", SPLIT_TYPES[split.by]),
2977
+ ...position,
2978
+ createValue("c:secondPieSize", Math.round((_options$secondPlotSi = options.secondPlotSize) !== null && _options$secondPlotSi !== void 0 ? _options$secondPlotSi : 75)),
2979
+ createElement("c:serLines", {}, [createChartLinesProperties(options.seriesLines, 35)])
2980
+ ];
2981
+ };
2982
+ /**
2983
+ * How far a slice is pulled out, if it is on its own: an amount for each slice.
2984
+ */
2985
+ var explosionOf = ({ explosion }, slice) => {
2986
+ const amount = Array.isArray(explosion) ? explosion[slice] : void 0;
2987
+ return amount === void 0 ? [] : [createValue("c:explosion", Math.round(amount))];
2988
+ };
2989
+ /**
2990
+ * A pie, doughnut, pie of pie or bar of pie chart, which has no axes. Each slice takes the next colour, or its own, with a border between it and
2991
+ * the next, and a slice has the same colour in each ring of a doughnut, as the legend shows the categories.
2992
+ *
2993
+ * ## XSD Schema
2994
+ * ```xml
2995
+ * <xsd:complexType name="CT_PieChart">
2996
+ * <xsd:sequence>
2997
+ * <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/>
2998
+ * <xsd:element name="firstSliceAng" type="CT_FirstSliceAng" minOccurs="0" maxOccurs="1"/>
2999
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3000
+ * </xsd:sequence>
3001
+ * </xsd:complexType>
3002
+ *
3003
+ * <xsd:complexType name="CT_DoughnutChart">
3004
+ * <xsd:sequence>
3005
+ * <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/>
3006
+ * <xsd:element name="firstSliceAng" type="CT_FirstSliceAng" minOccurs="0" maxOccurs="1"/>
3007
+ * <xsd:element name="holeSize" type="CT_HoleSize" minOccurs="0" maxOccurs="1"/>
3008
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3009
+ * </xsd:sequence>
3010
+ * </xsd:complexType>
3011
+ *
3012
+ * <xsd:complexType name="CT_DPt">
3013
+ * <xsd:sequence>
3014
+ * <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/>
3015
+ * <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3016
+ * <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/>
3017
+ * <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3018
+ * <xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/>
3019
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
3020
+ * ...
3021
+ * </xsd:sequence>
3022
+ * </xsd:complexType>
3023
+ *
3024
+ * <xsd:complexType name="CT_PieSer">
3025
+ * <xsd:sequence>
3026
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
3027
+ * <xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/>
3028
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
3029
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3030
+ * <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
3031
+ * <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
3032
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3033
+ * </xsd:sequence>
3034
+ * </xsd:complexType>
3035
+ * ```
3036
+ */
3037
+ var createPieChart = (options, data, font) => {
3038
+ var _options$firstSliceAn, _options$holeSize;
3039
+ const { type } = options;
3040
+ const split = type === "pieOfPie" || type === "barOfPie";
3041
+ return {
3042
+ groups: [createElement(split ? "c:ofPieChart" : type === "doughnut" ? "c:doughnutChart" : "c:pieChart", {}, [
3043
+ ...split ? [createValue("c:ofPieType", type === "pieOfPie" ? "pie" : "bar")] : [],
3044
+ createValue("c:varyColors", true),
3045
+ ...data.series.map((series, index) => {
3046
+ const own = options.series[index];
3047
+ return createElement("c:ser", {}, [
3048
+ ...createSeriesStart(index, series),
3049
+ ...typeof own.explosion === "number" ? [createValue("c:explosion", Math.round(own.explosion))] : [],
3050
+ ...options.categories.map((_, slice) => {
3051
+ var _own$colors;
3052
+ return createElement("c:dPt", {}, [
3053
+ createValue("c:idx", slice),
3054
+ createValue("c:bubble3D", false),
3055
+ ...explosionOf(own, slice),
3056
+ createSliceProperties(createSeriesColor(slice, (_own$colors = own.colors) === null || _own$colors === void 0 ? void 0 : _own$colors[slice]))
3057
+ ]);
3058
+ }),
3059
+ ...createSeriesDataLabels(labelsOf(own.dataLabels, options.dataLabels), {
3060
+ shape: type === "doughnut" ? "doughnut" : "pie",
3061
+ series: own.name,
3062
+ leaderLines: true,
3063
+ font,
3064
+ pointLabels: own.pointLabels
3065
+ }),
3066
+ ...createCategoriesAndValues(series)
3067
+ ]);
3068
+ }),
3069
+ createGroupDataLabels(true),
3070
+ ...options.type === "pie" || options.type === "doughnut" ? [createValue("c:firstSliceAng", Math.round((_options$firstSliceAn = options.firstSliceAngle) !== null && _options$firstSliceAn !== void 0 ? _options$firstSliceAn : 0))] : createSplit(options),
3071
+ ...options.type === "doughnut" ? [createValue("c:holeSize", Math.round((_options$holeSize = options.holeSize) !== null && _options$holeSize !== void 0 ? _options$holeSize : 50))] : []
3072
+ ])],
3073
+ axes: []
3074
+ };
3075
+ };
3076
+ //#endregion
3077
+ //#region src/charts/plot-area/radar-chart.ts
3078
+ /**
3079
+ * A radar chart: a spoke for each category, the category axis' gridlines, and rings at each value, the value axis'
3080
+ * gridlines. Each series is a line around the spokes, 2.25 points wide, or a filled area.
3081
+ *
3082
+ * Excel writes `c:radarStyle` `marker` for its "Radar" and "Radar with Markers" charts alike, and gives the plain radar's
3083
+ * series markers of `none`, so this does too.
3084
+ *
3085
+ * ## XSD Schema
3086
+ * ```xml
3087
+ * <xsd:complexType name="CT_RadarChart">
3088
+ * <xsd:sequence>
3089
+ * <xsd:element name="radarStyle" type="CT_RadarStyle" minOccurs="1" maxOccurs="1"/>
3090
+ * <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3091
+ * <xsd:element name="ser" type="CT_RadarSer" minOccurs="0" maxOccurs="unbounded"/>
3092
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3093
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
3094
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3095
+ * </xsd:sequence>
3096
+ * </xsd:complexType>
3097
+ *
3098
+ * <xsd:complexType name="CT_RadarSer">
3099
+ * <xsd:sequence>
3100
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
3101
+ * <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/>
3102
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
3103
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3104
+ * <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
3105
+ * <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
3106
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3107
+ * </xsd:sequence>
3108
+ * </xsd:complexType>
3109
+ * ```
3110
+ */
3111
+ var createRadarChart = (options, data, font) => {
3112
+ var _options$filled;
3113
+ const filled = (_options$filled = options.filled) !== null && _options$filled !== void 0 ? _options$filled : false;
3114
+ return {
3115
+ groups: [createElement("c:radarChart", {}, [
3116
+ createValue("c:radarStyle", filled ? "filled" : "marker"),
3117
+ createValue("c:varyColors", false),
3118
+ ...data.series.map((series, index) => {
3119
+ var _own$markers;
3120
+ const own = options.series[index];
3121
+ const seriesColor = () => createSeriesColor(index, own.color);
3122
+ return createElement("c:ser", {}, [
3123
+ ...createSeriesStart(index, series),
3124
+ ...filled ? [createFilledSeriesProperties(seriesColor())] : [createLineSeriesProperties(seriesColor(), own.line), createSeriesMarker((_own$markers = own.markers) !== null && _own$markers !== void 0 ? _own$markers : options.markers, seriesColor)],
3125
+ ...createSeriesDataLabels(labelsOf(own.dataLabels, options.dataLabels), {
3126
+ shape: "radar",
3127
+ series: own.name,
3128
+ font,
3129
+ pointLabels: own.pointLabels
3130
+ }),
3131
+ ...createCategoriesAndValues(series)
3132
+ ]);
3133
+ }),
3134
+ createGroupDataLabels(),
3135
+ createValue("c:axId", PRIMARY_AXES.category),
3136
+ createValue("c:axId", PRIMARY_AXES.value)
3137
+ ])],
3138
+ axes: [createCategoryAxis({
3139
+ id: PRIMARY_AXES.category,
3140
+ crossAxisId: PRIMARY_AXES.value,
3141
+ position: "b",
3142
+ radar: true,
3143
+ font
3144
+ }, options.categoryAxis), createValueAxis({
3145
+ id: PRIMARY_AXES.value,
3146
+ crossAxisId: PRIMARY_AXES.category,
3147
+ position: "l",
3148
+ crossBetween: "between",
3149
+ radar: true,
3150
+ font
3151
+ }, options.valueAxis)]
3152
+ };
3153
+ };
3154
+ //#endregion
3155
+ //#region src/charts/plot-area/scatter-chart.ts
3156
+ /**
3157
+ * A scatter chart, with two value axes. Applications draw a scatter series' line from the series' own line, whatever
3158
+ * `c:scatterStyle` says, so a series without lines has a line with no fill, as Word's "Scatter" writes it.
3159
+ *
3160
+ * ## XSD Schema
3161
+ * ```xml
3162
+ * <xsd:complexType name="CT_ScatterChart">
3163
+ * <xsd:sequence>
3164
+ * <xsd:element name="scatterStyle" type="CT_ScatterStyle" minOccurs="1" maxOccurs="1"/>
3165
+ * <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3166
+ * <xsd:element name="ser" type="CT_ScatterSer" minOccurs="0" maxOccurs="unbounded"/>
3167
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3168
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
3169
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3170
+ * </xsd:sequence>
3171
+ * </xsd:complexType>
3172
+ *
3173
+ * <xsd:complexType name="CT_ScatterSer">
3174
+ * <xsd:sequence>
3175
+ * <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/>
3176
+ * <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/>
3177
+ * <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/>
3178
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3179
+ * <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/>
3180
+ * <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/>
3181
+ * <xsd:element name="xVal" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/>
3182
+ * <xsd:element name="yVal" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/>
3183
+ * <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3184
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3185
+ * </xsd:sequence>
3186
+ * </xsd:complexType>
3187
+ * ```
3188
+ */
3189
+ var createScatterChart = (options, data, font) => {
3190
+ var _options$lines, _options$markers;
3191
+ const lines = (_options$lines = options.lines) !== null && _options$lines !== void 0 ? _options$lines : "none";
3192
+ const markers = (_options$markers = options.markers) !== null && _options$markers !== void 0 ? _options$markers : true;
3193
+ return {
3194
+ groups: [createElement("c:scatterChart", {}, [
3195
+ createValue("c:scatterStyle", lines === "smooth" ? "smoothMarker" : "lineMarker"),
3196
+ createValue("c:varyColors", false),
3197
+ ...data.series.map((series, index) => {
3198
+ var _own$markers, _series$errors, _series$errors2;
3199
+ const own = options.series[index];
3200
+ const seriesColor = () => createSeriesColor(index, own.color);
3201
+ return createElement("c:ser", {}, [
3202
+ ...createSeriesStart(index, series),
3203
+ createScatterSeriesProperties(lines === "none" ? void 0 : seriesColor(), own.line),
3204
+ createSeriesMarker((_own$markers = own.markers) !== null && _own$markers !== void 0 ? _own$markers : markers, seriesColor),
3205
+ ...createSeriesDataLabels(labelsOf(own.dataLabels, options.dataLabels), {
3206
+ shape: "points",
3207
+ series: own.name,
3208
+ font,
3209
+ pointLabels: own.pointLabels
3210
+ }),
3211
+ ...createTrendlines(own.trendlines, seriesColor, font),
3212
+ ...createErrorBars(own.xErrorBars, "x", (_series$errors = series.errors) === null || _series$errors === void 0 ? void 0 : _series$errors.x),
3213
+ ...createErrorBars(own.yErrorBars, "y", (_series$errors2 = series.errors) === null || _series$errors2 === void 0 ? void 0 : _series$errors2.y),
3214
+ createDataSource("c:xVal", series.categories),
3215
+ createDataSource("c:yVal", series.values),
3216
+ createValue("c:smooth", lines === "smooth")
3217
+ ]);
3218
+ }),
3219
+ createGroupDataLabels(),
3220
+ createValue("c:axId", PRIMARY_AXES.category),
3221
+ createValue("c:axId", PRIMARY_AXES.value)
3222
+ ])],
3223
+ axes: createPointAxes(options, font)
3224
+ };
3225
+ };
3226
+ //#endregion
3227
+ //#region src/charts/plot-area/stock-chart.ts
3228
+ /**
3229
+ * A stock chart: its prices, drawn by what joins them, and if it has volumes, their columns.
3230
+ *
3231
+ * - The prices' series have no line and no markers. Each category's high and low are joined by a line
3232
+ * (`c:hiLowLines`). With opening prices, a bar goes from each open to each close (`c:upDownBars`): white where the
3233
+ * price rose, and dark grey where it fell. Without them, the close is a short dash across the line.
3234
+ * - Volumes are columns against the primary value axis, on the left, and the prices are against the secondary value
3235
+ * axis, on the right, as in Word's "Volume-High-Low-Close" chart. Without volumes, the prices are against the primary
3236
+ * value axis.
3237
+ * - Dates are spaced evenly, one for each category, on a text axis rather than a date axis, so days without trading,
3238
+ * such as weekends, leave no gaps. LibreOffice doesn't draw a stock chart's prices on a date axis either.
3239
+ *
3240
+ * ## XSD Schema
3241
+ * ```xml
3242
+ * <xsd:complexType name="CT_StockChart">
3243
+ * <xsd:sequence>
3244
+ * <xsd:element name="ser" type="CT_LineSer" minOccurs="3" maxOccurs="4"/>
3245
+ * <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/>
3246
+ * <xsd:element name="dropLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
3247
+ * <xsd:element name="hiLowLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/>
3248
+ * <xsd:element name="upDownBars" type="CT_UpDownBars" minOccurs="0" maxOccurs="1"/>
3249
+ * <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
3250
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3251
+ * </xsd:sequence>
3252
+ * </xsd:complexType>
3253
+ *
3254
+ * <xsd:complexType name="CT_UpDownBars">
3255
+ * <xsd:sequence>
3256
+ * <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/>
3257
+ * <xsd:element name="upBars" type="CT_UpDownBar" minOccurs="0" maxOccurs="1"/>
3258
+ * <xsd:element name="downBars" type="CT_UpDownBar" minOccurs="0" maxOccurs="1"/>
3259
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3260
+ * </xsd:sequence>
3261
+ * </xsd:complexType>
3262
+ * ```
3263
+ */
3264
+ var createStockChart = (options, data, font) => {
3265
+ var _options$categoryAxis;
3266
+ const series = stockSeriesOf(options).map((one, index) => _objectSpread2(_objectSpread2({}, one), {}, {
3267
+ index,
3268
+ data: data.series[index]
3269
+ }));
3270
+ const volume = series.find(({ role }) => role === "volume");
3271
+ const prices = series.filter(({ role }) => role !== "volume");
3272
+ const opens = options.open !== void 0;
3273
+ const priceAxes = volume ? SECONDARY_AXES : PRIMARY_AXES;
3274
+ const dates = datesOf(options.categories);
3275
+ const reversed = (_options$categoryAxis = options.categoryAxis) === null || _options$categoryAxis === void 0 ? void 0 : _options$categoryAxis.reverseOrder;
3276
+ const stock = createElement("c:stockChart", {}, [
3277
+ ...prices.map(({ role, index, data: one }) => createElement("c:ser", {}, [
3278
+ ...createSeriesStart(index, one),
3279
+ createHiddenSeriesProperties(),
3280
+ role === "close" && !opens ? createCloseMarker() : createMarker(void 0),
3281
+ ...createCategoriesAndValues(one),
3282
+ createValue("c:smooth", false)
3283
+ ])),
3284
+ createGroupDataLabels(),
3285
+ createElement("c:hiLowLines", {}, [createChartLinesProperties(options.highLowLines, 75)]),
3286
+ ...opens ? [createElement("c:upDownBars", {}, [
3287
+ createValue("c:gapWidth", 150),
3288
+ createElement("c:upBars", {}, [createUpDownBarProperties(options.upBars, true)]),
3289
+ createElement("c:downBars", {}, [createUpDownBarProperties(options.downBars, false)])
3290
+ ])] : [],
3291
+ createValue("c:axId", priceAxes.category),
3292
+ createValue("c:axId", priceAxes.value)
3293
+ ]);
3294
+ const categoryAxis = createCategoryAxis({
3295
+ id: PRIMARY_AXES.category,
3296
+ crossAxisId: PRIMARY_AXES.value,
3297
+ position: "b",
3298
+ font
3299
+ }, options.categoryAxis, dates, false);
3300
+ const primaryValueAxis = (axis) => createValueAxis({
3301
+ id: PRIMARY_AXES.value,
3302
+ crossAxisId: PRIMARY_AXES.category,
3303
+ position: "l",
3304
+ crossBetween: "between",
3305
+ font
3306
+ }, axis);
3307
+ if (volume === void 0) return {
3308
+ groups: [stock],
3309
+ axes: [categoryAxis, primaryValueAxis(options.valueAxis)]
3310
+ };
3311
+ return {
3312
+ groups: [createBarChart({
3313
+ series: [{
3314
+ index: volume.index,
3315
+ options: {
3316
+ name: volume.name,
3317
+ values: volume.values
3318
+ },
3319
+ data: volume.data
3320
+ }],
3321
+ stacking: "none",
3322
+ axes: PRIMARY_AXES,
3323
+ font,
3324
+ horizontal: false
3325
+ }), stock],
3326
+ axes: [
3327
+ categoryAxis,
3328
+ primaryValueAxis(options.volumeAxis),
3329
+ createValueAxis({
3330
+ id: SECONDARY_AXES.value,
3331
+ crossAxisId: SECONDARY_AXES.category,
3332
+ position: "r",
3333
+ crosses: reversed ? "minimum" : "maximum",
3334
+ crossBetween: "between",
3335
+ gridlines: false,
3336
+ font
3337
+ }, options.valueAxis),
3338
+ createCategoryAxis({
3339
+ id: SECONDARY_AXES.category,
3340
+ crossAxisId: SECONDARY_AXES.value,
3341
+ position: "b"
3342
+ }, {
3343
+ visible: false,
3344
+ reverseOrder: reversed
3345
+ }, dates, false)
3346
+ ]
3347
+ };
3348
+ };
3349
+ //#endregion
3350
+ //#region src/charts/plot-area/plot-area.ts
3351
+ var createChartGroups = (options, data, font) => {
3352
+ switch (options.type) {
3353
+ case "pie":
3354
+ case "doughnut":
3355
+ case "pieOfPie":
3356
+ case "barOfPie": return createPieChart(options, data, font);
3357
+ case "stock": return createStockChart(options, data, font);
3358
+ case "radar": return createRadarChart(options, data, font);
3359
+ case "scatter": return createScatterChart(options, data, font);
3360
+ case "bubble": return createBubbleChart(options, data, font);
3361
+ default: return createCategoryCharts(options, data, font);
3362
+ }
3363
+ };
3364
+ /**
3365
+ * A table of the chart's data under its plot, with light grey borders and 9 point text, and each series' legend key,
3366
+ * unless asked otherwise.
3367
+ *
3368
+ * ## XSD Schema
3369
+ * ```xml
3370
+ * <xsd:complexType name="CT_DTable">
3371
+ * <xsd:sequence>
3372
+ * <xsd:element name="showHorzBorder" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3373
+ * <xsd:element name="showVertBorder" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3374
+ * <xsd:element name="showOutline" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3375
+ * <xsd:element name="showKeys" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3376
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
3377
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
3378
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3379
+ * </xsd:sequence>
3380
+ * </xsd:complexType>
3381
+ * ```
3382
+ */
3383
+ var createDataTable = (table, chartFont) => {
3384
+ const { legendKeys = true, horizontalBorders = true, verticalBorders = true, outline = true, font } = table === true ? {} : table;
3385
+ return createElement("c:dTable", {}, [
3386
+ createValue("c:showHorzBorder", horizontalBorders),
3387
+ createValue("c:showVertBorder", verticalBorders),
3388
+ createValue("c:showOutline", outline),
3389
+ createValue("c:showKeys", legendKeys),
3390
+ createDataTableProperties(),
3391
+ createTextProperties({
3392
+ size: 9,
3393
+ rotation: 0,
3394
+ font: fontOf(chartFont, font)
3395
+ })
3396
+ ]);
3397
+ };
3398
+ /**
3399
+ * The plot area, laid out automatically, with no fill or border unless asked for.
3400
+ *
3401
+ * ## XSD Schema
3402
+ * ```xml
3403
+ * <xsd:complexType name="CT_PlotArea">
3404
+ * <xsd:sequence>
3405
+ * <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
3406
+ * <xsd:choice minOccurs="1" maxOccurs="unbounded">
3407
+ * <xsd:element name="areaChart" type="CT_AreaChart" minOccurs="1" maxOccurs="1"/>
3408
+ * <xsd:element name="lineChart" type="CT_LineChart" minOccurs="1" maxOccurs="1"/>
3409
+ * <xsd:element name="scatterChart" type="CT_ScatterChart" minOccurs="1" maxOccurs="1"/>
3410
+ * <xsd:element name="pieChart" type="CT_PieChart" minOccurs="1" maxOccurs="1"/>
3411
+ * <xsd:element name="doughnutChart" type="CT_DoughnutChart" minOccurs="1" maxOccurs="1"/>
3412
+ * <xsd:element name="barChart" type="CT_BarChart" minOccurs="1" maxOccurs="1"/>
3413
+ * <xsd:element name="radarChart" type="CT_RadarChart" minOccurs="1" maxOccurs="1"/>
3414
+ * <xsd:element name="bubbleChart" type="CT_BubbleChart" minOccurs="1" maxOccurs="1"/>
3415
+ * ...
3416
+ * </xsd:choice>
3417
+ * <xsd:choice minOccurs="0" maxOccurs="unbounded">
3418
+ * <xsd:element name="valAx" type="CT_ValAx" minOccurs="1" maxOccurs="1"/>
3419
+ * <xsd:element name="catAx" type="CT_CatAx" minOccurs="1" maxOccurs="1"/>
3420
+ * <xsd:element name="dateAx" type="CT_DateAx" minOccurs="1" maxOccurs="1"/>
3421
+ * <xsd:element name="serAx" type="CT_SerAx" minOccurs="1" maxOccurs="1"/>
3422
+ * </xsd:choice>
3423
+ * <xsd:element name="dTable" type="CT_DTable" minOccurs="0" maxOccurs="1"/>
3424
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
3425
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3426
+ * </xsd:sequence>
3427
+ * </xsd:complexType>
3428
+ * ```
3429
+ */
3430
+ var createPlotArea = (options, data) => {
3431
+ const { groups, axes } = createChartGroups(options, data, options.font);
3432
+ const { dataTable } = options;
3433
+ return createElement("c:plotArea", {}, [
3434
+ createElement("c:layout"),
3435
+ ...groups,
3436
+ ...axes,
3437
+ ...dataTable ? [createDataTable(dataTable, options.font)] : [],
3438
+ createPlotAreaProperties(options.plotArea)
3439
+ ]);
3440
+ };
3441
+ //#endregion
3442
+ //#region src/charts/chart-space.ts
3443
+ var CHART_NAMESPACE = "http://schemas.openxmlformats.org/drawingml/2006/chart";
3444
+ var RELATIONSHIPS_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
3445
+ var LEGEND_POSITIONS = {
3446
+ top: "t",
3447
+ bottom: "b",
3448
+ left: "l",
3449
+ right: "r",
3450
+ topRight: "tr"
3451
+ };
3452
+ var EMPTY_VALUES = {
3453
+ gap: "gap",
3454
+ zero: "zero",
3455
+ connect: "span"
3456
+ };
3457
+ /**
3458
+ * The legend (`c:legend`), beside the plot rather than over it, in 9 point text, without the entries it hides.
3459
+ *
3460
+ * ## XSD Schema
3461
+ * ```xml
3462
+ * <xsd:complexType name="CT_Legend">
3463
+ * <xsd:sequence>
3464
+ * <xsd:element name="legendPos" type="CT_LegendPos" minOccurs="0" maxOccurs="1"/>
3465
+ * <xsd:element name="legendEntry" type="CT_LegendEntry" minOccurs="0" maxOccurs="unbounded"/>
3466
+ * <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
3467
+ * <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3468
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
3469
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
3470
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3471
+ * </xsd:sequence>
3472
+ * </xsd:complexType>
3473
+ * ```
3474
+ */
3475
+ var createLegend = (options, { position = "bottom", font, hiddenEntries = [] }) => createElement("c:legend", {}, [
3476
+ createValue("c:legendPos", LEGEND_POSITIONS[position]),
3477
+ ...legendEntriesOf(options).filter(({ text }) => hiddenEntries.some((entry) => String(entry) === text)).map(({ index }) => createElement("c:legendEntry", {}, [createValue("c:idx", index), createValue("c:delete", true)])),
3478
+ createValue("c:overlay", false),
3479
+ createNoShapeProperties(),
3480
+ createTextProperties({
3481
+ size: 9,
3482
+ rotation: 0,
3483
+ font: fontOf(options.font, font)
3484
+ })
3485
+ ]);
3486
+ /**
3487
+ * The chart part's root, in the schema's order. Office's `c14:style`, `c:extLst` and `c16` extensions are left out, as
3488
+ * the look is written explicitly.
3489
+ *
3490
+ * ## XSD Schema
3491
+ * ```xml
3492
+ * <xsd:complexType name="CT_ChartSpace">
3493
+ * <xsd:sequence>
3494
+ * <xsd:element name="date1904" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3495
+ * <xsd:element name="lang" type="CT_TextLanguageID" minOccurs="0" maxOccurs="1"/>
3496
+ * <xsd:element name="roundedCorners" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3497
+ * <xsd:element name="style" type="CT_Style" minOccurs="0" maxOccurs="1"/>
3498
+ * <xsd:element name="clrMapOvr" type="a:CT_ColorMapping" minOccurs="0" maxOccurs="1"/>
3499
+ * <xsd:element name="pivotSource" type="CT_PivotSource" minOccurs="0" maxOccurs="1"/>
3500
+ * <xsd:element name="protection" type="CT_Protection" minOccurs="0" maxOccurs="1"/>
3501
+ * <xsd:element name="chart" type="CT_Chart" minOccurs="1" maxOccurs="1"/>
3502
+ * <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
3503
+ * <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
3504
+ * <xsd:element name="externalData" type="CT_ExternalData" minOccurs="0" maxOccurs="1"/>
3505
+ * <xsd:element name="printSettings" type="CT_PrintSettings" minOccurs="0" maxOccurs="1"/>
3506
+ * <xsd:element name="userShapes" type="CT_RelId" minOccurs="0" maxOccurs="1"/>
3507
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3508
+ * </xsd:sequence>
3509
+ * </xsd:complexType>
3510
+ *
3511
+ * <xsd:complexType name="CT_Chart">
3512
+ * <xsd:sequence>
3513
+ * <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/>
3514
+ * <xsd:element name="autoTitleDeleted" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3515
+ * <xsd:element name="pivotFmts" type="CT_PivotFmts" minOccurs="0" maxOccurs="1"/>
3516
+ * <xsd:element name="view3D" type="CT_View3D" minOccurs="0" maxOccurs="1"/>
3517
+ * <xsd:element name="floor" type="CT_Surface" minOccurs="0" maxOccurs="1"/>
3518
+ * <xsd:element name="sideWall" type="CT_Surface" minOccurs="0" maxOccurs="1"/>
3519
+ * <xsd:element name="backWall" type="CT_Surface" minOccurs="0" maxOccurs="1"/>
3520
+ * <xsd:element name="plotArea" type="CT_PlotArea" minOccurs="1" maxOccurs="1"/>
3521
+ * <xsd:element name="legend" type="CT_Legend" minOccurs="0" maxOccurs="1"/>
3522
+ * <xsd:element name="plotVisOnly" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3523
+ * <xsd:element name="dispBlanksAs" type="CT_DispBlanksAs" minOccurs="0" maxOccurs="1"/>
3524
+ * <xsd:element name="showDLblsOverMax" type="CT_Boolean" minOccurs="0" maxOccurs="1"/>
3525
+ * <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
3526
+ * </xsd:sequence>
3527
+ * </xsd:complexType>
3528
+ * ```
3529
+ *
3530
+ * @param workbook - The embedded workbook, which the chart's data refers to
3531
+ */
3532
+ var createChartSpace = (options, data, workbook) => {
3533
+ var _options$legend, _options$emptyValues;
3534
+ return createElement("c:chartSpace", {
3535
+ "xmlns:c": CHART_NAMESPACE,
3536
+ "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
3537
+ "xmlns:r": RELATIONSHIPS_NAMESPACE
3538
+ }, [
3539
+ createValue("c:date1904", false),
3540
+ createValue("c:lang", "en-US"),
3541
+ createValue("c:roundedCorners", false),
3542
+ createElement("c:chart", {}, [
3543
+ ...options.title === void 0 ? [] : [createChartTitle(options.title, options.font)],
3544
+ createValue("c:autoTitleDeleted", options.title === void 0),
3545
+ createPlotArea(options, data),
3546
+ ...options.legend === false ? [] : [createLegend(options, (_options$legend = options.legend) !== null && _options$legend !== void 0 ? _options$legend : {})],
3547
+ createValue("c:plotVisOnly", true),
3548
+ createValue("c:dispBlanksAs", EMPTY_VALUES[(_options$emptyValues = options.emptyValues) !== null && _options$emptyValues !== void 0 ? _options$emptyValues : "gap"])
3549
+ ]),
3550
+ createChartAreaProperties(options.chartArea),
3551
+ createChartTextProperties(),
3552
+ new PartReference("c:externalData", workbook, { children: [createValue("c:autoUpdate", false)] })
3553
+ ]);
3554
+ };
3555
+ //#endregion
3556
+ //#region src/charts/workbook/workbook.ts
3557
+ /**
3558
+ * The embedded workbook (`word/embeddings/Microsoft_Excel_Worksheet1.xlsx`) that holds a chart's data, so Word's "Edit
3559
+ * Data" opens it. It has one sheet, laid out as Word lays out a new chart's data, with its text in shared strings, as
3560
+ * Excel writes it.
3561
+ *
3562
+ * @module
3563
+ */
3564
+ var SPREADSHEET_NAMESPACE = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
3565
+ var RELATIONSHIP_TYPES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
3566
+ var createContentTypes = () => createElement("Types", { xmlns: "http://schemas.openxmlformats.org/package/2006/content-types" }, [
3567
+ createElement("Default", {
3568
+ Extension: "rels",
3569
+ ContentType: "application/vnd.openxmlformats-package.relationships+xml"
3570
+ }),
3571
+ createElement("Default", {
3572
+ Extension: "xml",
3573
+ ContentType: "application/xml"
3574
+ }),
3575
+ ...[
3576
+ ["/xl/workbook.xml", "sheet.main+xml"],
3577
+ ["/xl/worksheets/sheet1.xml", "worksheet+xml"],
3578
+ ["/xl/styles.xml", "styles+xml"],
3579
+ ["/xl/sharedStrings.xml", "sharedStrings+xml"]
3580
+ ].map(([partName, type]) => createElement("Override", {
3581
+ PartName: partName,
3582
+ ContentType: `application/vnd.openxmlformats-officedocument.spreadsheetml.${type}`
3583
+ }))
3584
+ ]);
3585
+ var createRelationships = (relationships) => createElement("Relationships", { xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" }, relationships.map(([type, target], index) => createElement("Relationship", {
3586
+ Id: `rId${index + 1}`,
3587
+ Type: `${RELATIONSHIP_TYPES}/${type}`,
3588
+ Target: target
3589
+ })));
3590
+ var createWorkbook = () => createElement("workbook", {
3591
+ xmlns: SPREADSHEET_NAMESPACE,
3592
+ "xmlns:r": RELATIONSHIP_TYPES
3593
+ }, [createElement("sheets", {}, [createElement("sheet", {
3594
+ name: SHEET_NAME,
3595
+ sheetId: 1,
3596
+ "r:id": "rId1"
3597
+ })])]);
3598
+ var FIRST_NUMBER_FORMAT_ID = 164;
3599
+ /**
3600
+ * The fewest styles Excel accepts: one font, the two fills every workbook has, one border and one cell format, then a
3601
+ * cell format for each number format the sheet's cells have, such as a date format.
3602
+ */
3603
+ var createStyles = (formats) => createElement("styleSheet", { xmlns: SPREADSHEET_NAMESPACE }, [
3604
+ ...formats.length === 0 ? [] : [createElement("numFmts", { count: formats.length }, formats.map((formatCode, index) => createElement("numFmt", {
3605
+ numFmtId: FIRST_NUMBER_FORMAT_ID + index,
3606
+ formatCode
3607
+ })))],
3608
+ createElement("fonts", { count: 1 }, [createElement("font", {}, [
3609
+ createElement("sz", { val: 11 }),
3610
+ createElement("name", { val: "Calibri" }),
3611
+ createElement("family", { val: 2 })
3612
+ ])]),
3613
+ createElement("fills", { count: 2 }, [createElement("fill", {}, [createElement("patternFill", { patternType: "none" })]), createElement("fill", {}, [createElement("patternFill", { patternType: "gray125" })])]),
3614
+ createElement("borders", { count: 1 }, [createElement("border", {}, [
3615
+ "left",
3616
+ "right",
3617
+ "top",
3618
+ "bottom",
3619
+ "diagonal"
3620
+ ].map((side) => createElement(side)))]),
3621
+ createElement("cellStyleXfs", { count: 1 }, [createElement("xf", {
3622
+ numFmtId: 0,
3623
+ fontId: 0,
3624
+ fillId: 0,
3625
+ borderId: 0
3626
+ })]),
3627
+ createElement("cellXfs", { count: formats.length + 1 }, [createElement("xf", {
3628
+ numFmtId: 0,
3629
+ fontId: 0,
3630
+ fillId: 0,
3631
+ borderId: 0,
3632
+ xfId: 0
3633
+ }), ...formats.map((_, index) => createElement("xf", {
3634
+ numFmtId: FIRST_NUMBER_FORMAT_ID + index,
3635
+ fontId: 0,
3636
+ fillId: 0,
3637
+ borderId: 0,
3638
+ xfId: 0,
3639
+ applyNumberFormat: 1
3640
+ }))]),
3641
+ createElement("cellStyles", { count: 1 }, [createElement("cellStyle", {
3642
+ name: "Normal",
3643
+ xfId: 0,
3644
+ builtinId: 0
3645
+ })])
3646
+ ]);
3647
+ /**
3648
+ * A cell that isn't empty: text, as the index of a shared string, or a number, with the cell format of its number format.
3649
+ */
3650
+ var createCell = (cell, name, strings, formats) => {
3651
+ if (typeof cell === "string") return createElement("c", {
3652
+ r: name,
3653
+ t: "s"
3654
+ }, [createText("v", `${strings.get(cell)}`)]);
3655
+ return typeof cell === "number" ? createElement("c", { r: name }, [createText("v", formatNumber(cell))]) : createElement("c", {
3656
+ r: name,
3657
+ s: formats.indexOf(cell.format) + 1
3658
+ }, [createText("v", formatNumber(cell.value))]);
3659
+ };
3660
+ /**
3661
+ * The sheet: its used range, and each cell that isn't empty.
3662
+ */
3663
+ var createWorksheet = (sheet, strings, formats) => {
3664
+ const columns = Math.max(...sheet.map((row) => row.length));
3665
+ return createElement("worksheet", {
3666
+ xmlns: SPREADSHEET_NAMESPACE,
3667
+ "xmlns:r": RELATIONSHIP_TYPES
3668
+ }, [createElement("dimension", { ref: `A1:${cellName(columns - 1, sheet.length - 1)}` }), createElement("sheetData", {}, sheet.flatMap((row, rowIndex) => {
3669
+ const cells = row.flatMap((cell, column) => cell === void 0 ? [] : [createCell(cell, cellName(column, rowIndex), strings, formats)]);
3670
+ return cells.length === 0 ? [] : [createElement("row", { r: rowIndex + 1 }, cells)];
3671
+ }))]);
3672
+ };
3673
+ /**
3674
+ * The shared strings: each piece of text once. Excel writes `xml:space="preserve"` on text that starts or ends with
3675
+ * white space, though the ISO schema doesn't allow it there, so this does too.
3676
+ */
3677
+ var createSharedStrings = (strings, count) => createElement("sst", {
3678
+ xmlns: SPREADSHEET_NAMESPACE,
3679
+ count,
3680
+ uniqueCount: strings.length
3681
+ }, strings.map((text) => createElement("si", {}, [/^\s|\s$/.test(text) ? createElement("t", { "xml:space": "preserve" }).addChildElement(text) : createText("t", text)])));
3682
+ /**
3683
+ * The workbook's files, to zip into the embedded package.
3684
+ *
3685
+ * @param sheet - The sheet's cells, row by row
3686
+ */
3687
+ var createWorkbookFiles = (sheet) => {
3688
+ const texts = sheet.flat().filter((cell) => typeof cell === "string");
3689
+ const strings = [...new Set(texts)];
3690
+ const formats = [...new Set(sheet.flat().flatMap((cell) => typeof cell === "object" ? [cell.format] : []))];
3691
+ return [
3692
+ {
3693
+ path: "[Content_Types].xml",
3694
+ content: createContentTypes()
3695
+ },
3696
+ {
3697
+ path: "_rels/.rels",
3698
+ content: createRelationships([["officeDocument", "xl/workbook.xml"]])
3699
+ },
3700
+ {
3701
+ path: "xl/workbook.xml",
3702
+ content: createWorkbook()
3703
+ },
3704
+ {
3705
+ path: "xl/_rels/workbook.xml.rels",
3706
+ content: createRelationships([
3707
+ ["worksheet", "worksheets/sheet1.xml"],
3708
+ ["styles", "styles.xml"],
3709
+ ["sharedStrings", "sharedStrings.xml"]
3710
+ ])
3711
+ },
3712
+ {
3713
+ path: "xl/worksheets/sheet1.xml",
3714
+ content: createWorksheet(sheet, new Map(strings.map((text, index) => [text, index])), formats)
3715
+ },
3716
+ {
3717
+ path: "xl/styles.xml",
3718
+ content: createStyles(formats)
3719
+ },
3720
+ {
3721
+ path: "xl/sharedStrings.xml",
3722
+ content: createSharedStrings(strings, texts.length)
3723
+ }
3724
+ ];
3725
+ };
3726
+ /**
3727
+ * The workbook as a part of the package, with its relationship type and content type, which a chart refers to.
3728
+ *
3729
+ * @param sheet - The sheet's cells, row by row
3730
+ */
3731
+ var createWorkbookPart = (sheet) => new PackagePart({
3732
+ folder: "embeddings",
3733
+ name: "Microsoft_Excel_Worksheet",
3734
+ extension: "xlsx",
3735
+ contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
3736
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package",
3737
+ content: { files: createWorkbookFiles(sheet) }
3738
+ });
3739
+ //#endregion
3740
+ //#region src/charts/chart-run.ts
3741
+ /**
3742
+ * Chart run module: native Word charts, drawn by the application from their data.
3743
+ *
3744
+ * Reference: http://officeopenxml.com/drwOverview.php
3745
+ *
3746
+ * @module
3747
+ */
3748
+ /**
3749
+ * Represents a chart in a WordprocessingML document: a column, bar, line, area, pie, doughnut, pie of pie, bar of pie,
3750
+ * radar, scatter, bubble or stock chart, drawn by Word from its data in the document's theme, as a chart made with
3751
+ * Word's Insert Chart is. A column, line or area chart's series can each be drawn another way, as Word's "Combo" charts
3752
+ * are.
3753
+ *
3754
+ * The chart is a part of its own (`word/charts/chart1.xml`), with its data in an embedded workbook, so Word's "Edit
3755
+ * Data" opens it in Excel. It sits inline with text unless `floating` is set, and goes in a paragraph, including in a
3756
+ * table, header, footer or footnote. Without a description in its `altText`, the chart is described for screen readers
3757
+ * from its data.
3758
+ *
3759
+ * Reference: http://officeopenxml.com/drwOverview.php
3760
+ *
3761
+ * @publicApi
3762
+ *
3763
+ * @example
3764
+ * ```typescript
3765
+ * new Paragraph({
3766
+ * children: [
3767
+ * new ChartRun({
3768
+ * type: "column",
3769
+ * title: "Sales",
3770
+ * categories: ["Jan", "Feb", "Mar"],
3771
+ * series: [
3772
+ * { name: "2024", values: [10, 20, 30] },
3773
+ * { name: "2025", values: [15, 25, null] },
3774
+ * ],
3775
+ * }),
3776
+ * ],
3777
+ * });
3778
+ * ```
3779
+ */
3780
+ var ChartRun = class extends Run {
3781
+ /**
3782
+ * @throws If there are no series or categories, a value isn't a finite number or null, a series has more values
3783
+ * than there are categories or an option the way it is drawn doesn't have, a pie chart has more than one series or
3784
+ * a pie or doughnut chart a negative value, a scatter or bubble point isn't finite numbers, a data label position
3785
+ * isn't one the chart's type has, a trendline can't be fitted to its series' values, a stock chart's high is below
3786
+ * its low, a hidden legend entry isn't one of the legend's, or an option is out of its range
3787
+ */
3788
+ constructor(options) {
3789
+ var _options$transformati;
3790
+ super(_objectSpread2(_objectSpread2({}, options.run), {}, {
3791
+ break: void 0,
3792
+ text: void 0,
3793
+ children: void 0
3794
+ }));
3795
+ const data = createChartData(options);
3796
+ const workbook = createWorkbookPart(data.sheet);
3797
+ const chart = new PackagePart({
3798
+ folder: "charts",
3799
+ name: "chart",
3800
+ extension: "xml",
3801
+ contentType: "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
3802
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
3803
+ content: createChartSpace(options, data, workbook)
3804
+ });
3805
+ this.root.push(new Drawing({
3806
+ type: "graphic",
3807
+ uri: CHART_NAMESPACE,
3808
+ transformation: createTransformation((_options$transformati = options.transformation) !== null && _options$transformati !== void 0 ? _options$transformati : DEFAULT_CHART_SIZE),
3809
+ content: new PartReference("c:chart", chart, { namespaces: {
3810
+ c: CHART_NAMESPACE,
3811
+ r: RELATIONSHIPS_NAMESPACE
3812
+ } }),
3813
+ lockAspectRatio: false
3814
+ }, {
3815
+ floating: options.floating,
3816
+ docProperties: chartAltText(options),
3817
+ decorative: options.decorative
3818
+ }));
3819
+ }
3820
+ };
3821
+ //#endregion
3822
+ //#region src/charts/template/template-xml.ts
3823
+ /**
3824
+ * An element's name, such as "c:ser", or "" for text and comments, which have none.
3825
+ */
3826
+ var nameOf = (element) => {
3827
+ var _element$name;
3828
+ return (_element$name = element.name) !== null && _element$name !== void 0 ? _element$name : "";
3829
+ };
3830
+ /**
3831
+ * The child elements of an element, without its text and comments.
3832
+ */
3833
+ var elementsOf = (element) => {
3834
+ var _element$elements;
3835
+ return ((_element$elements = element === null || element === void 0 ? void 0 : element.elements) !== null && _element$elements !== void 0 ? _element$elements : []).filter((child) => child.type === "element");
3836
+ };
3837
+ /**
3838
+ * The child elements with a name, such as each `c:ser` of a `c:barChart`.
3839
+ */
3840
+ var childrenOf = (element, name) => elementsOf(element).filter((child) => child.name === name);
3841
+ /**
3842
+ * The first child element with a name.
3843
+ */
3844
+ var childOf = (element, name) => elementsOf(element).find((child) => child.name === name);
3845
+ /**
3846
+ * Every element under an element with a name, in document order.
3847
+ */
3848
+ var descendantsOf = (element, name) => elementsOf(element).flatMap((child) => [...child.name === name ? [child] : [], ...descendantsOf(child, name)]);
3849
+ /**
3850
+ * An attribute's value, as text.
3851
+ */
3852
+ var attributeOf = (element, name) => {
3853
+ var _element$attributes;
3854
+ const value = element === null || element === void 0 || (_element$attributes = element.attributes) === null || _element$attributes === void 0 ? void 0 : _element$attributes[name];
3855
+ return value === void 0 ? void 0 : String(value);
3856
+ };
3857
+ /**
3858
+ * An element's `val` attribute, such as "col" for `<c:barDir val="col"/>`.
3859
+ */
3860
+ var valueOf = (element) => attributeOf(element, "val");
3861
+ /**
3862
+ * An element's `val` attribute as a whole number, or undefined if it has none, as in `<c:idx val="2"/>`.
3863
+ */
3864
+ var numberOf = (element) => {
3865
+ var _valueOf;
3866
+ const value = Number(valueOf(element));
3867
+ return ((_valueOf = valueOf(element)) === null || _valueOf === void 0 ? void 0 : _valueOf.trim()) && Number.isInteger(value) ? value : void 0;
3868
+ };
3869
+ /**
3870
+ * An element's text, and its children's.
3871
+ */
3872
+ var textOf = (element) => {
3873
+ var _element$elements2;
3874
+ return ((_element$elements2 = element === null || element === void 0 ? void 0 : element.elements) !== null && _element$elements2 !== void 0 ? _element$elements2 : []).map((child) => {
3875
+ if (child.type === "text") {
3876
+ var _child$text;
3877
+ return String((_child$text = child.text) !== null && _child$text !== void 0 ? _child$text : "");
3878
+ }
3879
+ if (child.type === "cdata") {
3880
+ var _child$cdata;
3881
+ return String((_child$cdata = child.cdata) !== null && _child$cdata !== void 0 ? _child$cdata : "");
3882
+ }
3883
+ return child.type === "element" ? textOf(child) : "";
3884
+ }).join("");
3885
+ };
3886
+ /**
3887
+ * A copy of an element, which can be changed without changing it.
3888
+ */
3889
+ var copyOf = (element) => JSON.parse(JSON.stringify(element));
3890
+ /**
3891
+ * An element with other children.
3892
+ */
3893
+ var withChildren = (element, children) => _objectSpread2(_objectSpread2({}, element), {}, { elements: [...children] });
3894
+ /**
3895
+ * An element with its children changed: each is replaced by what the function gives, which can be none or several.
3896
+ * Text and comments are kept.
3897
+ */
3898
+ var mapChildren = (element, change) => {
3899
+ var _element$elements3;
3900
+ return withChildren(element, ((_element$elements3 = element.elements) !== null && _element$elements3 !== void 0 ? _element$elements3 : []).flatMap((child) => child.type === "element" ? change(child) : [child]));
3901
+ };
3902
+ /**
3903
+ * An element without the child elements a test picks.
3904
+ */
3905
+ var withoutChildren = (element, remove) => mapChildren(element, (child) => remove(child) ? [] : [child]);
3906
+ /**
3907
+ * An element with other attributes, which are added to or replace its own. An undefined value removes the attribute.
3908
+ */
3909
+ var withAttributes = (element, attributes) => {
3910
+ const all = _objectSpread2(_objectSpread2({}, element.attributes), attributes);
3911
+ return _objectSpread2(_objectSpread2({}, element), {}, { attributes: Object.fromEntries(Object.entries(all).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]])) });
3912
+ };
3913
+ /**
3914
+ * An element with a child in its place in the schema's order: in place of its child of the same name, or before its
3915
+ * first child that comes after it. Children the order doesn't name keep their places.
3916
+ *
3917
+ * @param order - The names of the element's children, in the schema's order, which includes the child's name
3918
+ */
3919
+ var withChild = (element, child, order) => {
3920
+ var _element$elements4;
3921
+ const children = (_element$elements4 = element.elements) !== null && _element$elements4 !== void 0 ? _element$elements4 : [];
3922
+ const same = children.findIndex((existing) => existing.type === "element" && existing.name === child.name);
3923
+ if (same !== -1) return withChildren(element, children.map((existing, index) => index === same ? child : existing));
3924
+ const rank = order.indexOf(nameOf(child));
3925
+ const next = children.findIndex((existing) => existing.type === "element" && order.indexOf(nameOf(existing)) > rank);
3926
+ return withChildren(element, next === -1 ? [...children, child] : [
3927
+ ...children.slice(0, next),
3928
+ child,
3929
+ ...children.slice(next)
3930
+ ]);
3931
+ };
3932
+ /**
3933
+ * A new element.
3934
+ */
3935
+ var createXmlElement = (name, attributes = {}, children = []) => _objectSpread2(_objectSpread2({
3936
+ type: "element",
3937
+ name
3938
+ }, Object.keys(attributes).length > 0 ? { attributes: _objectSpread2({}, attributes) } : {}), children.length > 0 ? { elements: [...children] } : {});
3939
+ //#endregion
3940
+ //#region src/charts/template/template-chart.ts
3941
+ var barType = (group) => valueOf(childOf(group, "c:barDir")) === "bar" ? "bar" : "column";
3942
+ var GROUPS = /* @__PURE__ */ new Map([
3943
+ ["c:barChart", barType],
3944
+ ["c:bar3DChart", barType],
3945
+ ["c:lineChart", () => "line"],
3946
+ ["c:line3DChart", () => "line"],
3947
+ ["c:areaChart", () => "area"],
3948
+ ["c:area3DChart", () => "area"],
3949
+ ["c:pieChart", () => "pie"],
3950
+ ["c:pie3DChart", () => "pie"],
3951
+ ["c:ofPieChart", (group) => valueOf(childOf(group, "c:ofPieType")) === "bar" ? "barOfPie" : "pieOfPie"],
3952
+ ["c:doughnutChart", () => "doughnut"],
3953
+ ["c:radarChart", () => "radar"],
3954
+ ["c:scatterChart", () => "scatter"],
3955
+ ["c:bubbleChart", () => "bubble"],
3956
+ ["c:stockChart", () => "stock"]
3957
+ ]);
3958
+ var UNSUPPORTED_GROUPS = /* @__PURE__ */ new Map([["c:surfaceChart", "a surface chart"], ["c:surface3DChart", "a 3-D surface chart"]]);
3959
+ var WHOLE_CHART_TYPES = [
3960
+ "pie",
3961
+ "doughnut",
3962
+ "pieOfPie",
3963
+ "barOfPie",
3964
+ "radar",
3965
+ "stock"
3966
+ ];
3967
+ var PIE_TYPES$1 = [
3968
+ "pie",
3969
+ "doughnut",
3970
+ "pieOfPie",
3971
+ "barOfPie"
3972
+ ];
3973
+ var kindOf = (type) => {
3974
+ switch (type) {
3975
+ case "scatter":
3976
+ case "bubble": return type;
3977
+ default: return "category";
3978
+ }
3979
+ };
3980
+ /**
3981
+ * Whether a group's points each have their own colour. Office varies them unless told not to on pie and doughnut
3982
+ * charts, and doesn't on the others, when there is no `c:varyColors`. A `c:varyColors` without a value is true, as in
3983
+ * the schema.
3984
+ */
3985
+ var variesColors = (group, type) => {
3986
+ const varyColors = childOf(group, "c:varyColors");
3987
+ if (varyColors === void 0) return PIE_TYPES$1.includes(type);
3988
+ const value = valueOf(varyColors);
3989
+ return value === void 0 || value === "1" || value === "true";
3990
+ };
3991
+ /**
3992
+ * The text of the chart's own title: each paragraph's runs and fields, a line each. A title Office writes from a
3993
+ * single series' name, or linked to a cell, has none.
3994
+ */
3995
+ var titleOf = (chart) => {
3996
+ const rich = childOf(childOf(childOf(chart, "c:title"), "c:tx"), "c:rich");
3997
+ return rich === void 0 ? void 0 : childrenOf(rich, "a:p").map((paragraph) => descendantsOf(paragraph, "a:t").map(textOf).join("")).join("\n");
3998
+ };
3999
+ /**
4000
+ * Reads a chart part's chart.
4001
+ *
4002
+ * @throws If the chart is a pivot chart, has no plot area or series groups, has a group this can't patch, such as a
4003
+ * stock chart, or combines series with categories with series with points
4004
+ */
4005
+ var readTemplateChart = (chartSpace) => {
4006
+ var _groups$find$type, _groups$find;
4007
+ if (childOf(chartSpace, "c:pivotSource") !== void 0) throw new Error("It is a pivot chart, whose data is a pivot table in its workbook");
4008
+ const chart = childOf(chartSpace, "c:chart");
4009
+ const plotArea = childOf(chart, "c:plotArea");
4010
+ if (chart === void 0 || plotArea === void 0) throw new Error("Its chart part has no plot area (c:chart and c:plotArea)");
4011
+ const groups = elementsOf(plotArea).filter((element) => nameOf(element).endsWith("Chart")).map((element) => {
4012
+ const name = nameOf(element);
4013
+ const unsupported = UNSUPPORTED_GROUPS.get(name);
4014
+ if (unsupported !== void 0) throw new Error(`It is ${unsupported}, which ChartDataPatch can't patch`);
4015
+ const typeOf = GROUPS.get(name);
4016
+ if (typeOf === void 0) throw new Error(`It has a group of series of a type ChartDataPatch doesn't know (${name})`);
4017
+ const groupType = typeOf(element);
4018
+ return {
4019
+ element,
4020
+ kind: kindOf(groupType),
4021
+ type: groupType,
4022
+ varyColors: variesColors(element, groupType)
4023
+ };
4024
+ });
4025
+ if (groups.length === 0) throw new Error("Its plot area has no series groups, such as c:barChart");
4026
+ const kinds = [...new Set(groups.map(({ kind }) => kind))];
4027
+ if (kinds.length > 1) throw new Error("It combines a scatter or bubble chart, whose series have points, with another type, whose series have categories, which ChartDataPatch can't patch");
4028
+ const series = groups.flatMap((group) => childrenOf(group.element, "c:ser").map((element) => ({
4029
+ element,
4030
+ group,
4031
+ index: numberOf(childOf(element, "c:idx")),
4032
+ order: numberOf(childOf(element, "c:order"))
4033
+ }))).map((one, position) => ({
4034
+ one,
4035
+ position
4036
+ })).sort((a, b) => {
4037
+ var _a$one$order, _b$one$order;
4038
+ return ((_a$one$order = a.one.order) !== null && _a$one$order !== void 0 ? _a$one$order : Infinity) - ((_b$one$order = b.one.order) !== null && _b$one$order !== void 0 ? _b$one$order : Infinity) || a.position - b.position;
4039
+ }).map(({ one }) => one);
4040
+ const type = (_groups$find$type = (_groups$find = groups.find((group) => WHOLE_CHART_TYPES.includes(group.type))) === null || _groups$find === void 0 ? void 0 : _groups$find.type) !== null && _groups$find$type !== void 0 ? _groups$find$type : groups[0].type;
4041
+ const stock = groups.find((group) => group.type === "stock");
4042
+ if (stock !== void 0) {
4043
+ const prices = childrenOf(stock.element, "c:ser").length;
4044
+ if (prices !== 3 && prices !== 4) throw new Error(`It is a stock chart with ${prices} series of prices. A stock chart has 3, or 4 with opening prices`);
4045
+ const others = groups.filter((group) => group !== stock);
4046
+ if (others.length > 1 || others.some((group) => group.type !== "column" || childrenOf(group.element, "c:ser").length !== 1)) throw new Error("It is a stock chart combined with a chart other than its volumes' columns, which ChartDataPatch can't patch");
4047
+ }
4048
+ return {
4049
+ chartSpace,
4050
+ chart,
4051
+ plotArea,
4052
+ groups,
4053
+ series,
4054
+ kind: kinds[0],
4055
+ type,
4056
+ title: titleOf(chart)
4057
+ };
4058
+ };
4059
+ /**
4060
+ * The number of points the series' values had in the template, from their cache.
4061
+ */
4062
+ var pointCountOf = (series) => {
4063
+ var _childOf, _numberOf;
4064
+ return (_numberOf = numberOf(descendantsOf((_childOf = childOf(series, "c:val")) !== null && _childOf !== void 0 ? _childOf : childOf(series, "c:yVal"), "c:ptCount")[0])) !== null && _numberOf !== void 0 ? _numberOf : 0;
4065
+ };
4066
+ /**
4067
+ * The number format of a series' data in the template, from its cache, such as "0%", or undefined for "General".
4068
+ *
4069
+ * @param name - The data: `c:cat`, `c:val`, `c:xVal`, `c:yVal` or `c:bubbleSize`
4070
+ */
4071
+ var formatCodeOf = (series, name) => {
4072
+ const [format] = descendantsOf(childOf(series, name), "c:formatCode");
4073
+ const code = format === void 0 ? "" : textOf(format).trim();
4074
+ return code === "" || code.toLowerCase() === "general" ? void 0 : code;
4075
+ };
4076
+ /**
4077
+ * Whether an Excel number format writes a date or time, such as "d mmm yyyy" or "[h]:mm", rather than a number, such as
4078
+ * "#,##0" or "0.0%". Quoted and escaped text, and colours and conditions in brackets, are left out.
4079
+ */
4080
+ var isDateFormat = (code) => /\[(h+|m+|s+)\]/i.test(code) || /[dmyhs]/i.test(code.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").replace(/[_*]./g, ""));
4081
+ //#endregion
4082
+ //#region src/charts/template/template-series.ts
4083
+ /**
4084
+ * The children of every type of series, in the schema's order (`CT_BarSer`, `CT_LineSer`, `CT_AreaSer`, `CT_PieSer`,
4085
+ * `CT_RadarSer`, `CT_ScatterSer` and `CT_BubbleSer`), as one order all of them keep.
4086
+ */
4087
+ var SERIES_ORDER = [
4088
+ "c:idx",
4089
+ "c:order",
4090
+ "c:tx",
4091
+ "c:spPr",
4092
+ "c:invertIfNegative",
4093
+ "c:pictureOptions",
4094
+ "c:marker",
4095
+ "c:explosion",
4096
+ "c:dPt",
4097
+ "c:dLbls",
4098
+ "c:trendline",
4099
+ "c:errBars",
4100
+ "c:cat",
4101
+ "c:xVal",
4102
+ "c:val",
4103
+ "c:yVal",
4104
+ "c:shape",
4105
+ "c:smooth",
4106
+ "c:bubbleSize",
4107
+ "c:bubble3D",
4108
+ "c:extLst"
4109
+ ];
4110
+ /**
4111
+ * The children of a point's own look (`CT_DPt`), in the schema's order.
4112
+ */
4113
+ var POINT_ORDER = [
4114
+ "c:idx",
4115
+ "c:invertIfNegative",
4116
+ "c:marker",
4117
+ "c:bubble3D",
4118
+ "c:explosion",
4119
+ "c:spPr",
4120
+ "c:pictureOptions",
4121
+ "c:extLst"
4122
+ ];
4123
+ var COLORS = /* @__PURE__ */ new Set([
4124
+ "a:srgbClr",
4125
+ "a:schemeClr",
4126
+ "a:scrgbClr",
4127
+ "a:hslClr",
4128
+ "a:sysClr",
4129
+ "a:prstClr"
4130
+ ]);
4131
+ var colorKey = (color) => JSON.stringify(color, (key, value) => key === "elements" && Array.isArray(value) ? value.filter((child) => !(child.type === "text" && String(child.text).trim() === "")) : value);
4132
+ var firstColorIn = (element) => elementsOf(element).reduce((found, child) => found !== null && found !== void 0 ? found : COLORS.has(nameOf(child)) ? child : firstColorIn(child), void 0);
4133
+ /**
4134
+ * The main colour of a series or a point: the first colour of its shape properties' fill or line, or else of its
4135
+ * marker's.
4136
+ */
4137
+ var mainColorOf = (element) => {
4138
+ var _firstColorIn;
4139
+ return (_firstColorIn = firstColorIn(childOf(element, "c:spPr"))) !== null && _firstColorIn !== void 0 ? _firstColorIn : firstColorIn(childOf(childOf(element, "c:marker"), "c:spPr"));
4140
+ };
4141
+ /**
4142
+ * Replaces a colour, wherever it is in an element, with another. The old colour's transparency (`a:alpha`) is kept,
4143
+ * unless the new one has its own.
4144
+ */
4145
+ var recolor = (element, from, to) => {
4146
+ var _to$elements;
4147
+ const key = colorKey(from);
4148
+ const alpha = childOf(from, "a:alpha");
4149
+ const replacement = alpha !== void 0 && childOf(to, "a:alpha") === void 0 ? _objectSpread2(_objectSpread2({}, to), {}, { elements: [...(_to$elements = to.elements) !== null && _to$elements !== void 0 ? _to$elements : [], alpha] }) : to;
4150
+ const change = (current) => mapChildren(current, (child) => [COLORS.has(nameOf(child)) && colorKey(child) === key ? copyOf(replacement) : change(child)]);
4151
+ return change(element);
4152
+ };
4153
+ /**
4154
+ * A series or point in another colour: its main colour, in its shape properties and its marker's, replaced with another.
4155
+ */
4156
+ var withColor = (element, color) => {
4157
+ const main = mainColorOf(element);
4158
+ if (main === void 0) return element;
4159
+ return mapChildren(element, (child) => {
4160
+ if (child.name === "c:spPr") return [recolor(child, main, color)];
4161
+ return [child.name === "c:marker" ? mapChildren(child, (inner) => [inner.name === "c:spPr" ? recolor(inner, main, color) : inner]) : child];
4162
+ });
4163
+ };
4164
+ /**
4165
+ * An element without Office's unique id of it (`c16:uniqueId`), which a copy can't share, and its extension list if
4166
+ * that leaves it empty.
4167
+ */
4168
+ var withoutUniqueId = (element) => mapChildren(element, (child) => {
4169
+ if (child.name !== "c:extLst") return [child];
4170
+ const extensions = withoutChildren(child, (extension) => descendantsOf(extension, "c16:uniqueId").length > 0);
4171
+ return elementsOf(extensions).length === 0 ? [] : [extensions];
4172
+ });
4173
+ var indexOf = (element) => {
4174
+ var _numberOf;
4175
+ return (_numberOf = numberOf(childOf(element, "c:idx"))) !== null && _numberOf !== void 0 ? _numberOf : 0;
4176
+ };
4177
+ /**
4178
+ * A series with its index (`c:idx`) and plot order (`c:order`).
4179
+ */
4180
+ var withIndex = (series, index, order) => withChild(withChild(series, createXmlElement("c:idx", { val: index }), SERIES_ORDER), createXmlElement("c:order", { val: order }), SERIES_ORDER);
4181
+ /**
4182
+ * A series with new data: its name (`c:tx`), categories (`c:cat` or `c:xVal`), values (`c:val` or `c:yVal`) and sizes
4183
+ * (`c:bubbleSize`), each in place of the series' own or, if it has none, in its place in the schema's order.
4184
+ */
4185
+ var withData = (series, data) => data.reduce((current, element) => withChild(current, element, SERIES_ORDER), series);
4186
+ /**
4187
+ * A series without the points' own looks and labels (`c:dPt` and `c:dLbl`) past its last point.
4188
+ */
4189
+ var withoutPointsPast = (series, count) => mapChildren(series, (child) => {
4190
+ if (child.name === "c:dPt") return indexOf(child) < count ? [child] : [];
4191
+ return [child.name === "c:dLbls" ? withoutChildren(child, (label) => label.name === "c:dLbl" && indexOf(label) >= count) : child];
4192
+ });
4193
+ /**
4194
+ * A series whose points each have a look of their own, such as the slices of a pie, with a look for each new point: a
4195
+ * copy of the last point's, in the next colour, and pulled out of the pie only if every point is, as far. A series whose points don't all have one is left as it is, as the
4196
+ * points without one take the series' look.
4197
+ *
4198
+ * @param count - The number of points it has now
4199
+ * @param templateCount - The number it had in the template
4200
+ * @param colorOf - The colour of a point, by its index
4201
+ */
4202
+ var withPointsUpTo = (series, count, templateCount, colorOf) => {
4203
+ const points = childrenOf(series, "c:dPt");
4204
+ const indexes = new Set(points.map(indexOf));
4205
+ const last = points.find((point) => indexOf(point) === templateCount - 1);
4206
+ if (count <= templateCount || last === void 0 || !Array.from({ length: templateCount }, (_, index) => index).every((index) => indexes.has(index))) return series;
4207
+ const model = new Set(points.map((point) => valueOf(childOf(point, "c:explosion")))).size === 1 ? withoutUniqueId(last) : withoutChildren(withoutUniqueId(last), (child) => child.name === "c:explosion");
4208
+ const added = Array.from({ length: count - templateCount }, (_, offset) => {
4209
+ const point = templateCount + offset;
4210
+ return withColor(withChild(copyOf(model), createXmlElement("c:idx", { val: point }), POINT_ORDER), colorOf(point));
4211
+ });
4212
+ const lastPoint = points[points.length - 1];
4213
+ return mapChildren(series, (child) => child === lastPoint ? [child, ...added] : [child]);
4214
+ };
4215
+ /**
4216
+ * A new series with the look of the template's last series: a copy of it with its own colour, and without what was the
4217
+ * last series' own, which are its unique id, trendlines, error bars and its points' own labels, and unless its points
4218
+ * are the categories' colours, as in a pie or doughnut chart, its points' own looks.
4219
+ *
4220
+ * @param keepPointColors - Whether its points' own looks are the categories' colours, and are kept
4221
+ * @param color - The new series' colour
4222
+ */
4223
+ var copySeries = (model, keepPointColors, color) => {
4224
+ const copy = mapChildren(withoutUniqueId(model), (child) => {
4225
+ switch (child.name) {
4226
+ case "c:trendline":
4227
+ case "c:errBars": return [];
4228
+ case "c:dPt": return keepPointColors ? [withoutUniqueId(child)] : [];
4229
+ case "c:dLbls": return [withoutChildren(child, (label) => label.name === "c:dLbl")];
4230
+ default: return [child];
4231
+ }
4232
+ });
4233
+ return keepPointColors ? copy : withColor(copy, color);
4234
+ };
4235
+ //#endregion
4236
+ //#region src/charts/template/patch-chart.ts
4237
+ /**
4238
+ * The children of a chart part's root (`CT_ChartSpace`), in the schema's order.
4239
+ */
4240
+ var CHART_SPACE_ORDER = [
4241
+ "c:date1904",
4242
+ "c:lang",
4243
+ "c:roundedCorners",
4244
+ "c:style",
4245
+ "c:clrMapOvr",
4246
+ "c:pivotSource",
4247
+ "c:protection",
4248
+ "c:chart",
4249
+ "c:spPr",
4250
+ "c:txPr",
4251
+ "c:externalData",
4252
+ "c:printSettings",
4253
+ "c:userShapes",
4254
+ "c:extLst"
4255
+ ];
4256
+ var BEFORE_SERIES = /* @__PURE__ */ new Set([
4257
+ "c:barDir",
4258
+ "c:grouping",
4259
+ "c:varyColors",
4260
+ "c:radarStyle",
4261
+ "c:scatterStyle",
4262
+ "c:ofPieType"
4263
+ ]);
4264
+ var AXES = /* @__PURE__ */ new Set([
4265
+ "c:valAx",
4266
+ "c:catAx",
4267
+ "c:dateAx",
4268
+ "c:serAx"
4269
+ ]);
4270
+ var DATE_AXIS_ONLY = /* @__PURE__ */ new Set([
4271
+ "c:baseTimeUnit",
4272
+ "c:majorUnit",
4273
+ "c:majorTimeUnit",
4274
+ "c:minorUnit",
4275
+ "c:minorTimeUnit"
4276
+ ]);
4277
+ var TIME_UNITS = [
4278
+ "days",
4279
+ "months",
4280
+ "years"
4281
+ ];
4282
+ /**
4283
+ * A group with its series: the template's, patched, and after them, new ones. A group without series of its own has
4284
+ * the new ones after its `c:varyColors` and the like.
4285
+ */
4286
+ var withSeries = (group, patched, added) => {
4287
+ var _group$elements;
4288
+ const children = (_group$elements = group.elements) !== null && _group$elements !== void 0 ? _group$elements : [];
4289
+ const isSeries = (child) => child.type === "element" && child.name === "c:ser";
4290
+ const last = children.reduce((found, child, index) => isSeries(child) ? index : found, -1);
4291
+ if (last === -1) {
4292
+ const before = children.reduce((found, child, index) => BEFORE_SERIES.has(nameOf(child)) ? index : found, -1);
4293
+ return withChildren(group, [
4294
+ ...children.slice(0, before + 1),
4295
+ ...added,
4296
+ ...children.slice(before + 1)
4297
+ ]);
4298
+ }
4299
+ return withChildren(group, children.flatMap((child, index) => {
4300
+ if (!isSeries(child)) return [child];
4301
+ const own = patched.get(child);
4302
+ return [...own === void 0 ? [] : [own], ...index === last ? added : []];
4303
+ }));
4304
+ };
4305
+ /**
4306
+ * A date axis as a category axis, for categories that aren't dates.
4307
+ */
4308
+ var asCategoryAxis = (axis) => _objectSpread2(_objectSpread2({}, withoutChildren(axis, (child) => DATE_AXIS_ONLY.has(nameOf(child)))), {}, { name: "c:catAx" });
4309
+ /**
4310
+ * A date axis spacing its dates by the new dates' unit, if it spaced them by a longer one, so no two fall together.
4311
+ */
4312
+ var withTimeUnit = (axis, unit) => mapChildren(axis, (child) => {
4313
+ var _valueOf;
4314
+ return child.name === "c:baseTimeUnit" && TIME_UNITS.indexOf((_valueOf = valueOf(child)) !== null && _valueOf !== void 0 ? _valueOf : "days") > TIME_UNITS.indexOf(unit) ? [createXmlElement("c:baseTimeUnit", { val: unit })] : [child];
4315
+ });
4316
+ var PIE_TYPES = [
4317
+ "pie",
4318
+ "doughnut",
4319
+ "pieOfPie",
4320
+ "barOfPie"
4321
+ ];
4322
+ /**
4323
+ * A pie of pie or bar of pie chart whose own split (`c:custSplit`) has only the slices it has now.
4324
+ */
4325
+ var withSplitUpTo = (group, count) => mapChildren(group, (child) => [child.name === "c:custSplit" ? withoutChildren(child, (point) => {
4326
+ var _numberOf;
4327
+ return point.name === "c:secondPiePt" && !(((_numberOf = numberOf(point)) !== null && _numberOf !== void 0 ? _numberOf : count) < count);
4328
+ }) : child]);
4329
+ var maxOf = (values) => values.reduce((max, value) => value === void 0 ? max : Math.max(max, value), -1);
4330
+ /**
4331
+ * The chart part's root with the new data.
4332
+ *
4333
+ * @param format - Formats `docx/charts`' XML as the template's parts are parsed
4334
+ * @param createSeries - Creates the series `docx/charts` would write for the new data, for a chart that has none to copy
4335
+ * @returns The new root, and the elements of the new data, which refer to the new workbook
4336
+ */
4337
+ var patchChartSpace = (chart, data, format, createSeries) => {
4338
+ var _model$group, _kept$0$group, _kept$;
4339
+ const references = /* @__PURE__ */ new Set();
4340
+ const formatData = (content) => {
4341
+ const element = format(content);
4342
+ references.add(element);
4343
+ return element;
4344
+ };
4345
+ const dataOf = (series) => [
4346
+ formatData(createSeriesName(series.name)),
4347
+ formatData(createDataSource(chart.kind === "category" ? "c:cat" : "c:xVal", series.categories)),
4348
+ formatData(createDataSource(chart.kind === "category" ? "c:val" : "c:yVal", series.values)),
4349
+ ...chart.kind === "bubble" && series.sizes ? [formatData(createDataSource("c:bubbleSize", series.sizes))] : []
4350
+ ];
4351
+ const colorOf = (index) => format(createSeriesColor(index));
4352
+ const patch = (element, { varyColors }, series, templateCount) => {
4353
+ const count = series.values.points.length;
4354
+ const withNewData = withoutPointsPast(withData(element, dataOf(series)), count);
4355
+ return varyColors ? withPointsUpTo(withNewData, count, templateCount, colorOf) : withNewData;
4356
+ };
4357
+ const kept = chart.series.slice(0, data.series.length);
4358
+ const patched = new Map(kept.map((own, index) => [own.element, patch(own.element, own.group, data.series[index], pointCountOf(own.element))]));
4359
+ const model = chart.series[chart.series.length - 1];
4360
+ const group = (_model$group = model === null || model === void 0 ? void 0 : model.group) !== null && _model$group !== void 0 ? _model$group : chart.groups[0];
4361
+ const created = model === void 0 && data.series.length > 0 ? createSeries() : [];
4362
+ const firstIndex = maxOf(chart.series.map(({ index }) => index)) + 1;
4363
+ const firstOrder = maxOf(chart.series.map(({ order }) => order)) + 1;
4364
+ const added = data.series.slice(kept.length).map((series, offset) => {
4365
+ const position = kept.length + offset;
4366
+ const base = model === void 0 ? created[position] : withIndex(copySeries(model.element, PIE_TYPES.includes(group.type), colorOf(position)), firstIndex + offset, firstOrder + offset);
4367
+ return patch(base, group, series, model === void 0 ? 0 : pointCountOf(model.element));
4368
+ });
4369
+ const groups = new Map(chart.groups.map(({ element }) => {
4370
+ const withNewSeries = withSeries(element, patched, element === group.element ? added : []);
4371
+ return [element, element.name === "c:ofPieChart" ? withSplitUpTo(withNewSeries, data.series[0].values.points.length) : withNewSeries];
4372
+ }));
4373
+ const removed = new Set(chart.groups.filter(({ element }) => childrenOf(element, "c:ser").length > 0 && childrenOf(groups.get(element), "c:ser").length === 0).map(({ element }) => element));
4374
+ const axesOf = (element) => childrenOf(element, "c:axId").flatMap((axis) => {
4375
+ const id = valueOf(axis);
4376
+ return id === void 0 ? [] : [id];
4377
+ });
4378
+ const usedAxes = new Set(chart.groups.filter(({ element }) => !removed.has(element)).flatMap(({ element }) => axesOf(element)));
4379
+ const unusedAxes = new Set([...removed].flatMap(axesOf).filter((axis) => !usedAxes.has(axis)));
4380
+ const plotArea = mapChildren(chart.plotArea, (child) => {
4381
+ const patchedGroup = groups.get(child);
4382
+ if (patchedGroup !== void 0) return removed.has(child) ? [] : [patchedGroup];
4383
+ const id = valueOf(childOf(child, "c:axId"));
4384
+ if (AXES.has(nameOf(child)) && id !== void 0 && unusedAxes.has(id)) return [];
4385
+ if (child.name === "c:dateAx" && chart.kind === "category") return [data.dates === void 0 ? asCategoryAxis(child) : withTimeUnit(child, data.dates)];
4386
+ return [child];
4387
+ });
4388
+ const single = data.series.length === 1 ? (_kept$0$group = (_kept$ = kept[0]) === null || _kept$ === void 0 ? void 0 : _kept$.group) !== null && _kept$0$group !== void 0 ? _kept$0$group : group : void 0;
4389
+ const entries = (single === null || single === void 0 ? void 0 : single.varyColors) ? data.series[0].values.points.length : data.series.length;
4390
+ const newChart = mapChildren(chart.chart, (child) => {
4391
+ if (child === chart.plotArea) return [plotArea];
4392
+ return [child.name === "c:legend" ? withoutChildren(child, (entry) => {
4393
+ var _numberOf2;
4394
+ return entry.name === "c:legendEntry" && ((_numberOf2 = numberOf(childOf(entry, "c:idx"))) !== null && _numberOf2 !== void 0 ? _numberOf2 : 0) >= entries;
4395
+ }) : child];
4396
+ });
4397
+ const root = mapChildren(chart.chartSpace, (child) => {
4398
+ if (child === chart.chart) return [newChart];
4399
+ return [child.name === "c:date1904" ? withAttributes(child, { val: 0 }) : child];
4400
+ });
4401
+ return {
4402
+ chartSpace: withAttributes(root, Object.fromEntries([
4403
+ ["xmlns:c", CHART_NAMESPACE],
4404
+ ["xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main"],
4405
+ ["xmlns:r", RELATIONSHIPS_NAMESPACE]
4406
+ ].filter(([name]) => attributeOf(root, name) === void 0))),
4407
+ references
4408
+ };
4409
+ };
4410
+ /**
4411
+ * The chart part's root, referring to its workbook by a relationship id, with Word's `c:autoUpdate` if it had no
4412
+ * reference to a workbook.
4413
+ */
4414
+ var withWorkbook = (chartSpace, relationshipId) => {
4415
+ var _relationshipIdAttrib;
4416
+ const externalData = childOf(chartSpace, "c:externalData");
4417
+ if (externalData === void 0) return withChild(chartSpace, createXmlElement("c:externalData", { "r:id": relationshipId }, [createXmlElement("c:autoUpdate", { val: 0 })]), CHART_SPACE_ORDER);
4418
+ const name = (_relationshipIdAttrib = relationshipIdAttributeOf(externalData)) !== null && _relationshipIdAttrib !== void 0 ? _relationshipIdAttrib : "r:id";
4419
+ return mapChildren(chartSpace, (child) => [child === externalData ? withAttributes(child, { [name]: relationshipId }) : child]);
4420
+ };
4421
+ /**
4422
+ * The name of an element's relationship id attribute, such as `r:id`, whatever its prefix.
4423
+ */
4424
+ var relationshipIdAttributeOf = (element) => {
4425
+ var _element$attributes;
4426
+ return Object.keys((_element$attributes = element === null || element === void 0 ? void 0 : element.attributes) !== null && _element$attributes !== void 0 ? _element$attributes : {}).find((name) => name.endsWith(":id") && !name.startsWith("xmlns"));
4427
+ };
4428
+ var REFERENCE = /(^|:)(f|sqref)$/;
4429
+ /**
4430
+ * The first element that refers to cells of the chart's workbook, other than the new data's, with the elements it is in.
4431
+ */
4432
+ var findWorkbookReference = (element, skip, path = []) => elementsOf(element).reduce((found, child) => {
4433
+ if (found !== void 0 || skip.has(child)) return found;
4434
+ return REFERENCE.test(nameOf(child)) ? [...path, child] : findWorkbookReference(child, skip, [...path, child]);
4435
+ }, void 0);
4436
+ /**
4437
+ * Why something that refers to cells of the chart's workbook can't be kept, and what to do in Word.
4438
+ *
4439
+ * @param path - The element that refers to cells, with the elements it is in
4440
+ */
4441
+ var describeWorkbookReference = (path) => {
4442
+ const names = path.map(nameOf);
4443
+ return `${(() => {
4444
+ if (names.some((name) => name.endsWith(":datalabelsRange"))) return "Its data labels show text from cells of its workbook (Word's \"Value From Cells\"). Turn that off in Word";
4445
+ if (names.some((name) => /:filtered/.test(name) || /:categoryFilterException/.test(name))) return "It has series or categories hidden with Word's chart filters. Show them, or remove them in Word's Select Data";
4446
+ if (names.includes("c:errBars")) return "Its error bars' custom values are cells of its workbook. Give them fixed values in Word, or remove them";
4447
+ if (names.includes("c:title")) return "A title is linked to a cell of its workbook. Type the title in Word instead";
4448
+ return names.some((name) => name === "c:dLbl" || name === "c:dLbls" || name === "c:trendlineLbl") ? "A label is linked to a cell of its workbook. Type the label in Word instead" : `Something in it refers to cells of its workbook (${names.join(" > ")})`;
4449
+ })()}: the new data replaces the workbook`;
4450
+ };
4451
+ //#endregion
4452
+ //#region src/charts/chart-data-patch.ts
4453
+ var STOCK_OPTIONS = [
4454
+ "open",
4455
+ "high",
4456
+ "low",
4457
+ "close",
4458
+ "volume"
4459
+ ];
4460
+ var quoted = (value) => typeof value === "string" ? `"${value}"` : String(value);
4461
+ var checkSize = ({ x, y, size }, series) => {
4462
+ if (size !== void 0 && !(typeof size === "number" && size >= 0 && Number.isFinite(size))) throw new Error(`Invalid size ${quoted(size)} of the point at (${x}, ${y}) in series "${series}". Expected a finite number of 0 or more`);
4463
+ };
4464
+ var copyValues = (values) => Array.isArray(values) ? [...values] : values;
4465
+ /**
4466
+ * A copy of the categories, with their dates and groups copied too.
4467
+ */
4468
+ var copyCategories = (categories) => categories.map((category) => {
4469
+ if (category instanceof Date) return new Date(category.getTime());
4470
+ if (typeof category === "object" && category !== null) {
4471
+ const { name, categories: inner } = category;
4472
+ return {
4473
+ name,
4474
+ categories: Array.isArray(inner) ? copyCategories(inner) : inner
4475
+ };
4476
+ }
4477
+ return category;
4478
+ });
4479
+ /**
4480
+ * Checks a stock chart's prices, and copies them.
4481
+ *
4482
+ * @throws If there are no categories, a price is missing or wrong, or a high is below its low, as for `ChartRun`
4483
+ */
4484
+ var readStockOptions = (options) => {
4485
+ const { categories, names, description } = options;
4486
+ if (description !== void 0 && typeof description !== "string") throw new Error(`Invalid description ${quoted(description)}. Expected text`);
4487
+ if (!Array.isArray(categories)) throw new Error("Invalid option categories. A stock chart's prices need categories, one for each price");
4488
+ const copied = _objectSpread2(_objectSpread2({ categories: copyCategories(categories) }, Object.fromEntries(STOCK_OPTIONS.flatMap((option) => options[option] === void 0 ? [] : [[option, copyValues(options[option])]]))), names === void 0 ? {} : { names: _objectSpread2({}, names) });
4489
+ checkChartOptions(_objectSpread2({ type: "stock" }, copied));
4490
+ return {
4491
+ kind: "stock",
4492
+ options: copied,
4493
+ description
4494
+ };
4495
+ };
4496
+ /**
4497
+ * Checks the options, and copies the data.
4498
+ *
4499
+ * @throws If there are no series, a series has no name, has neither values nor points, or has one and other series the
4500
+ * other, series with values have no categories or series with points have them, or the data is wrong, as for
4501
+ * `ChartRun`: see its errors
4502
+ */
4503
+ var readOptions = (options) => {
4504
+ if (typeof options !== "object" || options === null) throw new Error(`Invalid chart data ${quoted(options)}. Expected { categories, series }, or for a scatter or bubble chart, { series }`);
4505
+ const { series, description } = options;
4506
+ const prices = STOCK_OPTIONS.find((option) => option in options);
4507
+ if (series === void 0 && prices !== void 0) return readStockOptions(options);
4508
+ if (prices !== void 0) throw new Error(`Invalid option ${prices}. A stock chart's data is its prices, and another chart's is its series, not both`);
4509
+ if (!Array.isArray(series) || series.length === 0) throw new Error("A chart needs at least one series");
4510
+ if (description !== void 0 && typeof description !== "string") throw new Error(`Invalid description ${quoted(description)}. Expected text`);
4511
+ const shapes = series.map((one, index) => {
4512
+ const { name, values, points } = typeof one === "object" && one !== null ? one : {};
4513
+ if (typeof name !== "string") throw new Error(`Invalid name ${quoted(name)} of series ${index + 1}. Expected text`);
4514
+ if (Array.isArray(values) === Array.isArray(points)) throw new Error(`Series "${name}" needs values, for a chart with categories, or points, for a scatter or bubble chart`);
4515
+ return {
4516
+ name,
4517
+ points: Array.isArray(points)
4518
+ };
4519
+ });
4520
+ const withPoints = shapes.find(({ points }) => points);
4521
+ const withValues = shapes.find(({ points }) => !points);
4522
+ if (withPoints !== void 0 && withValues !== void 0) throw new Error(`Series "${withValues.name}" has values, and series "${withPoints.name}" has points. A chart's series all have values, or all have points`);
4523
+ const { categories } = options;
4524
+ if (withPoints !== void 0) {
4525
+ if (categories !== void 0) throw new Error("Invalid option categories. The series have points, which have their own x values");
4526
+ const pointSeries = series.map(({ name, points }) => ({
4527
+ name,
4528
+ points: points.map((point) => _objectSpread2({}, point))
4529
+ }));
4530
+ checkChartOptions({
4531
+ type: "scatter",
4532
+ series: pointSeries
4533
+ });
4534
+ pointSeries.forEach(({ name, points }) => points.forEach((point) => checkSize(point, name)));
4535
+ return {
4536
+ kind: "points",
4537
+ series: pointSeries,
4538
+ description
4539
+ };
4540
+ }
4541
+ if (!Array.isArray(categories)) throw new Error("Invalid option categories. Series with values need categories, one for each value");
4542
+ const copiedCategories = copyCategories(categories);
4543
+ const copied = series.map(({ name, values }) => ({
4544
+ name,
4545
+ values: [...values]
4546
+ }));
4547
+ checkChartOptions({
4548
+ type: "line",
4549
+ categories: copiedCategories,
4550
+ series: copied
4551
+ });
4552
+ return {
4553
+ kind: "category",
4554
+ categories: copiedCategories,
4555
+ series: copied,
4556
+ description
4557
+ };
4558
+ };
4559
+ var withArticle = (type) => `${type === "area" ? "an" : "a"} ${TYPE_NAMES$1[type]} chart`;
4560
+ /**
4561
+ * A stock chart's options from the template's chart and the new prices, which have to be the same kind of stock chart
4562
+ * as the template's: with opening prices if it has them, and volumes if it has them.
4563
+ *
4564
+ * @throws If the data isn't for a stock chart, or has opening prices or volumes the template's chart doesn't, or not
4565
+ * those it does
4566
+ */
4567
+ var stockOptionsFor = (chart, data, title) => {
4568
+ if (data.kind !== "stock") throw new Error("It is a stock chart, whose data is each category's prices. Give categories, and high, low and close prices");
4569
+ const kinds = [[
4570
+ "open",
4571
+ "opening prices",
4572
+ childrenOf(chart.groups.find(({ type }) => type === "stock").element, "c:ser").length === 4
4573
+ ], [
4574
+ "volume",
4575
+ "volumes",
4576
+ chart.groups.length > 1
4577
+ ]];
4578
+ for (const [option, name, has] of kinds) {
4579
+ const given = data.options[option] !== void 0;
4580
+ if (has && !given) throw new Error(`It is a stock chart with ${name}. Give ${option} too`);
4581
+ if (!has && given) throw new Error(`It is a stock chart without ${name}, so it can't take ${option}`);
4582
+ }
4583
+ return _objectSpread2({
4584
+ type: "stock",
4585
+ title
4586
+ }, data.options);
4587
+ };
4588
+ /**
4589
+ * The options `docx/charts` would draw the new data with in the template's chart's type, which check the data and
4590
+ * describe it.
4591
+ *
4592
+ * @throws If the data isn't for the chart's type: values for a scatter or bubble chart, points for another, or points
4593
+ * without sizes for a bubble chart
4594
+ */
4595
+ var optionsFor = (chart, data) => {
4596
+ var _chart$title;
4597
+ const title = ((_chart$title = chart.title) === null || _chart$title === void 0 ? void 0 : _chart$title.trim()) ? chart.title : void 0;
4598
+ if (chart.type === "stock") return stockOptionsFor(chart, data, title);
4599
+ if (chart.kind === "category") {
4600
+ if (data.kind !== "category") throw new Error(`It is ${withArticle(chart.type)}, whose series have a value for each category. Give categories, and each series values`);
4601
+ return {
4602
+ type: chart.type,
4603
+ title,
4604
+ categories: data.categories,
4605
+ series: data.series
4606
+ };
4607
+ }
4608
+ if (data.kind !== "points") throw new Error(`It is ${withArticle(chart.type)}, whose series have points. Give each series points, with an x and y${chart.kind === "bubble" ? " and a size" : ""}`);
4609
+ if (chart.kind === "scatter") return {
4610
+ type: "scatter",
4611
+ title,
4612
+ series: data.series.map(({ name, points }) => ({
4613
+ name,
4614
+ points: points.map(({ x, y }) => ({
4615
+ x,
4616
+ y
4617
+ }))
4618
+ }))
4619
+ };
4620
+ return {
4621
+ type: "bubble",
4622
+ title,
4623
+ series: data.series.map(({ name, points }) => ({
4624
+ name,
4625
+ points: points.map((point) => {
4626
+ if (!("size" in point) || point.size === void 0) throw new Error(`The point at (${point.x}, ${point.y}) in series "${name}" has no size, and a bubble chart's points each need one`);
4627
+ return point;
4628
+ })
4629
+ }))
4630
+ };
4631
+ };
4632
+ var rangeOf = (formula) => {
4633
+ const [, column, first, last] = /\$([A-Z]+)\$(\d+)(?::\$[A-Z]+\$(\d+))?$/.exec(formula);
4634
+ return {
4635
+ column: columnIndexOf(column),
4636
+ first: Number(first) - 1,
4637
+ last: Number(last !== null && last !== void 0 ? last : first) - 1
4638
+ };
4639
+ };
4640
+ /**
4641
+ * The sheet with a number format on the cells a reference refers to.
4642
+ */
4643
+ var withCellFormat = (sheet, data) => {
4644
+ if ((data === null || data === void 0 ? void 0 : data.type) !== "number" || data.format === void 0) return sheet;
4645
+ const { format } = data;
4646
+ const { column, first, last } = rangeOf(data.formula);
4647
+ return sheet.map((row, index) => index < first || index > last ? row : row.map((cell, at) => at !== column || cell === void 0 || typeof cell === "string" ? cell : {
4648
+ value: typeof cell === "number" ? cell : cell.value,
4649
+ format
4650
+ }));
4651
+ };
4652
+ /**
4653
+ * The data with the template's number formats, such as "0%", in its caches and cells, as Word keeps a chart's number
4654
+ * formats when its data is edited. Categories keep the template's format if it and the new categories are both dates,
4655
+ * or both other numbers.
4656
+ *
4657
+ * @param unit - The unit the categories are spaced by, if they are dates
4658
+ */
4659
+ var withTemplateFormats = (data, chart, unit) => {
4660
+ const withFormat = (own, format) => own.type === "number" && format !== void 0 ? _objectSpread2(_objectSpread2({}, own), {}, { format }) : own;
4661
+ const categoryFormat = (own, format) => {
4662
+ if (own.type !== "number" || format === void 0 || chart.kind !== "category") return format;
4663
+ return own.format !== void 0 === isDateFormat(format) ? format : void 0;
4664
+ };
4665
+ const series = data.series.map((one, index) => {
4666
+ var _ref, _chart$series$index;
4667
+ const template = (_ref = (_chart$series$index = chart.series[index]) !== null && _chart$series$index !== void 0 ? _chart$series$index : chart.series[chart.series.length - 1]) === null || _ref === void 0 ? void 0 : _ref.element;
4668
+ const categoriesName = chart.kind === "category" ? "c:cat" : "c:xVal";
4669
+ const valuesName = chart.kind === "category" ? "c:val" : "c:yVal";
4670
+ return _objectSpread2(_objectSpread2({}, one), {}, {
4671
+ categories: withFormat(one.categories, categoryFormat(one.categories, formatCodeOf(template, categoriesName))),
4672
+ values: withFormat(one.values, formatCodeOf(template, valuesName))
4673
+ }, one.sizes === void 0 ? {} : { sizes: withFormat(one.sizes, formatCodeOf(template, "c:bubbleSize")) });
4674
+ });
4675
+ const shared = chart.kind === "category" ? series.map((one) => _objectSpread2(_objectSpread2({}, one), {}, { categories: series[0].categories })) : series;
4676
+ return {
4677
+ sheet: shared.reduce((cells, one, index) => [
4678
+ one.values,
4679
+ one.sizes,
4680
+ ...chart.kind === "category" && index > 0 ? [] : [one.categories]
4681
+ ].reduce(withCellFormat, cells), data.sheet),
4682
+ series: shared,
4683
+ dates: unit
4684
+ };
4685
+ };
4686
+ var chartIdOf = (drawing) => {
4687
+ const charts = descendantsOf(drawing, "c:chart");
4688
+ if (charts.length > 1) throw new Error(`It is a group of ${charts.length} charts. Put the placeholder in the alt text of one of them`);
4689
+ if (charts.length === 0) {
4690
+ if (descendantsOf(drawing, "cx:chart").length > 0) throw new Error("It is a chart of a type Office 2016 added, such as a waterfall, histogram or treemap chart, which ChartDataPatch can't patch");
4691
+ if (descendantsOf(drawing, "pic:pic").length > 0) throw new Error("It is a picture, not a chart");
4692
+ if (descendantsOf(drawing, "wps:wsp").length > 0) throw new Error("It is a shape, not a chart");
4693
+ throw new Error("It isn't a chart");
4694
+ }
4695
+ const name = relationshipIdAttributeOf(charts[0]);
4696
+ const id = name === void 0 ? void 0 : attributeOf(charts[0], name);
4697
+ if (!id) throw new Error("Its c:chart has no relationship id (r:id)");
4698
+ return id;
4699
+ };
4700
+ /**
4701
+ * Sets the chart's alt text: a description of the new data, as a description of the template's data no longer fits it,
4702
+ * and its title without the placeholder. A decorative chart isn't described.
4703
+ */
4704
+ var setAltText = ({ properties, placeholder }, description, describe) => {
4705
+ const title = attributeOf(properties, "title");
4706
+ const decorative = descendantsOf(properties, "adec:decorative").some((element) => {
4707
+ var _valueOf;
4708
+ return !["0", "false"].includes((_valueOf = valueOf(element)) !== null && _valueOf !== void 0 ? _valueOf : "1");
4709
+ });
4710
+ properties.attributes = withAttributes(properties, {
4711
+ descr: (description !== null && description !== void 0 ? description : decorative ? void 0 : describe()) || void 0,
4712
+ title: (title === null || title === void 0 ? void 0 : title.split(placeholder).join("").trim()) || void 0
4713
+ }).attributes;
4714
+ };
4715
+ /**
4716
+ * Replaces the data of a chart in a template, found by a placeholder in its alt text, such as `{{sales}}`, keeping its
4717
+ * look: its type, title, colours, fonts, labels, axes and legend. Give it as a patch to `patchDocument`, with the
4718
+ * placeholder's key.
4719
+ *
4720
+ * - Each series' name and data are replaced, in the order the series are plotted, and its data is written in the
4721
+ * chart's own number formats, such as "0%".
4722
+ * - New series copy the look of the template's last series, in their own colour, the next of the theme's accents, as
4723
+ * `ChartRun` colours them. Series the new data doesn't have are removed, with any axes only they used.
4724
+ * - Points past the new data lose their own colours and labels. When each slice of a pie has its own colour, new
4725
+ * slices take the next of the theme's accents.
4726
+ * - The chart's workbook is replaced with one holding the new data, so Word's "Edit Data" opens it.
4727
+ * - The alt text's description is replaced with a description of the new data.
4728
+ *
4729
+ * The patch checks the data against the chart's type when the document is patched: a pie chart has one series, a
4730
+ * scatter or bubble chart's series have points, and a stock chart has prices, with opening prices and volumes if the
4731
+ * template's has them. Put the placeholder in the chart's alt text in Word, in "Alt Text" or "Edit Alt Text". A
4732
+ * placeholder in the document's text is left as it is.
4733
+ *
4734
+ * @publicApi
4735
+ *
4736
+ * @example
4737
+ * ```typescript
4738
+ * await patchDocument({
4739
+ * outputType: "nodebuffer",
4740
+ * data: template,
4741
+ * patches: {
4742
+ * sales: new ChartDataPatch({
4743
+ * categories: ["Jan", "Feb", "Mar"],
4744
+ * series: [{ name: "2025", values: [10, 20, 30] }],
4745
+ * }),
4746
+ * },
4747
+ * });
4748
+ * ```
4749
+ */
4750
+ var ChartDataPatch = class extends DrawingPatch {
4751
+ /**
4752
+ * @throws If there are no series, a series has no name, or has neither values nor points, some series have values
4753
+ * and others points, series with values have no categories, or a value, category or point is wrong, as for
4754
+ * `ChartRun`
4755
+ */
4756
+ constructor(options) {
4757
+ super();
4758
+ _defineProperty(this, "data", void 0);
4759
+ _defineProperty(this, "patched", /* @__PURE__ */ new WeakSet());
4760
+ this.data = readOptions(options);
4761
+ }
4762
+ /**
4763
+ * Replaces the chart's data, and its workbook, and describes it in its alt text.
4764
+ *
4765
+ * @throws If the drawing isn't a chart, is a type of chart this can't patch, such as a surface chart, or has something
4766
+ * that refers to its workbook's cells other than its data, such as labels from cells, or the data isn't for the
4767
+ * chart's type, such as two series for a pie chart
4768
+ */
4769
+ patch(drawing, template) {
4770
+ try {
4771
+ this.patchChart(drawing, template);
4772
+ } catch (error) {
4773
+ throw new Error(`Can't patch the chart ${drawing.placeholder}. ${error instanceof Error ? error.message : String(error)}`, { cause: error });
4774
+ }
4775
+ }
4776
+ patchChart(drawing, template) {
4777
+ const part = template.getRelatedPart(drawing.part, chartIdOf(drawing.element));
4778
+ if ((part === null || part === void 0 ? void 0 : part.xml) === void 0) throw new Error("It refers to a chart part the template doesn't have");
4779
+ const chartSpace = childOf(part.xml, "c:chartSpace");
4780
+ if (chartSpace === void 0) throw new Error(`Its part ${part.path} isn't a chart: it has no c:chartSpace`);
4781
+ const chart = readTemplateChart(chartSpace);
4782
+ const options = optionsFor(chart, this.data);
4783
+ if (!this.patched.has(part.xml)) {
4784
+ const dates = ("categories" in options ? leafCategoriesOf(options.categories) : []).filter((category) => category instanceof Date);
4785
+ const data = withTemplateFormats(createChartData(options), chart, dates.length > 0 ? timeUnitOf(dates) : void 0);
4786
+ const patched = patchChartSpace(chart, data, template.format, () => descendantsOf(template.format(createPlotArea(options, data)), "c:ser"));
4787
+ const reference = findWorkbookReference(patched.chartSpace, patched.references);
4788
+ if (reference !== void 0) throw new Error(describeWorkbookReference(reference));
4789
+ const externalData = childOf(chartSpace, "c:externalData");
4790
+ const name = relationshipIdAttributeOf(externalData);
4791
+ const id = template.replaceRelatedPart(part, name === void 0 ? void 0 : attributeOf(externalData, name), createWorkbookPart(data.sheet));
4792
+ const withNewWorkbook = withWorkbook(patched.chartSpace, id);
4793
+ part.xml.elements = part.xml.elements.map((element) => element === chartSpace ? withNewWorkbook : element);
4794
+ this.patched.add(part.xml);
4795
+ }
4796
+ setAltText(drawing, this.data.description, () => describeChart(options));
4797
+ }
4798
+ };
4799
+ //#endregion
4800
+ export { ChartDataPatch, ChartRun };