@pacem/pacem-charts 1.0.0-abel

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,1462 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // packages/charts/dist/esm/index-components.js
8
+ var index_components_exports = {};
9
+ __export(index_components_exports, {
10
+ Charts: () => index_components_charts_exports
11
+ });
12
+
13
+ // packages/charts/dist/esm/index-components-charts.js
14
+ var index_components_charts_exports = {};
15
+ __export(index_components_charts_exports, {
16
+ ChartEvent: () => ChartEvent,
17
+ MANAGED_EVENTS: () => MANAGED_EVENTS,
18
+ PacemChartElement: () => PacemChartElement,
19
+ PacemChartSeriesElement: () => PacemChartSeriesElement,
20
+ PacemColumnChartElement: () => PacemColumnChartElement,
21
+ PacemPieChartElement: () => PacemPieChartElement,
22
+ PacemPieSliceElement: () => PacemPieSliceElement,
23
+ PacemSeriesChartElement: () => PacemSeriesChartElement
24
+ });
25
+
26
+ // packages/charts/dist/esm/types.js
27
+ import { CustomElement, Watch, PropertyConverters, P, PCSS, Components, CustomUIEvent, CustomElementUtils, Utils, Throttle, PropertyChangeEventName } from "@pacem/pacem-core";
28
+ var __decorate = function(decorators, target, key, desc) {
29
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
30
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
32
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
33
+ };
34
+ var MANAGED_EVENTS = ["keydown", "keyup", "click", "dblclick", "mouseover", "mouseout", "mouseenter", "mouseleave", "mousedown", "mouseup", "mousemove", "contextmenu"];
35
+ var MSECS_PER_DAY = 1e3 * 60 * 60 * 24;
36
+ var MAX_X_LABELS = 10;
37
+ var MAX_Y_LABELS = 10;
38
+ var SERIES_DATAITEM = "pacem:chart-series:dataitem";
39
+ var SERIES_SERIES = "pacem:chart-series:series";
40
+ function getEvenlySpaced(items, type, min, max, formatOrLang, labels = MAX_X_LABELS) {
41
+ const length = type === "number" || type === "date" ? max - min : Math.max(1, items.length - 1);
42
+ const gaps = labels - 1;
43
+ var retval = [];
44
+ var step = 1;
45
+ for (var l = gaps; l > 1; l--) {
46
+ if (length % l === 0) {
47
+ step = length / l;
48
+ break;
49
+ }
50
+ }
51
+ if (step === 1 && length > labels) {
52
+ step = length;
53
+ }
54
+ const fnDate = typeof formatOrLang === "function" ? formatOrLang : step >= MSECS_PER_DAY ? ((d) => d.toLocaleDateString(formatOrLang)) : ((d) => d.toLocaleTimeString(formatOrLang));
55
+ const fnDateFirst = typeof formatOrLang === "function" ? formatOrLang : step < MSECS_PER_DAY ? ((d) => d.toLocaleString(formatOrLang)) : fnDate;
56
+ const fnNum = typeof formatOrLang === "function" ? formatOrLang : (n) => n.toLocaleString(formatOrLang);
57
+ for (var j = 0; j <= length; j += step) {
58
+ let label;
59
+ switch (type) {
60
+ case "string":
61
+ if (j >= items.length) {
62
+ continue;
63
+ }
64
+ label = items[j].label;
65
+ break;
66
+ case "number":
67
+ label = fnNum(min + j);
68
+ break;
69
+ case "date":
70
+ let date = Utils.parseDate(min + j);
71
+ let fn = j == 0 ? fnDateFirst : fnDate;
72
+ label = fn(date);
73
+ break;
74
+ default:
75
+ throw "Not supported.";
76
+ }
77
+ retval.push(label);
78
+ }
79
+ return retval;
80
+ }
81
+ function getRoundedBoundaries(min, max, desiredSteps) {
82
+ desiredSteps ??= Math.min(bestGuessedDensity(min, max), MAX_Y_LABELS);
83
+ const roughStep = (max - min) / desiredSteps;
84
+ const magnitude = Math.pow(10, Math.floor(Math.log10(roughStep)));
85
+ const step = [1, 2, 5, 10].map((n) => n * magnitude).filter((s) => s >= roughStep).reduce((min2, s) => Math.min(min2, s), Number.POSITIVE_INFINITY);
86
+ return {
87
+ min: Math.floor(min / step) * step,
88
+ max: Math.ceil(max / step) * step,
89
+ round: step
90
+ };
91
+ }
92
+ function bestGuessedDensity(min, max) {
93
+ const delta = max - min;
94
+ if (!(delta > 0)) {
95
+ return 2;
96
+ }
97
+ const oom = Math.floor(Math.log10(delta));
98
+ const exp = Math.pow(10, -oom);
99
+ if (oom != 0) {
100
+ return bestGuessedDensity(min * exp, max * exp);
101
+ }
102
+ const capFn = (n) => {
103
+ const norm = Math.floor(Math.abs(n) * 10), limit = norm + 10 - norm % 10;
104
+ return limit.roundoff();
105
+ };
106
+ const b = capFn(delta);
107
+ let a = 10;
108
+ if (min !== 0) {
109
+ a = capFn(Math.abs(max));
110
+ }
111
+ const ret = gcd(a, b);
112
+ return ret === 1 ? b : Math.max(ret, 10 - ret);
113
+ }
114
+ function gcd(a, b) {
115
+ if (a <= 0) {
116
+ return b;
117
+ }
118
+ return gcd(b % a, a);
119
+ }
120
+ var ChartEvent = class extends CustomUIEvent {
121
+ constructor(type, eventInit, originalEvent) {
122
+ super(type, eventInit, originalEvent);
123
+ }
124
+ };
125
+ var PacemChartSeriesElement = class PacemChartSeriesElement2 extends Components.PacemItemElement {
126
+ get values() {
127
+ return this.datasource;
128
+ }
129
+ };
130
+ __decorate([
131
+ Watch({ emit: true, converter: PropertyConverters.Json })
132
+ ], PacemChartSeriesElement.prototype, "datasource", void 0);
133
+ __decorate([
134
+ Watch({ emit: true, converter: PropertyConverters.String })
135
+ ], PacemChartSeriesElement.prototype, "label", void 0);
136
+ __decorate([
137
+ Watch({ emit: true, converter: PropertyConverters.String })
138
+ ], PacemChartSeriesElement.prototype, "color", void 0);
139
+ __decorate([
140
+ Watch({ emit: true, converter: PropertyConverters.Boolean })
141
+ ], PacemChartSeriesElement.prototype, "datapoints", void 0);
142
+ __decorate([
143
+ Watch(
144
+ /* to be set programmatically (internally) */
145
+ )
146
+ ], PacemChartSeriesElement.prototype, "_uiElements", void 0);
147
+ PacemChartSeriesElement = __decorate([
148
+ CustomElement({ tagName: P + "-chart-series" })
149
+ ], PacemChartSeriesElement);
150
+ var SVG_NS = "http://www.w3.org/2000/svg";
151
+ var PacemSeriesChartElement = class extends Components.PacemItemsContainerElement {
152
+ constructor() {
153
+ super();
154
+ this._itemPropertyChangedCallback = (evt) => {
155
+ const propName = evt.detail.propertyName;
156
+ if (propName === "datasource" || propName === "label" || propName === "datapoints" || propName === "cssClass" || propName === "color") {
157
+ this.draw();
158
+ }
159
+ };
160
+ this._series = [];
161
+ this._resizeHandler = (evt) => {
162
+ this._size = evt.detail;
163
+ this.draw();
164
+ };
165
+ this._broadcastHandler = (e) => {
166
+ const element = e.currentTarget;
167
+ const dataItem = CustomElementUtils.getAttachedPropertyValue(element, SERIES_DATAITEM);
168
+ if (Utils.isNull(dataItem)) {
169
+ return;
170
+ }
171
+ const chart = this, anchorPoint = chart.getAnchorPoint(element);
172
+ const evt = new ChartEvent("item" + e.type, { detail: { dataItem, anchorPoint } }, e);
173
+ const series = CustomElementUtils.getAttachedPropertyValue(element, SERIES_SERIES);
174
+ if (series instanceof PacemChartSeriesElement) {
175
+ series.dispatchEvent(evt);
176
+ }
177
+ chart.dispatchEvent(evt);
178
+ };
179
+ this._key = Utils.uniqueCode();
180
+ }
181
+ validate(item) {
182
+ return item instanceof PacemChartSeriesElement;
183
+ }
184
+ register(item) {
185
+ if (super.register(item)) {
186
+ item.addEventListener(PropertyChangeEventName, this._itemPropertyChangedCallback, false);
187
+ return true;
188
+ }
189
+ return false;
190
+ }
191
+ unregister(item) {
192
+ if (super.unregister(item)) {
193
+ item.removeEventListener(PropertyChangeEventName, this._itemPropertyChangedCallback, false);
194
+ return true;
195
+ }
196
+ return false;
197
+ }
198
+ propertyChangedCallback(name, old, val, first) {
199
+ super.propertyChangedCallback(name, old, val, first);
200
+ if (name === "target") {
201
+ if (this._div != old) {
202
+ this._div && this._div.remove();
203
+ }
204
+ this._div = null;
205
+ this._body = null;
206
+ const eold = old;
207
+ if (eold) {
208
+ eold.classList.remove(PCSS + "-chart-area");
209
+ eold.innerHTML = "";
210
+ }
211
+ this._ensureResizer();
212
+ this.draw();
213
+ } else if (!first) {
214
+ switch (name) {
215
+ case "items":
216
+ this._databindAndDrawDebounced();
217
+ break;
218
+ case "datasource":
219
+ this._databind();
220
+ // fall down to draw() call.
221
+ case "yAxisDensity":
222
+ case "xAxisDensity":
223
+ case "xAxisType":
224
+ case "yAxisMax":
225
+ case "xAxisPosition":
226
+ case "yAxisFormat":
227
+ this.draw();
228
+ break;
229
+ }
230
+ }
231
+ }
232
+ _databindAndDrawDebounced() {
233
+ cancelAnimationFrame(this._handle);
234
+ this._handle = requestAnimationFrame(() => {
235
+ this._databind();
236
+ this.draw();
237
+ });
238
+ }
239
+ _databind() {
240
+ this._datasource = Utils.isNullOrEmpty(this.datasource) ? this.items : this.datasource;
241
+ }
242
+ disconnectedCallback() {
243
+ this._div && this._div.remove();
244
+ const resizer = this._resizer;
245
+ if (!Utils.isNull(resizer)) {
246
+ resizer.removeEventListener(Components.ResizeEventName, this._resizeHandler, false);
247
+ resizer.remove();
248
+ this._resizer = null;
249
+ }
250
+ super.disconnectedCallback();
251
+ }
252
+ viewActivatedCallback() {
253
+ super.viewActivatedCallback();
254
+ this._ensureResizer();
255
+ this._databind();
256
+ this.draw();
257
+ }
258
+ _ensureResizer(target = this.target || this._div) {
259
+ if (Utils.isNull(this._resizer)) {
260
+ const shell = CustomElementUtils.findAncestorShell(this);
261
+ const resizer = this._resizer = shell.appendChild(new Components.PacemResizeElement());
262
+ resizer.addEventListener(Components.ResizeEventName, this._resizeHandler, false);
263
+ }
264
+ this._resizer.target = target;
265
+ }
266
+ // #region OO-scoped props
267
+ get chartSize() {
268
+ return this._size;
269
+ }
270
+ get chartSeries() {
271
+ return this._series;
272
+ }
273
+ get chartBody() {
274
+ return this._body;
275
+ }
276
+ get chartGrid() {
277
+ return this._grid;
278
+ }
279
+ get chartMask() {
280
+ return this._mask;
281
+ }
282
+ get chartKey() {
283
+ return this._key;
284
+ }
285
+ get chartContainer() {
286
+ return this._div;
287
+ }
288
+ assignUiBehaviors(ui, series, data, color) {
289
+ const alreadyRegistered = !Utils.isNull(CustomElementUtils.getAttachedPropertyValue(ui, SERIES_DATAITEM));
290
+ const item = Utils.extend({ series: series.label, color: color || series.color }, data);
291
+ CustomElementUtils.setAttachedPropertyValue(ui, SERIES_DATAITEM, item);
292
+ CustomElementUtils.setAttachedPropertyValue(ui, SERIES_SERIES, series);
293
+ if (!alreadyRegistered) {
294
+ MANAGED_EVENTS.forEach((type) => {
295
+ ui.addEventListener(type, this._broadcastHandler);
296
+ });
297
+ }
298
+ }
299
+ disposeUiBehaviors(ui) {
300
+ CustomElementUtils.deleteAttachedPropertyValue(ui, SERIES_DATAITEM);
301
+ CustomElementUtils.deleteAttachedPropertyValue(ui, SERIES_SERIES);
302
+ MANAGED_EVENTS.forEach((type) => {
303
+ ui.removeEventListener(type, this._broadcastHandler);
304
+ });
305
+ }
306
+ ensureChartContainer() {
307
+ if (Utils.isNull(this._div)) {
308
+ let div = this._div = this.target || document.createElement("div");
309
+ div.classList.add(PCSS + "-chart-area");
310
+ if (div != this.target) {
311
+ this.parentElement.insertBefore(div, this);
312
+ }
313
+ }
314
+ return this._div;
315
+ }
316
+ ensureChartBody(type, w, h) {
317
+ if (Utils.isNull(this._body)) {
318
+ let svg = this._body = document.createElementNS(SVG_NS, "svg");
319
+ svg.setAttribute("pacem", "");
320
+ svg.setAttribute("class", PCSS + "-" + type + "-chart");
321
+ svg.setAttribute("preserveAspectRatio", "xMinYMax slice");
322
+ const g = this._grid = document.createElementNS(SVG_NS, "svg");
323
+ g.setAttribute("pacem", "");
324
+ g.setAttribute("class", "chart-grid");
325
+ let defs = document.createElementNS(SVG_NS, "defs");
326
+ let mask = this._mask = document.createElementNS(SVG_NS, "mask");
327
+ let rect = document.createElementNS(SVG_NS, "rect");
328
+ rect.setAttribute("x", "0");
329
+ rect.setAttribute("y", "0");
330
+ rect.setAttribute("width", "100%");
331
+ rect.setAttribute("height", "100%");
332
+ let rect0 = document.createElementNS(SVG_NS, "rect");
333
+ rect0.setAttribute("y", "0");
334
+ rect0.setAttribute("width", "100%");
335
+ rect0.setAttribute("fill", "#fff");
336
+ mask.id = "gnrc_mask_" + this._key;
337
+ mask.appendChild(rect);
338
+ mask.appendChild(rect0);
339
+ defs.appendChild(mask);
340
+ svg.appendChild(defs);
341
+ svg.appendChild(g);
342
+ this._div.appendChild(svg);
343
+ }
344
+ return this._body;
345
+ }
346
+ chartDataItemToPoint(input, source) {
347
+ switch (this.xAxisType || "string") {
348
+ case "number":
349
+ return { x: parseFloat(input.label), y: input.value };
350
+ case "date":
351
+ return { x: Utils.parseDate(input.label).valueOf(), y: input.value };
352
+ case "string":
353
+ return { x: source.findIndex((e) => e.label == input.label), y: input.value };
354
+ default:
355
+ throw "Not supported.";
356
+ }
357
+ }
358
+ getVirtualGrid(items, minX, maxX, minY, maxY, xAxisType = this.xAxisType, steps, labels) {
359
+ const rangeY = getRoundedBoundaries(minY, maxY, steps), stepY = rangeY.round;
360
+ var y = [];
361
+ for (let j = rangeY.min; j <= rangeY.max; j += stepY) {
362
+ y.push(j.roundoff());
363
+ }
364
+ let lang = Utils.lang(this);
365
+ let format = null;
366
+ const intl = this.xAxisFormat;
367
+ if (!Utils.isNullOrEmpty(intl)) {
368
+ switch (xAxisType) {
369
+ case "number":
370
+ format = (n) => Intl.NumberFormat(lang, intl).format(n);
371
+ break;
372
+ case "date":
373
+ format = (n) => Intl.DateTimeFormat(lang, intl).format(Utils.parseDate(n));
374
+ break;
375
+ }
376
+ }
377
+ const x = getEvenlySpaced(items, xAxisType, minX, maxX, format ?? lang, labels);
378
+ return { x, y };
379
+ }
380
+ wipeOut(series = this._series, startIndex = 0) {
381
+ for (var j = series.length - 1; j >= startIndex; j--) {
382
+ series[j].remove();
383
+ }
384
+ series.splice(startIndex);
385
+ }
386
+ buildLinearGradient(seriesIndex, invert = false) {
387
+ const grad = document.createElementNS(SVG_NS, "linearGradient");
388
+ grad.id = this.chartKey + "_grad" + seriesIndex + (invert ? "_inverted" : "");
389
+ if (invert) {
390
+ Utils.addClass(grad, "bottom-up");
391
+ }
392
+ grad.setAttribute("x1", "0%");
393
+ grad.setAttribute("x2", "0%");
394
+ grad.setAttribute("y1", "0%");
395
+ grad.setAttribute("y2", "100%");
396
+ grad.setAttribute("spreadMethod", "pad");
397
+ const stop1 = document.createElementNS(SVG_NS, "stop");
398
+ stop1.setAttribute("offset", "0%");
399
+ const stop2 = document.createElementNS(SVG_NS, "stop");
400
+ stop2.setAttribute("offset", "100%");
401
+ grad.appendChild(stop1);
402
+ grad.appendChild(stop2);
403
+ return grad;
404
+ }
405
+ setGradientColor(grad, color) {
406
+ for (let j = 0; j < grad.children.length; j++) {
407
+ const stop = grad.children.item(j);
408
+ if (stop instanceof SVGStopElement) {
409
+ stop.style.stopColor = color;
410
+ }
411
+ }
412
+ }
413
+ estimateYAxisLabelWidth(max) {
414
+ const txt = this.formatYAxisLabel(max);
415
+ return this.estimateLabelWidth(txt);
416
+ }
417
+ estimateLabelWidth(txt) {
418
+ const grid = this._grid;
419
+ if (Utils.isNull(grid)) {
420
+ throw new Error("Unable to estimate label without an underlying grid available.");
421
+ }
422
+ const lbl = document.createElementNS(SVG_NS, "text");
423
+ lbl.textContent = txt;
424
+ grid.appendChild(lbl);
425
+ const size = Utils.offset(lbl);
426
+ lbl.remove();
427
+ return size.width;
428
+ }
429
+ formatYAxisLabel(y) {
430
+ const intl = this.yAxisFormat;
431
+ return Utils.isNullOrEmpty(intl) ? y.toString() : Intl.NumberFormat(Utils.lang(this), intl).format(y);
432
+ }
433
+ estimateXAxisLabelWidth(max) {
434
+ const txt = this.formatXAxisLabel(max);
435
+ return this.estimateLabelWidth(txt);
436
+ }
437
+ formatXAxisLabel(x) {
438
+ const intl = this.xAxisFormat, lang = Utils.lang(this);
439
+ switch (this.xAxisType) {
440
+ case "date":
441
+ const date = Utils.Dates.parse(x);
442
+ return Utils.isNullOrEmpty(intl) ? date.toLocaleString(lang) : Intl.DateTimeFormat(lang, intl).format(date);
443
+ case "number":
444
+ const num = x;
445
+ return Utils.isNullOrEmpty(intl) ? num.toLocaleString(lang) : Intl.NumberFormat(lang, intl).format(num);
446
+ default:
447
+ return x;
448
+ }
449
+ }
450
+ draw() {
451
+ this.drawSeries(this._datasource);
452
+ }
453
+ /**
454
+ * Default implementation.
455
+ * @param element
456
+ */
457
+ getAnchorPoint(element) {
458
+ const rect = Utils.offset(element);
459
+ return { x: rect.left + rect.width * 0.5, y: rect.top + rect.height * 0.5 };
460
+ }
461
+ };
462
+ __decorate([
463
+ Watch({ converter: PropertyConverters.Element })
464
+ ], PacemSeriesChartElement.prototype, "target", void 0);
465
+ __decorate([
466
+ Watch({ emit: false, converter: PropertyConverters.String })
467
+ ], PacemSeriesChartElement.prototype, "xAxisType", void 0);
468
+ __decorate([
469
+ Watch({ emit: false, converter: PropertyConverters.String })
470
+ ], PacemSeriesChartElement.prototype, "xAxisPosition", void 0);
471
+ __decorate([
472
+ Watch({ emit: false, converter: PropertyConverters.Json })
473
+ ], PacemSeriesChartElement.prototype, "datasource", void 0);
474
+ __decorate([
475
+ Watch({ emit: false, converter: PropertyConverters.Number })
476
+ ], PacemSeriesChartElement.prototype, "yAxisDensity", void 0);
477
+ __decorate([
478
+ Watch({ emit: false, converter: PropertyConverters.Number })
479
+ ], PacemSeriesChartElement.prototype, "xAxisDensity", void 0);
480
+ __decorate([
481
+ Watch({ emit: false, converter: PropertyConverters.Number })
482
+ ], PacemSeriesChartElement.prototype, "yAxisMin", void 0);
483
+ __decorate([
484
+ Watch({ emit: false, converter: PropertyConverters.Number })
485
+ ], PacemSeriesChartElement.prototype, "yAxisMax", void 0);
486
+ __decorate([
487
+ Watch({ emit: false, converter: PropertyConverters.Json })
488
+ ], PacemSeriesChartElement.prototype, "yAxisFormat", void 0);
489
+ __decorate([
490
+ Watch({ emit: false, converter: PropertyConverters.Json })
491
+ ], PacemSeriesChartElement.prototype, "xAxisFormat", void 0);
492
+ __decorate([
493
+ Throttle(true)
494
+ ], PacemSeriesChartElement.prototype, "draw", null);
495
+
496
+ // packages/charts/dist/esm/generic.js
497
+ import { CustomElement as CustomElement2, Watch as Watch2, PropertyConverters as PropertyConverters2, P as P2, PCSS as PCSS2, Utils as Utils2, CustomElementUtils as CustomElementUtils2, Logging } from "@pacem/pacem-core";
498
+ var __decorate2 = function(decorators, target, key, desc) {
499
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
500
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
501
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
502
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
503
+ };
504
+ function getSplineCtrlPoints(p, p0, p1) {
505
+ let c0 = p, c1 = p;
506
+ const p0Null = Utils2.isNull(p0), p1Null = Utils2.isNull(p1);
507
+ if (!(p0Null && p1Null)) {
508
+ const portion = 3;
509
+ let m0, m1;
510
+ if (!p0Null) {
511
+ m0 = (p.y - p0.y) / (p.x - p0.x);
512
+ }
513
+ if (!p1Null) {
514
+ m1 = (p1.y - p.y) / (p1.x - p.x);
515
+ }
516
+ const m = ((m1 || (m0 || 0)) + (m0 || (m1 || 0))) / 2;
517
+ const dx0 = p0Null ? 0 : (p.x - p0.x) / portion;
518
+ const dx1 = p1Null ? 0 : (p1.x - p.x) / portion;
519
+ c0 = { x: p.x - dx0, y: p.y - dx0 * m };
520
+ c1 = { x: p.x + dx1, y: p.y + dx1 * m };
521
+ }
522
+ return { c0, c1 };
523
+ }
524
+ var GET_VAL = CustomElementUtils2.getAttachedPropertyValue;
525
+ var SET_VAL = CustomElementUtils2.setAttachedPropertyValue;
526
+ var DEL_VAL = CustomElementUtils2.deleteAttachedPropertyValue;
527
+ var PADDING_PIXELS = 24;
528
+ var SERIES_MAGNITUDE = "pacem:chart-series:area";
529
+ var SVG_NS2 = "http://www.w3.org/2000/svg";
530
+ var PacemChartElement = class PacemChartElement2 extends PacemSeriesChartElement {
531
+ constructor() {
532
+ super(...arguments);
533
+ this.#hover = false;
534
+ this._enterHandler = (evt) => {
535
+ this.#hover = true;
536
+ };
537
+ this._leaveHandler = (evt) => {
538
+ this.#hover = false;
539
+ };
540
+ this._moveHandler = (evt) => {
541
+ if (!this.#hover) {
542
+ return;
543
+ }
544
+ };
545
+ this._chartFillSeries = [];
546
+ }
547
+ // TODO: implement
548
+ // @Watch({ converter: PropertyConverters.String }) hoverMode: 'abscissa' | 'point'; // 'point' assumed as default
549
+ _getVirtualGrid(items, minX, maxX, minY, maxY, xAxisType = this.xAxisType, steps, labels) {
550
+ return super.getVirtualGrid(items, minX, maxX, minY, maxY, xAxisType, steps, labels);
551
+ }
552
+ _wipe(series = this.chartSeries, startIndex = 0) {
553
+ super.wipeOut(series, startIndex);
554
+ }
555
+ viewActivatedCallback() {
556
+ super.viewActivatedCallback();
557
+ this._setupBehavior();
558
+ }
559
+ disconnectedCallback() {
560
+ this._dismantleBehavior();
561
+ super.disconnectedCallback();
562
+ }
563
+ propertyChangedCallback(name, old, val, first) {
564
+ super.propertyChangedCallback(name, old, val, first);
565
+ switch (name) {
566
+ case "type":
567
+ case "aspectRatio":
568
+ this.draw();
569
+ break;
570
+ }
571
+ }
572
+ _setupBehavior() {
573
+ this.addEventListener("mouseenter", this._enterHandler, false);
574
+ this.addEventListener("mouseleave", this._enterHandler, false);
575
+ this.addEventListener("mousemove", this._moveHandler, false);
576
+ }
577
+ _dismantleBehavior() {
578
+ this.removeEventListener("mouseenter", this._enterHandler, false);
579
+ this.removeEventListener("mouseleave", this._leaveHandler, false);
580
+ this.removeEventListener("mousemove", this._moveHandler, false);
581
+ }
582
+ #hover;
583
+ _buildLinearGradient(seriesIndex) {
584
+ return super.buildLinearGradient(seriesIndex);
585
+ }
586
+ _setGradientColor(grad, color) {
587
+ super.setGradientColor(grad, color);
588
+ }
589
+ drawSeries(datasource) {
590
+ if (!this.isReady || Utils2.isNull(this.chartSize)) {
591
+ return;
592
+ }
593
+ this.ensureChartContainer();
594
+ const type = this.type || "line";
595
+ const padding = PADDING_PIXELS;
596
+ var size = this.chartSize;
597
+ if (size.height <= padding || size.width <= padding) {
598
+ return;
599
+ }
600
+ if (Utils2.isNullOrEmpty(datasource) || datasource.every((i) => Utils2.isNullOrEmpty(i.values))) {
601
+ this._wipe();
602
+ return;
603
+ }
604
+ const body = this.ensureChartBody("line", size.width, size.height);
605
+ this.log(Logging.LogLevel.Debug, `Drawing ${type} chart.`);
606
+ const xAxisType = this.xAxisType || "string";
607
+ let minY = this.yAxisMin ?? Number.NaN, maxY = this.yAxisMax ?? Number.NaN, minX = Number.NaN, maxX = Number.NaN;
608
+ let stretch = 1;
609
+ for (let series of datasource) {
610
+ let data = series.values;
611
+ if (data && data.length) {
612
+ let j2 = 0;
613
+ for (let item of data) {
614
+ let pt = this.chartDataItemToPoint(item, data);
615
+ if (Utils2.isNull(this.yAxisMin)) {
616
+ minY = isNaN(minY) ? pt.y : Math.min(minY, pt.y);
617
+ }
618
+ if (Utils2.isNull(this.yAxisMax)) {
619
+ maxY = isNaN(maxY) ? pt.y : Math.max(maxY, pt.y);
620
+ }
621
+ if (j2 === 0)
622
+ minX = isNaN(minX) ? pt.x : Math.min(minX, pt.x);
623
+ else if (j2 === data.length - 1)
624
+ maxX = isNaN(maxX) ? pt.x : Math.max(maxX, pt.x);
625
+ j2++;
626
+ }
627
+ }
628
+ }
629
+ const withValues = datasource.find((i) => !Utils2.isNullOrEmpty(i.values));
630
+ const grid = this._getVirtualGrid(withValues.values, minX, maxX, minY, maxY, xAxisType, this.yAxisDensity, this.xAxisDensity);
631
+ const topGrid = grid.y[grid.y.length - 1], bottomGrid = grid.y[0];
632
+ if (topGrid === bottomGrid)
633
+ return;
634
+ const halfPad = padding * 0.5;
635
+ const maxYLabelLength = grid.y.reduce((max, i) => Math.max(max, this.estimateYAxisLabelWidth(i) + halfPad), padding);
636
+ const maxXLabelHalfLength = grid.x.reduce((max, i) => Math.max(max, this.estimateXAxisLabelWidth(i)), padding) * 0.5;
637
+ const paddingYAxis = Math.max(maxXLabelHalfLength, maxYLabelLength), paddingYAxisEnd = maxXLabelHalfLength;
638
+ const seriesWidth = size.width - paddingYAxis - paddingYAxisEnd;
639
+ const gridHeight = size.height - 2 * padding;
640
+ const seriesHeight = gridHeight * (1 - (topGrid - bottomGrid - (maxY - minY)) / (topGrid - bottomGrid));
641
+ const seriesY = gridHeight * (topGrid - maxY) / (topGrid - bottomGrid);
642
+ if (xAxisType !== "number" || this.aspectRatio !== "monometric" && this.aspectRatio !== "logaritmic") {
643
+ stretch = seriesWidth / seriesHeight;
644
+ body.setAttribute("height", size.height.toString());
645
+ body.setAttribute("width", size.width.toString());
646
+ }
647
+ body.setAttribute("viewBox", `0 0 ${size.width} ${size.height}`);
648
+ let iter = 0;
649
+ const spanX = maxX - minX, spanY = maxY - minY;
650
+ const normX = 100 * stretch / spanX, normY = 100 / spanY;
651
+ const normPadding = 100 * padding / seriesHeight;
652
+ const buildPoint = (it, series) => {
653
+ let p = this.chartDataItemToPoint(it, series);
654
+ p.y *= normY;
655
+ p.x = (p.x - minX) * normX;
656
+ return p;
657
+ };
658
+ const chartSeries = this.chartSeries;
659
+ const chartFillSeries = this._chartFillSeries;
660
+ const chartGrid = this.chartGrid;
661
+ const splineHere = type === "spline" || type === "splinearea";
662
+ for (let series of datasource) {
663
+ let svg2, svgFill;
664
+ let grad;
665
+ if (chartSeries.length > iter) {
666
+ svg2 = chartSeries[iter];
667
+ svgFill = chartFillSeries[iter];
668
+ grad = svgFill.firstElementChild.firstElementChild;
669
+ } else {
670
+ svg2 = document.createElementNS(SVG_NS2, "svg");
671
+ svg2.setAttribute("pacem", "");
672
+ body.appendChild(svg2);
673
+ svgFill = document.createElementNS(SVG_NS2, "svg");
674
+ svgFill.setAttribute("pacem", "");
675
+ body.insertBefore(svgFill, body.children.item(iter + /* <defs> should remain the very first child and 'grid' the very second */
676
+ 2));
677
+ const defs = document.createElementNS(SVG_NS2, "defs");
678
+ defs.appendChild(grad = this._buildLinearGradient(iter));
679
+ svgFill.appendChild(defs);
680
+ svgFill.appendChild(document.createElementNS(SVG_NS2, "path"));
681
+ chartFillSeries.push(svgFill);
682
+ svg2.appendChild(document.createElementNS(SVG_NS2, "path"));
683
+ chartSeries.push(svg2);
684
+ }
685
+ let className = "chart-series";
686
+ const fill = type === "area" || type === "splinearea";
687
+ if (!Utils2.isNullOrEmpty(series.className)) {
688
+ className += " " + series.className;
689
+ }
690
+ [svg2, svgFill].forEach((s) => {
691
+ s.setAttribute("class", className);
692
+ s.setAttribute("x", paddingYAxis.toString());
693
+ s.setAttribute("y", seriesY.toString());
694
+ s.setAttribute("width", seriesWidth.toString());
695
+ s.setAttribute("height", (seriesHeight + 2 * padding).toString());
696
+ });
697
+ Utils2.addClass(svgFill, PCSS2 + "-inert");
698
+ let pathFill = svgFill.children.item(1);
699
+ let path = svg2.firstElementChild;
700
+ path.style.stroke = series.color;
701
+ pathFill.style.stroke = path.style.fill = "none";
702
+ this._setGradientColor(grad, series.color);
703
+ pathFill.style.fill = `url(#${grad.id})`;
704
+ pathFill.style.display = fill ? "" : "none";
705
+ let d = "";
706
+ let data = series.values;
707
+ if (data && data.length) {
708
+ const addInteractivePoint = (center, j2, series2, dataItem, color) => {
709
+ const ndx = j2 + /* count the <path> child */
710
+ 1;
711
+ let circle;
712
+ if (svg2.children.length > ndx) {
713
+ circle = svg2.children.item(ndx);
714
+ } else {
715
+ circle = document.createElementNS(SVG_NS2, "line");
716
+ circle.setAttribute("class", "circle");
717
+ svg2.appendChild(circle);
718
+ }
719
+ const x1 = center.x.toString(), y1 = (-center.y).toString();
720
+ circle.setAttribute("x1", x1);
721
+ circle.setAttribute("y1", y1);
722
+ circle.setAttribute("x2", x1);
723
+ circle.setAttribute("y2", y1);
724
+ circle.style.stroke = color;
725
+ this.assignUiBehaviors(circle, series2, dataItem, color);
726
+ };
727
+ const wipeExceedingPoints = () => {
728
+ const remaining = series.datapoints ? data.length + 1 : 1;
729
+ for (let k = svg2.children.length - 1; k >= remaining; k--) {
730
+ var circle = svg2.children.item(k);
731
+ this.disposeUiBehaviors(circle);
732
+ circle.remove();
733
+ }
734
+ };
735
+ if (splineHere) {
736
+ let pt0, pt, c0;
737
+ for (let j2 = 0; j2 < data.length; j2++) {
738
+ const item = data[j2];
739
+ if (isNaN(item.value)) {
740
+ continue;
741
+ }
742
+ if (!pt) {
743
+ pt = buildPoint(item, data);
744
+ }
745
+ let pt1;
746
+ if (splineHere && j2 < data.length - 1) {
747
+ pt1 = buildPoint(data[j2 + 1], data);
748
+ }
749
+ let areaSoFar = GET_VAL(series, SERIES_MAGNITUDE, 0);
750
+ areaSoFar += item.value;
751
+ SET_VAL(series, SERIES_MAGNITUDE, areaSoFar);
752
+ var c = getSplineCtrlPoints(pt, pt0, pt1);
753
+ d += Utils2.isNullOrEmpty(d) ? `M${pt.x},${-pt.y} ` : `C${c0.x},${-c0.y} ${c.c0.x},${-c.c0.y} ${pt.x},${-pt.y} `;
754
+ if (series.datapoints) {
755
+ addInteractivePoint(pt, j2, series, item, series.color);
756
+ }
757
+ pt0 = pt;
758
+ pt = pt1, c0 = c.c1;
759
+ }
760
+ } else {
761
+ let j2 = 0;
762
+ for (let item of data) {
763
+ if (isNaN(item.value)) {
764
+ continue;
765
+ }
766
+ const pt = buildPoint(item, data);
767
+ let areaSoFar = GET_VAL(series, SERIES_MAGNITUDE, 0);
768
+ areaSoFar += item.value;
769
+ SET_VAL(series, SERIES_MAGNITUDE, areaSoFar);
770
+ d += Utils2.isNullOrEmpty(d) ? `M${pt.x},${-pt.y} ` : `L${pt.x},${-pt.y} `;
771
+ if (series.datapoints) {
772
+ addInteractivePoint(pt, j2, series, item, series.color);
773
+ }
774
+ j2++;
775
+ }
776
+ }
777
+ wipeExceedingPoints();
778
+ }
779
+ path.setAttribute("d", d);
780
+ pathFill.setAttribute("d", d + `V${-minY * normY} H0 Z`);
781
+ iter++;
782
+ }
783
+ this._wipe(chartFillSeries, iter);
784
+ this._wipe(chartSeries, iter);
785
+ const w0 = 100 * stretch, h0 = 100 + 2 * normPadding, x0 = 0, y0 = maxY * normY + normPadding;
786
+ const svbox = `${x0} ${-y0} ${w0} ${h0}`;
787
+ for (var svg of chartSeries.concat(chartFillSeries)) {
788
+ svg.setAttribute("viewBox", svbox);
789
+ }
790
+ const chartMask = this.chartMask;
791
+ let mask = chartMask.children.item(1);
792
+ mask.setAttribute("x", x0.toString());
793
+ mask.setAttribute("height", (size.height - padding).toString());
794
+ chartGrid.setAttribute("viewBox", `0 0 ${size.width} ${size.height}`);
795
+ if (grid.x.length <= 1 || grid.y.length <= 1) {
796
+ for (let j2 = chartGrid.children.length - 1; j2 >= 0; j2--) {
797
+ chartGrid.children.item(j2).remove();
798
+ }
799
+ return;
800
+ }
801
+ let pgrid;
802
+ if (chartGrid.children.length > 0) {
803
+ pgrid = chartGrid.children.item(0);
804
+ } else {
805
+ pgrid = document.createElementNS(SVG_NS2, "path");
806
+ chartGrid.appendChild(pgrid);
807
+ }
808
+ const tick = padding * 0.25;
809
+ let lblCounter = 0;
810
+ let ensureLabel = (index, x2, y2, txt) => {
811
+ const ndx = index + /* <path> is the first child element */
812
+ 1;
813
+ let lbl;
814
+ if (chartGrid.children.length <= ndx) {
815
+ lbl = document.createElementNS(SVG_NS2, "text");
816
+ chartGrid.appendChild(lbl);
817
+ } else {
818
+ lbl = chartGrid.children.item(ndx);
819
+ }
820
+ lbl.textContent = txt;
821
+ lbl.setAttribute("x", x2.toString());
822
+ lbl.setAttribute("y", y2.toString());
823
+ return lbl;
824
+ };
825
+ let dgrid = `M${paddingYAxis},${padding} v${gridHeight}`;
826
+ let j = 0;
827
+ const xincr = seriesWidth / (grid.x.length - 1), yincr = gridHeight / (grid.y.length - 1);
828
+ if (this.xAxisPosition !== "none") {
829
+ for (var x of grid.x) {
830
+ const xcoord = paddingYAxis + j * xincr;
831
+ if (this.xAxisPosition === "top") {
832
+ dgrid += ` M${xcoord},${padding} v${-tick}`;
833
+ let lbl = ensureLabel(lblCounter++, xcoord, 0, x);
834
+ lbl.setAttribute("text-anchor", "middle");
835
+ lbl.setAttribute("alignment-baseline", "hanging");
836
+ } else {
837
+ let ycoord = gridHeight + padding;
838
+ dgrid += ` M${xcoord},${ycoord} v${tick}`;
839
+ ensureLabel(lblCounter++, xcoord, ycoord + padding, x).setAttribute("text-anchor", "middle");
840
+ }
841
+ j++;
842
+ }
843
+ }
844
+ j = 0;
845
+ for (var y of grid.y) {
846
+ const ycoord = gridHeight + padding - j * yincr, xcoord = paddingYAxis - tick;
847
+ dgrid += ` M${xcoord},${ycoord} H${seriesWidth + paddingYAxis}`;
848
+ let txt = this.formatYAxisLabel(y);
849
+ ensureLabel(lblCounter++, xcoord - tick, ycoord, txt).setAttribute("text-anchor", "end");
850
+ j++;
851
+ }
852
+ pgrid.setAttribute("d", dgrid);
853
+ for (let j2 = chartGrid.children.length - 1; j2 > lblCounter; j2--) {
854
+ chartGrid.children.item(j2).remove();
855
+ }
856
+ }
857
+ };
858
+ __decorate2([
859
+ Watch2({ emit: false, converter: PropertyConverters2.String })
860
+ ], PacemChartElement.prototype, "type", void 0);
861
+ __decorate2([
862
+ Watch2({ converter: PropertyConverters2.String })
863
+ ], PacemChartElement.prototype, "aspectRatio", void 0);
864
+ PacemChartElement = __decorate2([
865
+ CustomElement2({ tagName: P2 + "-chart" })
866
+ ], PacemChartElement);
867
+
868
+ // packages/charts/dist/esm/column.js
869
+ import { CustomElement as CustomElement3, Watch as Watch3, PropertyConverters as PropertyConverters3, P as P3, Utils as Utils3, Logging as Logging2 } from "@pacem/pacem-core";
870
+ var __decorate3 = function(decorators, target, key, desc) {
871
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
872
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
873
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
874
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
875
+ };
876
+ var SVG_NS3 = "http://www.w3.org/2000/svg";
877
+ var PADDING_PIXELS2 = 24;
878
+ var PacemColumnChartElement = class PacemColumnChartElement2 extends PacemSeriesChartElement {
879
+ constructor() {
880
+ super(...arguments);
881
+ this.groupWidth = 0;
882
+ }
883
+ propertyChangedCallback(name, old, val, first) {
884
+ super.propertyChangedCallback(name, old, val, first);
885
+ if (name === "type" || name === "groupWidth") {
886
+ this.draw();
887
+ }
888
+ }
889
+ _safen(w = this.groupWidth) {
890
+ return Math.min(1, Math.max(w || 0.75, 0));
891
+ }
892
+ drawSeries(datasource) {
893
+ if (!this.isReady || Utils3.isNull(this.chartSize)) {
894
+ return;
895
+ }
896
+ const div = this.ensureChartContainer();
897
+ const type = this.type || "cluster";
898
+ const padding = PADDING_PIXELS2;
899
+ var size = this.chartSize;
900
+ if (size.height <= padding || size.width <= padding) {
901
+ return;
902
+ }
903
+ if (Utils3.isNullOrEmpty(datasource) || datasource.every((i) => Utils3.isNullOrEmpty(i.values))) {
904
+ this.wipeOut();
905
+ return;
906
+ }
907
+ const body = this.ensureChartBody("column", size.width, size.height);
908
+ this.log(Logging2.LogLevel.Debug, `Drawing ${type} chart.`);
909
+ const xAxisType = this.xAxisType || "string";
910
+ let minY = this.yAxisMin ?? 0, maxY = this.yAxisMax ?? 0, minX = 0, maxX = 0, maxCount = 0;
911
+ let stretch = 1;
912
+ const accumulator = { negative: [], positive: [] };
913
+ for (let series of datasource) {
914
+ let data = series.values;
915
+ if (!Utils3.isNullOrEmpty(data)) {
916
+ let j2 = 0;
917
+ for (let item of data) {
918
+ accumulator.positive[j2] = accumulator.positive[j2] || 0;
919
+ accumulator.negative[j2] = accumulator.negative[j2] || 0;
920
+ let pt = this.chartDataItemToPoint(item, data);
921
+ if (Utils3.isNull(this.yAxisMin)) {
922
+ minY = Math.min(minY, pt.y);
923
+ }
924
+ if (Utils3.isNull(this.yAxisMax)) {
925
+ maxY = Math.max(maxY, pt.y);
926
+ }
927
+ minX = Math.min(minX, pt.x);
928
+ maxX = Math.max(maxX, pt.x);
929
+ if (pt.y > 0) {
930
+ accumulator.positive[j2] += pt.y;
931
+ } else if (pt.y < 0) {
932
+ accumulator.negative[j2] += pt.y;
933
+ }
934
+ j2++;
935
+ }
936
+ maxCount = Math.max(maxCount, data.length);
937
+ }
938
+ }
939
+ const stacked = type === "stack";
940
+ if (stacked) {
941
+ if (Utils3.isNull(this.yAxisMin))
942
+ minY = Math.min.apply(null, accumulator.negative);
943
+ if (Utils3.isNull(this.yAxisMax))
944
+ maxY = Math.max.apply(null, accumulator.positive);
945
+ }
946
+ if (maxX === 0 && maxX === minX) {
947
+ maxX = 1;
948
+ }
949
+ const slot = (maxX - minX) / maxCount, halfSlot = slot * 0.5, availSlot = slot * this._safen(this.groupWidth), halfAvailSlot = availSlot * 0.5;
950
+ const withValues = datasource.find((i) => !Utils3.isNullOrEmpty(i.values));
951
+ const grid = this.getVirtualGrid(withValues.values, minX - halfSlot, maxX + halfSlot, minY, maxY, xAxisType, this.yAxisDensity, this.xAxisDensity);
952
+ const topGrid = grid.y[grid.y.length - 1], bottomGrid = grid.y[0];
953
+ if (topGrid === bottomGrid) {
954
+ return;
955
+ }
956
+ const halfPad = PADDING_PIXELS2 * 0.5;
957
+ const paddingYAxis = grid.y.reduce((max, i) => Math.max(max, this.estimateYAxisLabelWidth(i) + halfPad), padding);
958
+ const seriesWidth = size.width - paddingYAxis - padding;
959
+ const gridHeight = size.height - 2 * padding;
960
+ const seriesHeight = gridHeight * (1 - (topGrid - bottomGrid - (maxY - minY)) / (topGrid - bottomGrid));
961
+ const seriesY = gridHeight * (topGrid - maxY) / (topGrid - bottomGrid);
962
+ stretch = seriesWidth / seriesHeight;
963
+ body.setAttribute("height", size.height.toString());
964
+ body.setAttribute("width", size.width.toString());
965
+ body.setAttribute("viewBox", `0 0 ${size.width} ${size.height}`);
966
+ let iter = 0;
967
+ const spanX = maxX - minX, spanY = maxY - minY;
968
+ const normX = 100 * stretch / spanX, normY = 100 / spanY;
969
+ const normPadding = 100 * padding / seriesHeight;
970
+ const chartSeries = this.chartSeries;
971
+ const chartGrid = this.chartGrid;
972
+ const xPad = (halfSlot - minX) * normX;
973
+ const buildPoint = (it, series) => {
974
+ const p = this.chartDataItemToPoint(it, series);
975
+ return {
976
+ x: xPad + p.x * 2 * xPad,
977
+ y: p.y * normY
978
+ };
979
+ };
980
+ var accumulators = new Array(maxCount);
981
+ for (let series of datasource) {
982
+ let svg2;
983
+ let grad;
984
+ let gradInv;
985
+ let g;
986
+ if (chartSeries.length > iter) {
987
+ svg2 = chartSeries[iter];
988
+ grad = svg2.firstElementChild.firstElementChild;
989
+ gradInv = svg2.firstElementChild.lastElementChild;
990
+ g = svg2.lastElementChild;
991
+ } else {
992
+ svg2 = document.createElementNS(SVG_NS3, "svg");
993
+ svg2.setAttribute("pacem", "");
994
+ chartGrid.insertAdjacentElement("afterend", svg2);
995
+ const defs = document.createElementNS(SVG_NS3, "defs");
996
+ defs.appendChild(grad = this.buildLinearGradient(iter));
997
+ defs.appendChild(gradInv = this.buildLinearGradient(iter, true));
998
+ svg2.appendChild(defs);
999
+ svg2.appendChild(g = document.createElementNS(SVG_NS3, "g"));
1000
+ chartSeries.push(svg2);
1001
+ }
1002
+ var className = "chart-series series-fill";
1003
+ if (!Utils3.isNullOrEmpty(series.className)) {
1004
+ className += " " + series.className;
1005
+ }
1006
+ svg2.setAttribute("class", className);
1007
+ svg2.setAttribute("x", paddingYAxis.toString());
1008
+ svg2.setAttribute("y", seriesY.toString());
1009
+ svg2.setAttribute("width", seriesWidth.toString());
1010
+ svg2.setAttribute("height", (seriesHeight + 2 * padding).toString());
1011
+ const data = series.values;
1012
+ const spinRect = (index) => {
1013
+ while (index >= g.children.length) {
1014
+ g.appendChild(document.createElementNS(SVG_NS3, "rect"));
1015
+ }
1016
+ const rect = g.children.item(index);
1017
+ rect.style.stroke = series.color;
1018
+ const gradient = data[index].value < 0 ? gradInv : grad;
1019
+ this.setGradientColor(gradient, series.color);
1020
+ rect.style.fill = `url(#${gradient.id})`;
1021
+ return rect;
1022
+ };
1023
+ const precision = 10;
1024
+ const assignVerticalCoordsCoords = (rect, pt0, pt, pt0Start = pt0) => {
1025
+ const y2 = -Math.max(pt0.y, pt.y), h = Math.abs(pt.y - pt0.y);
1026
+ const fnAssign = () => {
1027
+ rect.setAttribute("y", y2.toFixed(precision));
1028
+ rect.setAttribute("height", h.toFixed(precision));
1029
+ };
1030
+ if (!rect.hasAttribute("y")) {
1031
+ rect.setAttribute("y", "-" + pt0Start.y.toFixed(precision));
1032
+ rect.setAttribute("height", "0");
1033
+ requestAnimationFrame(fnAssign);
1034
+ } else {
1035
+ fnAssign();
1036
+ }
1037
+ };
1038
+ if (!Utils3.isNullOrEmpty(data)) {
1039
+ ;
1040
+ const pt00 = buildPoint({ value: 0, label: data[0].label }, data);
1041
+ if (stacked) {
1042
+ const iHalfAvailSlot = halfAvailSlot * normX, iAvailSlotAttr = (availSlot * normX).toFixed(precision);
1043
+ for (let j2 = 0; j2 < data.length; j2++) {
1044
+ const item = data[j2];
1045
+ if (Utils3.isNullOrEmpty(accumulators[j2])) {
1046
+ accumulators[j2] = { positive: 0, negative: 0 };
1047
+ }
1048
+ const accumulator2 = accumulators[j2];
1049
+ let posCursor = accumulator2.positive, negCursor = accumulator2.negative;
1050
+ const neg = item.value < 0, y2 = neg ? negCursor : posCursor + item.value, y02 = neg ? negCursor + item.value : posCursor;
1051
+ const pt = buildPoint({ label: item.label, value: y2 }, data);
1052
+ const pt0 = buildPoint({ label: item.label, value: y02 }, data);
1053
+ const x2 = pt.x - iHalfAvailSlot;
1054
+ const rect = spinRect(j2);
1055
+ this.assignUiBehaviors(rect, series, item);
1056
+ rect.setAttribute("x", x2.toFixed(precision));
1057
+ rect.setAttribute("width", iAvailSlotAttr);
1058
+ assignVerticalCoordsCoords(rect, pt0, pt, pt00);
1059
+ if (neg) {
1060
+ accumulator2.negative = y02;
1061
+ } else {
1062
+ accumulator2.positive = y2;
1063
+ }
1064
+ }
1065
+ } else {
1066
+ const iHalfAvailSlot = halfAvailSlot * normX, iSlot = iHalfAvailSlot * 2 / datasource.length, iSlotAttr = iSlot.toFixed(precision);
1067
+ for (let j2 = 0; j2 < data.length; j2++) {
1068
+ const item = data[j2];
1069
+ const pt = buildPoint(item, data);
1070
+ const x2 = pt.x - iHalfAvailSlot + iSlot * iter;
1071
+ const rect = spinRect(j2);
1072
+ this.assignUiBehaviors(rect, series, item);
1073
+ rect.setAttribute("x", x2.toFixed(precision));
1074
+ rect.setAttribute("width", iSlotAttr);
1075
+ assignVerticalCoordsCoords(rect, pt00, pt);
1076
+ }
1077
+ }
1078
+ }
1079
+ for (let j2 = g.children.length - 1; j2 >= data?.length || 0; j2--) {
1080
+ const rect = g.children.item(j2);
1081
+ this.disposeUiBehaviors(rect);
1082
+ rect.remove();
1083
+ }
1084
+ iter++;
1085
+ }
1086
+ this.wipeOut(chartSeries, iter);
1087
+ const w0 = 100 * stretch, h0 = 100 + 2 * normPadding, x0 = 0, y0 = maxY * normY + normPadding;
1088
+ const svbox = `${x0} ${-y0} ${w0} ${h0}`;
1089
+ for (var svg of chartSeries) {
1090
+ svg.setAttribute("viewBox", svbox);
1091
+ }
1092
+ const chartMask = this.chartMask;
1093
+ let mask = chartMask.children.item(1);
1094
+ mask.setAttribute("x", x0.toString());
1095
+ mask.setAttribute("height", (size.height - padding).toString());
1096
+ chartGrid.setAttribute("viewBox", `0 0 ${size.width} ${size.height}`);
1097
+ if (grid.x.length < 1 || grid.y.length <= 1) {
1098
+ for (let j2 = chartGrid.children.length - 1; j2 >= 0; j2--) {
1099
+ chartGrid.children.item(j2).remove();
1100
+ }
1101
+ return;
1102
+ }
1103
+ let pgrid;
1104
+ if (chartGrid.children.length > 0) {
1105
+ pgrid = chartGrid.children.item(0);
1106
+ } else {
1107
+ pgrid = document.createElementNS(SVG_NS3, "path");
1108
+ chartGrid.appendChild(pgrid);
1109
+ }
1110
+ const tick = PADDING_PIXELS2 * 0.25;
1111
+ let lblCounter = 0;
1112
+ let ensureLabel = (index, x2, y2, txt) => {
1113
+ const ndx = index + /* <path> is the first child element */
1114
+ 1;
1115
+ let lbl;
1116
+ if (chartGrid.children.length <= ndx) {
1117
+ lbl = document.createElementNS(SVG_NS3, "text");
1118
+ chartGrid.appendChild(lbl);
1119
+ } else {
1120
+ lbl = chartGrid.children.item(ndx);
1121
+ }
1122
+ lbl.textContent = txt;
1123
+ lbl.setAttribute("x", x2.toString());
1124
+ lbl.setAttribute("y", y2.toString());
1125
+ return lbl;
1126
+ };
1127
+ let dgrid = `M${paddingYAxis},${padding} v${gridHeight}`;
1128
+ let j = 0;
1129
+ const xincr = seriesWidth / grid.x.length, yincr = gridHeight / (grid.y.length - 1);
1130
+ if (this.xAxisPosition !== "none") {
1131
+ const paddingX = xincr * 0.5 + paddingYAxis;
1132
+ for (var x of grid.x) {
1133
+ let xcoord = paddingX + j * xincr;
1134
+ if (this.xAxisPosition === "top") {
1135
+ dgrid += ` M${xcoord},${padding} v${-tick}`;
1136
+ let lbl = ensureLabel(lblCounter++, xcoord, 0, x);
1137
+ lbl.setAttribute("text-anchor", "middle");
1138
+ lbl.setAttribute("alignment-baseline", "hanging");
1139
+ } else {
1140
+ let ycoord = gridHeight + padding;
1141
+ dgrid += ` M${xcoord},${ycoord} v${tick}`;
1142
+ ensureLabel(lblCounter++, xcoord, ycoord + padding, x).setAttribute("text-anchor", "middle");
1143
+ }
1144
+ j++;
1145
+ }
1146
+ }
1147
+ j = 0;
1148
+ for (var y of grid.y) {
1149
+ const ycoord = gridHeight + padding - j * yincr, xcoord = paddingYAxis - tick;
1150
+ dgrid += ` M${xcoord},${ycoord} H${seriesWidth + paddingYAxis}`;
1151
+ let txt = this.formatYAxisLabel(y);
1152
+ ensureLabel(lblCounter++, xcoord - tick, ycoord, txt).setAttribute("text-anchor", "end");
1153
+ j++;
1154
+ }
1155
+ pgrid.setAttribute("d", dgrid);
1156
+ for (let j2 = chartGrid.children.length - 1; j2 > lblCounter; j2--) {
1157
+ chartGrid.children.item(j2).remove();
1158
+ }
1159
+ }
1160
+ };
1161
+ __decorate3([
1162
+ Watch3({ converter: PropertyConverters3.String })
1163
+ ], PacemColumnChartElement.prototype, "type", void 0);
1164
+ __decorate3([
1165
+ Watch3({ converter: PropertyConverters3.Number })
1166
+ ], PacemColumnChartElement.prototype, "groupWidth", void 0);
1167
+ PacemColumnChartElement = __decorate3([
1168
+ CustomElement3({ tagName: P3 + "-column-chart" })
1169
+ ], PacemColumnChartElement);
1170
+
1171
+ // packages/charts/dist/esm/pie.js
1172
+ import { CustomElement as CustomElement4, Watch as Watch4, PropertyConverters as PropertyConverters4, P as P4, PCSS as PCSS3, Components as Components2, Utils as Utils4, CustomElementUtils as CustomElementUtils3, Debounce } from "@pacem/pacem-core";
1173
+ var __decorate4 = function(decorators, target, key, desc) {
1174
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1175
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1176
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1177
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1178
+ };
1179
+ var PacemPieSliceElement = class PacemPieSliceElement2 extends Components2.PacemItemElement {
1180
+ constructor() {
1181
+ super(...arguments);
1182
+ this._broadcastHandler = (e) => {
1183
+ this.emit(e);
1184
+ };
1185
+ }
1186
+ findContainer() {
1187
+ return CustomElementUtils3.findAncestorOfType(this, PacemPieChartElement);
1188
+ }
1189
+ get chart() {
1190
+ return this.container;
1191
+ }
1192
+ /** Returns the center of mass (point) of this pie/doughnut slice, in absolute coords (pixels). */
1193
+ getCenterOfMass() {
1194
+ const area = this.chart && this.chart.area;
1195
+ if (Utils4.isNull(area)) {
1196
+ return null;
1197
+ }
1198
+ const rect = Utils4.offset(area), center = { x: rect.width / 2 + rect.left, y: rect.top + rect.height / 2 }, r = Math.min(rect.width, rect.height) * 0.5;
1199
+ const pos = this.normalizedPolarCoords, angle = PI1_2 - pos.angle;
1200
+ return {
1201
+ y: center.y - r * pos.radius * Math.sin(angle),
1202
+ x: center.x + r * pos.radius * Math.cos(angle)
1203
+ };
1204
+ }
1205
+ propertyChangedCallback(name, old, val, first) {
1206
+ super.propertyChangedCallback(name, old, val, first);
1207
+ if (!first && this.chart && name != "normalizedPolarCoords")
1208
+ this.chart.draw();
1209
+ }
1210
+ /** @internal */
1211
+ _assignUi(el) {
1212
+ const ui = this._ui = el;
1213
+ MANAGED_EVENTS.forEach((type) => {
1214
+ ui.addEventListener(type, this._broadcastHandler);
1215
+ });
1216
+ }
1217
+ /** @internal */
1218
+ _disposeUi() {
1219
+ if (!Utils4.isNull(this._ui)) {
1220
+ MANAGED_EVENTS.forEach((type) => {
1221
+ this._ui.removeEventListener(type, this._broadcastHandler);
1222
+ });
1223
+ }
1224
+ }
1225
+ };
1226
+ __decorate4([
1227
+ Watch4({ converter: PropertyConverters4.Number })
1228
+ ], PacemPieSliceElement.prototype, "value", void 0);
1229
+ __decorate4([
1230
+ Watch4({ converter: PropertyConverters4.String })
1231
+ ], PacemPieSliceElement.prototype, "label", void 0);
1232
+ __decorate4([
1233
+ Watch4({ converter: PropertyConverters4.String })
1234
+ ], PacemPieSliceElement.prototype, "color", void 0);
1235
+ __decorate4([
1236
+ Watch4({ converter: PropertyConverters4.Json })
1237
+ ], PacemPieSliceElement.prototype, "normalizedPolarCoords", void 0);
1238
+ PacemPieSliceElement = __decorate4([
1239
+ CustomElement4({ tagName: P4 + "-pie-slice" })
1240
+ ], PacemPieSliceElement);
1241
+ var TWO_PI = Math.PI * 2;
1242
+ var PI1_2 = Math.PI * 0.5;
1243
+ var PacemPieChartElement = class PacemPieChartElement2 extends Components2.PacemItemsContainerElement {
1244
+ constructor() {
1245
+ super();
1246
+ this.cutout = 0;
1247
+ this.slicePadding = 0;
1248
+ this._slices = /* @__PURE__ */ new WeakMap();
1249
+ this._key = Utils4.uniqueCode();
1250
+ }
1251
+ validate(item) {
1252
+ return item instanceof PacemPieSliceElement;
1253
+ }
1254
+ viewActivatedCallback() {
1255
+ super.viewActivatedCallback();
1256
+ this.draw();
1257
+ }
1258
+ propertyChangedCallback(name, old, val, first) {
1259
+ super.propertyChangedCallback(name, old, val, first);
1260
+ if (name === "target") {
1261
+ this._g = null;
1262
+ this._div && this._div.remove();
1263
+ const eold = old;
1264
+ if (eold) {
1265
+ eold.classList.remove(PCSS3 + "-chart-area");
1266
+ eold.innerHTML = "";
1267
+ }
1268
+ this.draw();
1269
+ } else if (!first && (name === "cutout" || name === "items" || name === "slicePadding"))
1270
+ this.draw();
1271
+ }
1272
+ get area() {
1273
+ return this._svg;
1274
+ }
1275
+ disconnectedCallback() {
1276
+ this._div && this._div.remove();
1277
+ super.disconnectedCallback();
1278
+ }
1279
+ _ensureArea() {
1280
+ if (Utils4.isNull(this._g)) {
1281
+ let div = this.target || (this._div = document.createElement("div"));
1282
+ div.classList.add(PCSS3 + "-chart-area");
1283
+ let svg = this._svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1284
+ svg.setAttribute("pacem", "");
1285
+ svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
1286
+ svg.setAttribute("viewBox", "0 0 100 100");
1287
+ svg.classList.add(PCSS3 + "-pie-chart");
1288
+ let defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
1289
+ let g = this._g = document.createElementNS("http://www.w3.org/2000/svg", "g");
1290
+ svg.appendChild(defs);
1291
+ svg.appendChild(g);
1292
+ div.appendChild(svg);
1293
+ this._div && this.parentElement.insertBefore(div, this);
1294
+ }
1295
+ if (this.maskBasedRendering) {
1296
+ if (Utils4.isNull(this._mask)) {
1297
+ let mask = document.createElementNS("http://www.w3.org/2000/svg", "mask");
1298
+ mask.id = "pie_mask_" + this._key;
1299
+ let rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
1300
+ rect.setAttribute("x", "0");
1301
+ rect.setAttribute("y", "0");
1302
+ rect.setAttribute("width", "100");
1303
+ rect.setAttribute("height", "100");
1304
+ rect.setAttribute("fill", "#fff");
1305
+ let circle = this._mask = document.createElementNS("http://www.w3.org/2000/svg", "circle");
1306
+ circle.setAttribute("cx", "50");
1307
+ circle.setAttribute("cy", "50");
1308
+ const defs = this._svg.firstElementChild;
1309
+ mask.appendChild(rect);
1310
+ mask.appendChild(circle);
1311
+ defs.appendChild(mask);
1312
+ this._g.setAttribute("mask", `url(#${mask.id})`);
1313
+ }
1314
+ const cutout = 50 * this._safeCutout;
1315
+ this._mask.setAttribute("r", `${cutout}`);
1316
+ } else {
1317
+ if (!Utils4.isNull(this._mask)) {
1318
+ this._svg.firstElementChild.innerHTML = "";
1319
+ this._mask = null;
1320
+ this._g.removeAttribute("mask");
1321
+ }
1322
+ }
1323
+ const paddingPixels = this._safeSlicePaddingPixels;
1324
+ if (paddingPixels > 0) {
1325
+ const matrix = this._svg.getCTM();
1326
+ const paddingUnits = (paddingPixels / matrix.a).roundoff();
1327
+ const maskId = this._sliceMaskId;
1328
+ const defs = this._svg.firstElementChild;
1329
+ let mask = defs.querySelector(`#${maskId}`);
1330
+ if (Utils4.isNull(mask)) {
1331
+ mask = document.createElementNS("http://www.w3.org/2000/svg", "mask");
1332
+ mask.id = maskId;
1333
+ defs.appendChild(mask);
1334
+ } else {
1335
+ mask.innerHTML = "";
1336
+ }
1337
+ const maskPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
1338
+ const d = `M${50 + paddingUnits},0 H100 V100 H0 V0 H50 V50 h${paddingUnits} Z`;
1339
+ maskPath.setAttribute("d", d);
1340
+ maskPath.setAttribute("fill", "#fff");
1341
+ mask.appendChild(maskPath);
1342
+ }
1343
+ return this._g;
1344
+ }
1345
+ get _sliceMaskId() {
1346
+ return "pieslice_mask_" + this._key;
1347
+ }
1348
+ get _safeCutout() {
1349
+ return Math.min(1, Math.max(0, this.cutout)) || 0;
1350
+ }
1351
+ get _safeSlicePaddingPixels() {
1352
+ return Math.max(0, this.slicePadding ?? 0);
1353
+ }
1354
+ _drawSlice(path, slice, whole, partial) {
1355
+ const largeFlag = slice.value > 0.5 * whole ? 1 : 0;
1356
+ const angle = TWO_PI * slice.value / whole;
1357
+ const rot = 360 * partial / whole;
1358
+ const x = slice.value >= whole ? (
1359
+ /* handling single slice */
1360
+ 49.9
1361
+ ) : 50 * (1 + Math.sin(angle));
1362
+ const y = 50 * (1 - Math.cos(angle));
1363
+ const c = this._safeCutout, r = c * 50;
1364
+ path.style.fill = slice.color;
1365
+ path.style.transform = `rotate(${rot}deg)`;
1366
+ path.style.transformOrigin = "50% 50%";
1367
+ const d = this.maskBasedRendering ? `M50,50 V0 A50,50 0 ${largeFlag} 1 ${x} ${y} L50,50 Z` : `M50,0 A50,50 0 ${largeFlag} 1 ${x} ${y} l${(50 - x) * (1 - c)},${(50 - y) * (1 - c)} A${r},${r} 0 ${largeFlag} 0 50,${50 - r} Z`;
1368
+ path.setAttribute("d", d);
1369
+ slice.normalizedPolarCoords = { radius: c + Math.SQRT1_2 * (1 - c), angle: (
1370
+ /* deg to rad */
1371
+ Math.PI * rot / 180 + angle / 2
1372
+ ) };
1373
+ }
1374
+ _isSliceOk(slice) {
1375
+ return !slice.disabled;
1376
+ }
1377
+ _padSlice(path) {
1378
+ const paddingPixels = this._safeSlicePaddingPixels;
1379
+ if (paddingPixels > 0) {
1380
+ path.setAttribute("mask", `url(#${this._sliceMaskId})`);
1381
+ } else {
1382
+ path.removeAttribute("mask");
1383
+ }
1384
+ }
1385
+ draw() {
1386
+ const g = this._ensureArea(), pCount = g.children.length, chartArea = this._svg.parentElement;
1387
+ let ndx = 0, sum = 0, progress = 0;
1388
+ if (Utils4.isNullOrEmpty(this.items)) {
1389
+ g.innerHTML = "";
1390
+ Utils4.removeClass(chartArea, "chart-has-data");
1391
+ } else {
1392
+ Utils4.addClass(chartArea, "chart-has-data");
1393
+ for (let slice of this.items) {
1394
+ if (!this._isSliceOk(slice)) {
1395
+ continue;
1396
+ }
1397
+ sum += slice.value;
1398
+ }
1399
+ if (sum <= 0) {
1400
+ g.innerHTML = "";
1401
+ Utils4.removeClass(chartArea, "chart-has-data");
1402
+ } else {
1403
+ for (let slice of this.items) {
1404
+ if (!this._isSliceOk(slice)) {
1405
+ continue;
1406
+ }
1407
+ let p;
1408
+ if (ndx >= pCount) {
1409
+ const g_n = document.createElementNS("http://www.w3.org/2000/svg", "g");
1410
+ g_n.setAttribute("class", "chart-series " + PCSS3 + "-pie-slice" + (Utils4.isNullOrEmpty(slice.className) ? "" : " " + slice.className));
1411
+ p = document.createElementNS("http://www.w3.org/2000/svg", "path");
1412
+ g_n.appendChild(p);
1413
+ g.appendChild(g_n);
1414
+ slice._assignUi(g_n);
1415
+ this._slices.set(g_n, slice);
1416
+ } else {
1417
+ p = g.children.item(ndx).firstElementChild;
1418
+ }
1419
+ if (slice.value > 0) {
1420
+ this._drawSlice(p, slice, sum, progress);
1421
+ this._padSlice(p);
1422
+ progress += slice.value;
1423
+ p.removeAttribute("display");
1424
+ } else {
1425
+ p.setAttribute("display", "none");
1426
+ }
1427
+ ndx++;
1428
+ }
1429
+ }
1430
+ }
1431
+ while (ndx < g.children.length) {
1432
+ const slices = this._slices, g_n = g.children.item(ndx);
1433
+ if (slices.has(g_n)) {
1434
+ slices.get(g_n)._disposeUi();
1435
+ slices.delete(g_n);
1436
+ }
1437
+ g.removeChild(g_n);
1438
+ }
1439
+ }
1440
+ };
1441
+ __decorate4([
1442
+ Watch4({ converter: PropertyConverters4.Number })
1443
+ ], PacemPieChartElement.prototype, "cutout", void 0);
1444
+ __decorate4([
1445
+ Watch4({ converter: PropertyConverters4.Element })
1446
+ ], PacemPieChartElement.prototype, "target", void 0);
1447
+ __decorate4([
1448
+ Watch4({ converter: PropertyConverters4.Boolean })
1449
+ ], PacemPieChartElement.prototype, "maskBasedRendering", void 0);
1450
+ __decorate4([
1451
+ Watch4({ converter: PropertyConverters4.Number })
1452
+ ], PacemPieChartElement.prototype, "slicePadding", void 0);
1453
+ __decorate4([
1454
+ Debounce(true)
1455
+ ], PacemPieChartElement.prototype, "draw", null);
1456
+ PacemPieChartElement = __decorate4([
1457
+ CustomElement4({ tagName: P4 + "-pie-chart" })
1458
+ ], PacemPieChartElement);
1459
+ export {
1460
+ index_components_exports as Components
1461
+ };
1462
+ //# sourceMappingURL=pacem-charts.mjs.map