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