@tolle_/tolle-ui 18.3.0 → 18.3.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,95 @@
1
+ import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { cn } from './utils/cn';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ /**
7
+ * A ranked list of horizontal bars — label left, value right, bar width
8
+ * scaled to each row's share of the list's largest value. Unlike a chart
9
+ * series or a category bar's segments, every bar is the same accent: rank is
10
+ * carried by length, not by a categorical palette.
11
+ * @new
12
+ */
13
+ export class BarListComponent {
14
+ /**
15
+ * Angular writes a bound `class` input through its styling path, which does
16
+ * not mark an OnPush component dirty — without this hook the component keeps
17
+ * rendering the class it was born with.
18
+ */
19
+ ngOnChanges() {
20
+ this.cdr.markForCheck();
21
+ }
22
+ /** Identity for `*ngFor`, so a redraw patches nodes instead of replacing them. */
23
+ trackByIndex = (index) => index;
24
+ /** Rows to rank, in the order they should be drawn. @default [] */
25
+ data = [];
26
+ /** Row key holding each row's label. @default 'label' */
27
+ labelKey = 'label';
28
+ /** Row key holding each row's numeric value. @default 'value' */
29
+ valueKey = 'value';
30
+ /** Extra Tailwind classes merged onto the list via `cn()` (last-wins). */
31
+ class = '';
32
+ cdr = inject(ChangeDetectorRef);
33
+ get rows() {
34
+ const rows = this.data ?? [];
35
+ const values = rows.map((row) => {
36
+ const num = Number(row?.[this.valueKey]);
37
+ return Number.isFinite(num) ? num : 0;
38
+ });
39
+ const max = values.reduce((m, v) => Math.max(m, v), 0);
40
+ return rows.map((row, i) => {
41
+ const raw = row?.[this.labelKey];
42
+ const value = values[i];
43
+ return {
44
+ label: raw == null ? '' : String(raw),
45
+ value,
46
+ percent: max > 0 ? Math.max(0, Math.min(100, (value / max) * 100)) : 0,
47
+ formattedValue: value.toLocaleString('en-US'),
48
+ };
49
+ });
50
+ }
51
+ get computedClass() {
52
+ return cn('flex w-full flex-col gap-1', this.class);
53
+ }
54
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BarListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
55
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: BarListComponent, isStandalone: true, selector: "tolle-bar-list", inputs: { data: "data", labelKey: "labelKey", valueKey: "valueKey", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
56
+ <div [class]="computedClass">
57
+ <div
58
+ *ngFor="let row of rows; trackBy: trackByIndex"
59
+ class="relative flex items-center overflow-hidden rounded-sm"
60
+ >
61
+ <div class="absolute inset-y-0 left-0 rounded-sm bg-primary/15" [style.width.%]="row.percent"></div>
62
+ <span class="relative z-10 truncate px-2 py-1.5 text-sm text-foreground">{{ row.label }}</span>
63
+ <span class="relative z-10 ml-auto shrink-0 px-2 py-1.5 text-sm font-medium tabular-nums text-foreground">
64
+ {{ row.formattedValue }}
65
+ </span>
66
+ </div>
67
+ </div>
68
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
69
+ }
70
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BarListComponent, decorators: [{
71
+ type: Component,
72
+ args: [{ selector: 'tolle-bar-list', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
73
+ <div [class]="computedClass">
74
+ <div
75
+ *ngFor="let row of rows; trackBy: trackByIndex"
76
+ class="relative flex items-center overflow-hidden rounded-sm"
77
+ >
78
+ <div class="absolute inset-y-0 left-0 rounded-sm bg-primary/15" [style.width.%]="row.percent"></div>
79
+ <span class="relative z-10 truncate px-2 py-1.5 text-sm text-foreground">{{ row.label }}</span>
80
+ <span class="relative z-10 ml-auto shrink-0 px-2 py-1.5 text-sm font-medium tabular-nums text-foreground">
81
+ {{ row.formattedValue }}
82
+ </span>
83
+ </div>
84
+ </div>
85
+ `, styles: [":host{display:block}\n"] }]
86
+ }], propDecorators: { data: [{
87
+ type: Input
88
+ }], labelKey: [{
89
+ type: Input
90
+ }], valueKey: [{
91
+ type: Input
92
+ }], class: [{
93
+ type: Input
94
+ }] } });
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFyLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi9iYXItbGlzdC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sWUFBWSxDQUFDOzs7QUFVaEM7Ozs7OztHQU1HO0FBc0JILE1BQU0sT0FBTyxnQkFBZ0I7SUFDM0I7Ozs7T0FJRztJQUNILFdBQVc7UUFDVCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxrRkFBa0Y7SUFDbEYsWUFBWSxHQUFHLENBQUMsS0FBYSxFQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUM7SUFFaEQsbUVBQW1FO0lBQzFELElBQUksR0FBMEIsRUFBRSxDQUFDO0lBQzFDLHlEQUF5RDtJQUNoRCxRQUFRLEdBQUcsT0FBTyxDQUFDO0lBQzVCLGlFQUFpRTtJQUN4RCxRQUFRLEdBQUcsT0FBTyxDQUFDO0lBQzVCLDBFQUEwRTtJQUNqRSxLQUFLLEdBQUcsRUFBRSxDQUFDO0lBRUgsR0FBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRWpELElBQUksSUFBSTtRQUNOLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzdCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUM5QixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDekMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUV2RCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDekIsTUFBTSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4QixPQUFPO2dCQUNMLEtBQUssRUFBRSxHQUFHLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7Z0JBQ3JDLEtBQUs7Z0JBQ0wsT0FBTyxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RFLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQzthQUM5QyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSSxhQUFhO1FBQ2YsT0FBTyxFQUFFLENBQUMsNEJBQTRCLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RELENBQUM7d0dBOUNVLGdCQUFnQjs0RkFBaEIsZ0JBQWdCLHFMQWZqQjs7Ozs7Ozs7Ozs7OztHQWFULCtGQWZTLFlBQVk7OzRGQWlCWCxnQkFBZ0I7a0JBckI1QixTQUFTOytCQUNFLGdCQUFnQixjQUVkLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyxtQkFDTix1QkFBdUIsQ0FBQyxNQUFNLFlBQ3JDOzs7Ozs7Ozs7Ozs7O0dBYVQ7OEJBZ0JRLElBQUk7c0JBQVosS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBPbkNoYW5nZXMsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5cbi8qKiBPbmUgcmVzb2x2ZWQgcm93OiBpdHMgbGFiZWwsIGl0cyB2YWx1ZSwgYW5kIGl0cyBzaGFyZSBvZiB0aGUgbGlzdCdzIGxhcmdlc3QgdmFsdWUuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhckxpc3RSb3cge1xuICBsYWJlbDogc3RyaW5nO1xuICB2YWx1ZTogbnVtYmVyO1xuICBwZXJjZW50OiBudW1iZXI7XG4gIGZvcm1hdHRlZFZhbHVlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSByYW5rZWQgbGlzdCBvZiBob3Jpem9udGFsIGJhcnMg4oCUIGxhYmVsIGxlZnQsIHZhbHVlIHJpZ2h0LCBiYXIgd2lkdGhcbiAqIHNjYWxlZCB0byBlYWNoIHJvdydzIHNoYXJlIG9mIHRoZSBsaXN0J3MgbGFyZ2VzdCB2YWx1ZS4gVW5saWtlIGEgY2hhcnRcbiAqIHNlcmllcyBvciBhIGNhdGVnb3J5IGJhcidzIHNlZ21lbnRzLCBldmVyeSBiYXIgaXMgdGhlIHNhbWUgYWNjZW50OiByYW5rIGlzXG4gKiBjYXJyaWVkIGJ5IGxlbmd0aCwgbm90IGJ5IGEgY2F0ZWdvcmljYWwgcGFsZXR0ZS5cbiAqIEBuZXdcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtYmFyLWxpc3QnLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiPlxuICAgICAgPGRpdlxuICAgICAgICAqbmdGb3I9XCJsZXQgcm93IG9mIHJvd3M7IHRyYWNrQnk6IHRyYWNrQnlJbmRleFwiXG4gICAgICAgIGNsYXNzPVwicmVsYXRpdmUgZmxleCBpdGVtcy1jZW50ZXIgb3ZlcmZsb3ctaGlkZGVuIHJvdW5kZWQtc21cIlxuICAgICAgPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWJzb2x1dGUgaW5zZXQteS0wIGxlZnQtMCByb3VuZGVkLXNtIGJnLXByaW1hcnkvMTVcIiBbc3R5bGUud2lkdGguJV09XCJyb3cucGVyY2VudFwiPjwvZGl2PlxuICAgICAgICA8c3BhbiBjbGFzcz1cInJlbGF0aXZlIHotMTAgdHJ1bmNhdGUgcHgtMiBweS0xLjUgdGV4dC1zbSB0ZXh0LWZvcmVncm91bmRcIj57eyByb3cubGFiZWwgfX08L3NwYW4+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwicmVsYXRpdmUgei0xMCBtbC1hdXRvIHNocmluay0wIHB4LTIgcHktMS41IHRleHQtc20gZm9udC1tZWRpdW0gdGFidWxhci1udW1zIHRleHQtZm9yZWdyb3VuZFwiPlxuICAgICAgICAgIHt7IHJvdy5mb3JtYXR0ZWRWYWx1ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgQmFyTGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogSWRlbnRpdHkgZm9yIGAqbmdGb3JgLCBzbyBhIHJlZHJhdyBwYXRjaGVzIG5vZGVzIGluc3RlYWQgb2YgcmVwbGFjaW5nIHRoZW0uICovXG4gIHRyYWNrQnlJbmRleCA9IChpbmRleDogbnVtYmVyKTogbnVtYmVyID0+IGluZGV4O1xuXG4gIC8qKiBSb3dzIHRvIHJhbmssIGluIHRoZSBvcmRlciB0aGV5IHNob3VsZCBiZSBkcmF3bi4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PltdID0gW107XG4gIC8qKiBSb3cga2V5IGhvbGRpbmcgZWFjaCByb3cncyBsYWJlbC4gQGRlZmF1bHQgJ2xhYmVsJyAqL1xuICBASW5wdXQoKSBsYWJlbEtleSA9ICdsYWJlbCc7XG4gIC8qKiBSb3cga2V5IGhvbGRpbmcgZWFjaCByb3cncyBudW1lcmljIHZhbHVlLiBAZGVmYXVsdCAndmFsdWUnICovXG4gIEBJbnB1dCgpIHZhbHVlS2V5ID0gJ3ZhbHVlJztcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIGxpc3QgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgZ2V0IHJvd3MoKTogQmFyTGlzdFJvd1tdIHtcbiAgICBjb25zdCByb3dzID0gdGhpcy5kYXRhID8/IFtdO1xuICAgIGNvbnN0IHZhbHVlcyA9IHJvd3MubWFwKChyb3cpID0+IHtcbiAgICAgIGNvbnN0IG51bSA9IE51bWJlcihyb3c/Llt0aGlzLnZhbHVlS2V5XSk7XG4gICAgICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKG51bSkgPyBudW0gOiAwO1xuICAgIH0pO1xuICAgIGNvbnN0IG1heCA9IHZhbHVlcy5yZWR1Y2UoKG0sIHYpID0+IE1hdGgubWF4KG0sIHYpLCAwKTtcblxuICAgIHJldHVybiByb3dzLm1hcCgocm93LCBpKSA9PiB7XG4gICAgICBjb25zdCByYXcgPSByb3c/Llt0aGlzLmxhYmVsS2V5XTtcbiAgICAgIGNvbnN0IHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGFiZWw6IHJhdyA9PSBudWxsID8gJycgOiBTdHJpbmcocmF3KSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHBlcmNlbnQ6IG1heCA+IDAgPyBNYXRoLm1heCgwLCBNYXRoLm1pbigxMDAsICh2YWx1ZSAvIG1heCkgKiAxMDApKSA6IDAsXG4gICAgICAgIGZvcm1hdHRlZFZhbHVlOiB2YWx1ZS50b0xvY2FsZVN0cmluZygnZW4tVVMnKSxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oJ2ZsZXggdy1mdWxsIGZsZXgtY29sIGdhcC0xJywgdGhpcy5jbGFzcyk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,130 @@
1
+ import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { cn } from './utils/cn';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ /**
7
+ * A single bar split into proportional, labelled ranges — for showing where
8
+ * one value falls against a scale made of categories (a credit score inside
9
+ * "Poor / Fair / Good / Excellent", latency inside "Fast / OK / Slow").
10
+ *
11
+ * Segments take the chart palette by position, since a category bar has no
12
+ * stable per-render identity to key colour off the way a chart series does —
13
+ * pass `colors` to override.
14
+ * @new
15
+ */
16
+ export class CategoryBarComponent {
17
+ /**
18
+ * Angular writes a bound `class` input through its styling path, which does
19
+ * not mark an OnPush component dirty — without this hook the component keeps
20
+ * rendering the class it was born with.
21
+ */
22
+ ngOnChanges() {
23
+ this.cdr.markForCheck();
24
+ }
25
+ /** Identity for `*ngFor`, so a redraw patches nodes instead of replacing them. */
26
+ trackByIndex = (index) => index;
27
+ /** Width of each segment. Values that are not finite and greater than zero are dropped. @default [] */
28
+ values = [];
29
+ /** Name for each segment, used in the accessible summary and as a title tooltip. @default [] */
30
+ labels = [];
31
+ /** Paint for each segment, by index. Falls back to the chart palette --chart-1 through --chart-5. @default [] */
32
+ colors = [];
33
+ /** Position of the pointer, 0-100 on the same scale the segments sum to. Omit to draw no pointer. @default null */
34
+ markerValue = null;
35
+ /** Accessible name, prefixed onto the sr-only summary of segments and marker. @default '' */
36
+ ariaLabel = '';
37
+ /** Extra Tailwind classes merged onto the bar via `cn()` (last-wins). */
38
+ class = '';
39
+ cdr = inject(ChangeDetectorRef);
40
+ get total() {
41
+ return this.values.reduce((sum, v) => (Number.isFinite(v) && v > 0 ? sum + v : sum), 0);
42
+ }
43
+ get segments() {
44
+ const total = this.total;
45
+ if (total <= 0)
46
+ return [];
47
+ return this.values
48
+ .map((value, i) => ({ value, i }))
49
+ .filter(({ value }) => Number.isFinite(value) && value > 0)
50
+ .map(({ value, i }) => ({
51
+ label: this.labels[i] ?? '',
52
+ value,
53
+ percent: (value / total) * 100,
54
+ color: this.colors[i] || 'rgb(var(--chart-' + ((i % 5) + 1) + '))',
55
+ }));
56
+ }
57
+ get clampedMarker() {
58
+ if (this.markerValue == null || !Number.isFinite(this.markerValue))
59
+ return null;
60
+ return Math.min(100, Math.max(0, this.markerValue));
61
+ }
62
+ get summary() {
63
+ const parts = this.segments.map((s) => (s.label ? s.label + ': ' : '') + s.percent.toFixed(0) + '%');
64
+ const marker = this.clampedMarker !== null ? ', current position ' + this.clampedMarker.toFixed(0) + '%' : '';
65
+ const prefix = this.ariaLabel ? this.ariaLabel + '. ' : '';
66
+ return prefix + parts.join(', ') + marker;
67
+ }
68
+ get computedClass() {
69
+ return cn('w-full', this.class);
70
+ }
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CategoryBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
72
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CategoryBarComponent, isStandalone: true, selector: "tolle-category-bar", inputs: { values: "values", labels: "labels", colors: "colors", markerValue: "markerValue", ariaLabel: "ariaLabel", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
73
+ <div [class]="computedClass">
74
+ <div class="relative flex w-full gap-0.5">
75
+ <div
76
+ *ngFor="let segment of segments; let i = index; trackBy: trackByIndex"
77
+ class="h-2 first:rounded-l-full last:rounded-r-full"
78
+ [style.width.%]="segment.percent"
79
+ [style.background]="segment.color"
80
+ [attr.title]="segment.label || null"
81
+ ></div>
82
+
83
+ <span
84
+ *ngIf="clampedMarker !== null"
85
+ class="absolute top-1/2 h-3 w-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-background bg-foreground shadow"
86
+ [style.left.%]="clampedMarker"
87
+ ></span>
88
+ </div>
89
+
90
+ <p class="sr-only">{{ summary }}</p>
91
+ </div>
92
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
93
+ }
94
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CategoryBarComponent, decorators: [{
95
+ type: Component,
96
+ args: [{ selector: 'tolle-category-bar', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
97
+ <div [class]="computedClass">
98
+ <div class="relative flex w-full gap-0.5">
99
+ <div
100
+ *ngFor="let segment of segments; let i = index; trackBy: trackByIndex"
101
+ class="h-2 first:rounded-l-full last:rounded-r-full"
102
+ [style.width.%]="segment.percent"
103
+ [style.background]="segment.color"
104
+ [attr.title]="segment.label || null"
105
+ ></div>
106
+
107
+ <span
108
+ *ngIf="clampedMarker !== null"
109
+ class="absolute top-1/2 h-3 w-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-background bg-foreground shadow"
110
+ [style.left.%]="clampedMarker"
111
+ ></span>
112
+ </div>
113
+
114
+ <p class="sr-only">{{ summary }}</p>
115
+ </div>
116
+ `, styles: [":host{display:block}\n"] }]
117
+ }], propDecorators: { values: [{
118
+ type: Input
119
+ }], labels: [{
120
+ type: Input
121
+ }], colors: [{
122
+ type: Input
123
+ }], markerValue: [{
124
+ type: Input
125
+ }], ariaLabel: [{
126
+ type: Input
127
+ }], class: [{
128
+ type: Input
129
+ }] } });
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0ZWdvcnktYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvY2F0ZWdvcnktYmFyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEgsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7OztBQVVoQzs7Ozs7Ozs7O0dBU0c7QUE2QkgsTUFBTSxPQUFPLG9CQUFvQjtJQUMvQjs7OztPQUlHO0lBQ0gsV0FBVztRQUNULElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGtGQUFrRjtJQUNsRixZQUFZLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQztJQUVoRCx1R0FBdUc7SUFDOUYsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUMvQixnR0FBZ0c7SUFDdkYsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUMvQixpSEFBaUg7SUFDeEcsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUMvQixtSEFBbUg7SUFDMUcsV0FBVyxHQUFrQixJQUFJLENBQUM7SUFDM0MsNkZBQTZGO0lBQ3BGLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDeEIseUVBQXlFO0lBQ2hFLEtBQUssR0FBRyxFQUFFLENBQUM7SUFFSCxHQUFHLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFFakQsSUFBWSxLQUFLO1FBQ2YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEs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bUJBQ04sdUJBQXVCLENBQUMsTUFBTSxZQUNyQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQlQ7OEJBZ0JRLE1BQU07c0JBQWQsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIE9uQ2hhbmdlcywgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgY24gfSBmcm9tICcuL3V0aWxzL2NuJztcblxuLyoqIE9uZSByZXNvbHZlZCBzZWdtZW50OiBpdHMgc2hhcmUgb2YgdGhlIGJhcidzIHdpZHRoLCBpdHMgcGFpbnQsIGFuZCB0aGUgbnVtYmVycyBiZWhpbmQgaXQuICovXG5leHBvcnQgaW50ZXJmYWNlIENhdGVnb3J5QmFyU2VnbWVudCB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIHZhbHVlOiBudW1iZXI7XG4gIHBlcmNlbnQ6IG51bWJlcjtcbiAgY29sb3I6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBIHNpbmdsZSBiYXIgc3BsaXQgaW50byBwcm9wb3J0aW9uYWwsIGxhYmVsbGVkIHJhbmdlcyDigJQgZm9yIHNob3dpbmcgd2hlcmVcbiAqIG9uZSB2YWx1ZSBmYWxscyBhZ2FpbnN0IGEgc2NhbGUgbWFkZSBvZiBjYXRlZ29yaWVzIChhIGNyZWRpdCBzY29yZSBpbnNpZGVcbiAqIFwiUG9vciAvIEZhaXIgLyBHb29kIC8gRXhjZWxsZW50XCIsIGxhdGVuY3kgaW5zaWRlIFwiRmFzdCAvIE9LIC8gU2xvd1wiKS5cbiAqXG4gKiBTZWdtZW50cyB0YWtlIHRoZSBjaGFydCBwYWxldHRlIGJ5IHBvc2l0aW9uLCBzaW5jZSBhIGNhdGVnb3J5IGJhciBoYXMgbm9cbiAqIHN0YWJsZSBwZXItcmVuZGVyIGlkZW50aXR5IHRvIGtleSBjb2xvdXIgb2ZmIHRoZSB3YXkgYSBjaGFydCBzZXJpZXMgZG9lcyDigJRcbiAqIHBhc3MgYGNvbG9yc2AgdG8gb3ZlcnJpZGUuXG4gKiBAbmV3XG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLWNhdGVnb3J5LWJhcicsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IFtjbGFzc109XCJjb21wdXRlZENsYXNzXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwicmVsYXRpdmUgZmxleCB3LWZ1bGwgZ2FwLTAuNVwiPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgKm5nRm9yPVwibGV0IHNlZ21lbnQgb2Ygc2VnbWVudHM7IGxldCBpID0gaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlJbmRleFwiXG4gICAgICAgICAgY2xhc3M9XCJoLTIgZmlyc3Q6cm91bmRlZC1sLWZ1bGwgbGFzdDpyb3VuZGVkLXItZnVsbFwiXG4gICAgICAgICAgW3N0eWxlLndpZHRoLiVdPVwic2VnbWVudC5wZXJjZW50XCJcbiAgICAgICAgICBbc3R5bGUuYmFja2dyb3VuZF09XCJzZWdtZW50LmNvbG9yXCJcbiAgICAgICAgICBbYXR0ci50aXRsZV09XCJzZWdtZW50LmxhYmVsIHx8IG51bGxcIlxuICAgICAgICA+PC9kaXY+XG5cbiAgICAgICAgPHNwYW5cbiAgICAgICAgICAqbmdJZj1cImNsYW1wZWRNYXJrZXIgIT09IG51bGxcIlxuICAgICAgICAgIGNsYXNzPVwiYWJzb2x1dGUgdG9wLTEvMiBoLTMgdy0zIC10cmFuc2xhdGUteC0xLzIgLXRyYW5zbGF0ZS15LTEvMiByb3VuZGVkLWZ1bGwgYm9yZGVyLTIgYm9yZGVyLWJhY2tncm91bmQgYmctZm9yZWdyb3VuZCBzaGFkb3dcIlxuICAgICAgICAgIFtzdHlsZS5sZWZ0LiVdPVwiY2xhbXBlZE1hcmtlclwiXG4gICAgICAgID48L3NwYW4+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJzci1vbmx5XCI+e3sgc3VtbWFyeSB9fTwvcD5cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgQ2F0ZWdvcnlCYXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICAvKipcbiAgICogQW5ndWxhciB3cml0ZXMgYSBib3VuZCBgY2xhc3NgIGlucHV0IHRocm91Z2ggaXRzIHN0eWxpbmcgcGF0aCwgd2hpY2ggZG9lc1xuICAgKiBub3QgbWFyayBhbiBPblB1c2ggY29tcG9uZW50IGRpcnR5IOKAlCB3aXRob3V0IHRoaXMgaG9vayB0aGUgY29tcG9uZW50IGtlZXBzXG4gICAqIHJlbmRlcmluZyB0aGUgY2xhc3MgaXQgd2FzIGJvcm4gd2l0aC5cbiAgICovXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqIElkZW50aXR5IGZvciBgKm5nRm9yYCwgc28gYSByZWRyYXcgcGF0Y2hlcyBub2RlcyBpbnN0ZWFkIG9mIHJlcGxhY2luZyB0aGVtLiAqL1xuICB0cmFja0J5SW5kZXggPSAoaW5kZXg6IG51bWJlcik6IG51bWJlciA9PiBpbmRleDtcblxuICAvKiogV2lkdGggb2YgZWFjaCBzZWdtZW50LiBWYWx1ZXMgdGhhdCBhcmUgbm90IGZpbml0ZSBhbmQgZ3JlYXRlciB0aGFuIHplcm8gYXJlIGRyb3BwZWQuIEBkZWZhdWx0IFtdICovXG4gIEBJbnB1dCgpIHZhbHVlczogbnVtYmVyW10gPSBbXTtcbiAgLyoqIE5hbWUgZm9yIGVhY2ggc2VnbWVudCwgdXNlZCBpbiB0aGUgYWNjZXNzaWJsZSBzdW1tYXJ5IGFuZCBhcyBhIHRpdGxlIHRvb2x0aXAuIEBkZWZhdWx0IFtdICovXG4gIEBJbnB1dCgpIGxhYmVsczogc3RyaW5nW10gPSBbXTtcbiAgLyoqIFBhaW50IGZvciBlYWNoIHNlZ21lbnQsIGJ5IGluZGV4LiBGYWxscyBiYWNrIHRvIHRoZSBjaGFydCBwYWxldHRlIC0tY2hhcnQtMSB0aHJvdWdoIC0tY2hhcnQtNS4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgY29sb3JzOiBzdHJpbmdbXSA9IFtdO1xuICAvKiogUG9zaXRpb24gb2YgdGhlIHBvaW50ZXIsIDAtMTAwIG9uIHRoZSBzYW1lIHNjYWxlIHRoZSBzZWdtZW50cyBzdW0gdG8uIE9taXQgdG8gZHJhdyBubyBwb2ludGVyLiBAZGVmYXVsdCBudWxsICovXG4gIEBJbnB1dCgpIG1hcmtlclZhbHVlOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIEFjY2Vzc2libGUgbmFtZSwgcHJlZml4ZWQgb250byB0aGUgc3Itb25seSBzdW1tYXJ5IG9mIHNlZ21lbnRzIGFuZCBtYXJrZXIuIEBkZWZhdWx0ICcnICovXG4gIEBJbnB1dCgpIGFyaWFMYWJlbCA9ICcnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgYmFyIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gIHByaXZhdGUgZ2V0IHRvdGFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLnJlZHVjZSgoc3VtLCB2KSA9PiAoTnVtYmVyLmlzRmluaXRlKHYpICYmIHYgPiAwID8gc3VtICsgdiA6IHN1bSksIDApO1xuICB9XG5cbiAgZ2V0IHNlZ21lbnRzKCk6IENhdGVnb3J5QmFyU2VnbWVudFtdIHtcbiAgICBjb25zdCB0b3RhbCA9IHRoaXMudG90YWw7XG4gICAgaWYgKHRvdGFsIDw9IDApIHJldHVybiBbXTtcblxuICAgIHJldHVybiB0aGlzLnZhbHVlc1xuICAgICAgLm1hcCgodmFsdWUsIGkpID0+ICh7IHZhbHVlLCBpIH0pKVxuICAgICAgLmZpbHRlcigoeyB2YWx1ZSB9KSA9PiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpICYmIHZhbHVlID4gMClcbiAgICAgIC5tYXAoKHsgdmFsdWUsIGkgfSkgPT4gKHtcbiAgICAgICAgbGFiZWw6IHRoaXMubGFiZWxzW2ldID8/ICcnLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgcGVyY2VudDogKHZhbHVlIC8gdG90YWwpICogMTAwLFxuICAgICAgICBjb2xvcjogdGhpcy5jb2xvcnNbaV0gfHwgJ3JnYih2YXIoLS1jaGFydC0nICsgKChpICUgNSkgKyAxKSArICcpKScsXG4gICAgICB9KSk7XG4gIH1cblxuICBnZXQgY2xhbXBlZE1hcmtlcigpOiBudW1iZXIgfCBudWxsIHtcbiAgICBpZiAodGhpcy5tYXJrZXJWYWx1ZSA9PSBudWxsIHx8ICFOdW1iZXIuaXNGaW5pdGUodGhpcy5tYXJrZXJWYWx1ZSkpIHJldHVybiBudWxsO1xuICAgIHJldHVybiBNYXRoLm1pbigxMDAsIE1hdGgubWF4KDAsIHRoaXMubWFya2VyVmFsdWUpKTtcbiAgfVxuXG4gIGdldCBzdW1tYXJ5KCk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHMgPSB0aGlzLnNlZ21lbnRzLm1hcCgocykgPT4gKHMubGFiZWwgPyBzLmxhYmVsICsgJzogJyA6ICcnKSArIHMucGVyY2VudC50b0ZpeGVkKDApICsgJyUnKTtcbiAgICBjb25zdCBtYXJrZXIgPSB0aGlzLmNsYW1wZWRNYXJrZXIgIT09IG51bGwgPyAnLCBjdXJyZW50IHBvc2l0aW9uICcgKyB0aGlzLmNsYW1wZWRNYXJrZXIudG9GaXhlZCgwKSArICclJyA6ICcnO1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMuYXJpYUxhYmVsID8gdGhpcy5hcmlhTGFiZWwgKyAnLiAnIDogJyc7XG4gICAgcmV0dXJuIHByZWZpeCArIHBhcnRzLmpvaW4oJywgJykgKyBtYXJrZXI7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oJ3ctZnVsbCcsIHRoaXMuY2xhc3MpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,120 @@
1
+ import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { ChartComponent, ChartLineComponent, ChartAreaComponent, ChartBarComponent, } from './chart.component';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ /**
7
+ * A minimal inline chart: one series, no grid, no axes, no legend — sized to
8
+ * sit next to a number in a table cell or a stat card. A thin composition
9
+ * over `tolle-chart`; it draws nothing of its own and inherits `--chart-1`
10
+ * the same way any other single-series chart in this library does.
11
+ * @new
12
+ */
13
+ export class ChartSparkComponent {
14
+ /**
15
+ * Angular writes a bound `class` input through its styling path, which does
16
+ * not mark an OnPush component dirty — without this hook the component keeps
17
+ * rendering the class it was born with.
18
+ */
19
+ ngOnChanges() {
20
+ this.cdr.markForCheck();
21
+ }
22
+ /** Rows to plot, in x order. @default [] */
23
+ data = [];
24
+ /** Row key holding each row's numeric value. @default 'value' */
25
+ valueKey = 'value';
26
+ /** Row key holding each row's x position. Only matters once `hover` is on. @default '' */
27
+ xKey = '';
28
+ /** Which mark to draw. @default 'line' */
29
+ type = 'line';
30
+ /** Interpolation for line/area. @default 'linear' */
31
+ curve = 'linear';
32
+ /** Largest bar thickness in px, used when `type` is 'bar'. @default 6 */
33
+ maxBarWidth = 6;
34
+ /** Height in px. @default 32 */
35
+ height = 32;
36
+ /** Renders the crosshair, hit layer and tooltip. @default false */
37
+ hover = false;
38
+ /** Shows the data table instead of leaving it visually hidden. @default false */
39
+ showTable = false;
40
+ /** Accessible name, used as the svg <title>. @default '' */
41
+ ariaLabel = '';
42
+ /** Longer summary used as the svg <desc>. Falls back to `ariaLabel`. @default '' */
43
+ description = '';
44
+ /** Space reserved around the plot — a sparkline has no axis labels to fit. @default { top: 2, right: 2, bottom: 2, left: 2 } */
45
+ margin = { top: 2, right: 2, bottom: 2, left: 2 };
46
+ /** Extra Tailwind classes merged onto the chart via `cn()` (last-wins). */
47
+ class = '';
48
+ cdr = inject(ChangeDetectorRef);
49
+ /** Always exactly one series, reading `valueKey` off each row. */
50
+ get series() {
51
+ return [{ key: this.valueKey, label: this.ariaLabel || this.valueKey }];
52
+ }
53
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChartSparkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
54
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ChartSparkComponent, isStandalone: true, selector: "tolle-chart-spark", inputs: { data: "data", valueKey: "valueKey", xKey: "xKey", type: "type", curve: "curve", maxBarWidth: "maxBarWidth", height: "height", hover: "hover", showTable: "showTable", ariaLabel: "ariaLabel", description: "description", margin: "margin", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
55
+ <tolle-chart
56
+ [class]="class"
57
+ [data]="data"
58
+ [series]="series"
59
+ [xKey]="xKey"
60
+ [height]="height"
61
+ [margin]="margin"
62
+ [hover]="hover"
63
+ [showTable]="showTable"
64
+ [ariaLabel]="ariaLabel"
65
+ [description]="description"
66
+ >
67
+ <svg:g *ngIf="type === 'line'" tolle-chart-line [seriesKey]="valueKey" [curve]="curve"></svg:g>
68
+ <svg:g *ngIf="type === 'area'" tolle-chart-area [seriesKey]="valueKey" [curve]="curve"></svg:g>
69
+ <svg:g *ngIf="type === 'bar'" tolle-chart-bar [seriesKey]="valueKey" [maxWidth]="maxBarWidth"></svg:g>
70
+ </tolle-chart>
71
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ChartComponent, selector: "tolle-chart", inputs: ["data", "series", "xKey", "height", "margin", "ariaLabel", "description", "stacked", "orientation", "hover", "showTable", "xHeader", "variant", "density", "class"], outputs: ["activeIndexChange"] }, { kind: "component", type: ChartLineComponent, selector: "svg:g[tolle-chart-line]", inputs: ["seriesKey", "curve", "showDots", "dotRadius", "class"] }, { kind: "component", type: ChartAreaComponent, selector: "svg:g[tolle-chart-area]", inputs: ["seriesKey", "curve", "fillOpacity", "class"] }, { kind: "component", type: ChartBarComponent, selector: "svg:g[tolle-chart-bar]", inputs: ["seriesKey", "radius", "maxWidth", "gap", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
72
+ }
73
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChartSparkComponent, decorators: [{
74
+ type: Component,
75
+ args: [{ selector: 'tolle-chart-spark', standalone: true, imports: [CommonModule, ChartComponent, ChartLineComponent, ChartAreaComponent, ChartBarComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
76
+ <tolle-chart
77
+ [class]="class"
78
+ [data]="data"
79
+ [series]="series"
80
+ [xKey]="xKey"
81
+ [height]="height"
82
+ [margin]="margin"
83
+ [hover]="hover"
84
+ [showTable]="showTable"
85
+ [ariaLabel]="ariaLabel"
86
+ [description]="description"
87
+ >
88
+ <svg:g *ngIf="type === 'line'" tolle-chart-line [seriesKey]="valueKey" [curve]="curve"></svg:g>
89
+ <svg:g *ngIf="type === 'area'" tolle-chart-area [seriesKey]="valueKey" [curve]="curve"></svg:g>
90
+ <svg:g *ngIf="type === 'bar'" tolle-chart-bar [seriesKey]="valueKey" [maxWidth]="maxBarWidth"></svg:g>
91
+ </tolle-chart>
92
+ `, styles: [":host{display:block}\n"] }]
93
+ }], propDecorators: { data: [{
94
+ type: Input
95
+ }], valueKey: [{
96
+ type: Input
97
+ }], xKey: [{
98
+ type: Input
99
+ }], type: [{
100
+ type: Input
101
+ }], curve: [{
102
+ type: Input
103
+ }], maxBarWidth: [{
104
+ type: Input
105
+ }], height: [{
106
+ type: Input
107
+ }], hover: [{
108
+ type: Input
109
+ }], showTable: [{
110
+ type: Input
111
+ }], ariaLabel: [{
112
+ type: Input
113
+ }], description: [{
114
+ type: Input
115
+ }], margin: [{
116
+ type: Input
117
+ }], class: [{
118
+ type: Input
119
+ }] } });
120
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQtc3BhcmsuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi9jaGFydC1zcGFyay5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsY0FBYyxFQUNkLGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIsaUJBQWlCLEdBR2xCLE1BQU0sbUJBQW1CLENBQUM7OztBQUUzQjs7Ozs7O0dBTUc7QUEwQkgsTUFBTSxPQUFPLG1CQUFtQjtJQUM5Qjs7OztPQUlHO0lBQ0gsV0FBVztRQUNULElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELDRDQUE0QztJQUNuQyxJQUFJLEdBQTBCLEVBQUUsQ0FBQztJQUMxQyxpRUFBaUU7SUFDeEQsUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUM1QiwwRkFBMEY7SUFDakYsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNuQiwwQ0FBMEM7SUFDakMsSUFBSSxHQUE0QixNQUFNLENBQUM7SUFDaEQscURBQXFEO0lBQzVDLEtBQUssR0FBd0IsUUFBUSxDQUFDO0lBQy9DLHlFQUF5RTtJQUNoRSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLGdDQUFnQztJQUN2QixNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLG1FQUFtRTtJQUMxRCxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLGlGQUFpRjtJQUN4RSxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQzNCLDREQUE0RDtJQUNuRCxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLG9GQUFvRjtJQUMzRSxXQUFXLEdBQUcsRUFBRSxDQUFDO0lBQzFCLGdJQUFnSTtJQUN2SCxNQUFNLEdBQWdCLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hFLDJFQUEyRTtJQUNsRSxLQUFLLEdBQUcsRUFBRSxDQUFDO0lBRUgsR0FBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRWpELGtFQUFrRTtJQUNsRSxJQUFJLE1BQU07UUFDUixPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUMxRSxDQUFDO3dHQTFDVSxtQkFBbUI7NEZBQW5CLG1CQUFtQiwwV0FuQnBCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCVCwrRkFuQlMsWUFBWSxtSUFBRSxjQUFjLHNRQUFFLGtCQUFrQixzSUFBRSxrQkFBa0IsNEhBQUUsaUJBQWlCOzs0RkFxQnRGLG1CQUFtQjtrQkF6Qi9CLFNBQVM7K0JBQ0UsbUJBQW1CLGNBRWpCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsaUJBQWlCLENBQUMsbUJBQ2pGLHVCQUF1QixDQUFDLE1BQU0sWUFDckM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJUOzhCQWFRLElBQUk7c0JBQVosS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBPbkNoYW5nZXMsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIENoYXJ0Q29tcG9uZW50LFxuICBDaGFydExpbmVDb21wb25lbnQsXG4gIENoYXJ0QXJlYUNvbXBvbmVudCxcbiAgQ2hhcnRCYXJDb21wb25lbnQsXG4gIHR5cGUgQ2hhcnRNYXJnaW4sXG4gIHR5cGUgQ2hhcnRTZXJpZXMsXG59IGZyb20gJy4vY2hhcnQuY29tcG9uZW50JztcblxuLyoqXG4gKiBBIG1pbmltYWwgaW5saW5lIGNoYXJ0OiBvbmUgc2VyaWVzLCBubyBncmlkLCBubyBheGVzLCBubyBsZWdlbmQg4oCUIHNpemVkIHRvXG4gKiBzaXQgbmV4dCB0byBhIG51bWJlciBpbiBhIHRhYmxlIGNlbGwgb3IgYSBzdGF0IGNhcmQuIEEgdGhpbiBjb21wb3NpdGlvblxuICogb3ZlciBgdG9sbGUtY2hhcnRgOyBpdCBkcmF3cyBub3RoaW5nIG9mIGl0cyBvd24gYW5kIGluaGVyaXRzIGAtLWNoYXJ0LTFgXG4gKiB0aGUgc2FtZSB3YXkgYW55IG90aGVyIHNpbmdsZS1zZXJpZXMgY2hhcnQgaW4gdGhpcyBsaWJyYXJ5IGRvZXMuXG4gKiBAbmV3XG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLWNoYXJ0LXNwYXJrJyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgQ2hhcnRDb21wb25lbnQsIENoYXJ0TGluZUNvbXBvbmVudCwgQ2hhcnRBcmVhQ29tcG9uZW50LCBDaGFydEJhckNvbXBvbmVudF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDx0b2xsZS1jaGFydFxuICAgICAgW2NsYXNzXT1cImNsYXNzXCJcbiAgICAgIFtkYXRhXT1cImRhdGFcIlxuICAgICAgW3Nlcmllc109XCJzZXJpZXNcIlxuICAgICAgW3hLZXldPVwieEtleVwiXG4gICAgICBbaGVpZ2h0XT1cImhlaWdodFwiXG4gICAgICBbbWFyZ2luXT1cIm1hcmdpblwiXG4gICAgICBbaG92ZXJdPVwiaG92ZXJcIlxuICAgICAgW3Nob3dUYWJsZV09XCJzaG93VGFibGVcIlxuICAgICAgW2FyaWFMYWJlbF09XCJhcmlhTGFiZWxcIlxuICAgICAgW2Rlc2NyaXB0aW9uXT1cImRlc2NyaXB0aW9uXCJcbiAgICA+XG4gICAgICA8c3ZnOmcgKm5nSWY9XCJ0eXBlID09PSAnbGluZSdcIiB0b2xsZS1jaGFydC1saW5lIFtzZXJpZXNLZXldPVwidmFsdWVLZXlcIiBbY3VydmVdPVwiY3VydmVcIj48L3N2ZzpnPlxuICAgICAgPHN2ZzpnICpuZ0lmPVwidHlwZSA9PT0gJ2FyZWEnXCIgdG9sbGUtY2hhcnQtYXJlYSBbc2VyaWVzS2V5XT1cInZhbHVlS2V5XCIgW2N1cnZlXT1cImN1cnZlXCI+PC9zdmc6Zz5cbiAgICAgIDxzdmc6ZyAqbmdJZj1cInR5cGUgPT09ICdiYXInXCIgdG9sbGUtY2hhcnQtYmFyIFtzZXJpZXNLZXldPVwidmFsdWVLZXlcIiBbbWF4V2lkdGhdPVwibWF4QmFyV2lkdGhcIj48L3N2ZzpnPlxuICAgIDwvdG9sbGUtY2hhcnQ+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIENoYXJ0U3BhcmtDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICAvKipcbiAgICogQW5ndWxhciB3cml0ZXMgYSBib3VuZCBgY2xhc3NgIGlucHV0IHRocm91Z2ggaXRzIHN0eWxpbmcgcGF0aCwgd2hpY2ggZG9lc1xuICAgKiBub3QgbWFyayBhbiBPblB1c2ggY29tcG9uZW50IGRpcnR5IOKAlCB3aXRob3V0IHRoaXMgaG9vayB0aGUgY29tcG9uZW50IGtlZXBzXG4gICAqIHJlbmRlcmluZyB0aGUgY2xhc3MgaXQgd2FzIGJvcm4gd2l0aC5cbiAgICovXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqIFJvd3MgdG8gcGxvdCwgaW4geCBvcmRlci4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PltdID0gW107XG4gIC8qKiBSb3cga2V5IGhvbGRpbmcgZWFjaCByb3cncyBudW1lcmljIHZhbHVlLiBAZGVmYXVsdCAndmFsdWUnICovXG4gIEBJbnB1dCgpIHZhbHVlS2V5ID0gJ3ZhbHVlJztcbiAgLyoqIFJvdyBrZXkgaG9sZGluZyBlYWNoIHJvdydzIHggcG9zaXRpb24uIE9ubHkgbWF0dGVycyBvbmNlIGBob3ZlcmAgaXMgb24uIEBkZWZhdWx0ICcnICovXG4gIEBJbnB1dCgpIHhLZXkgPSAnJztcbiAgLyoqIFdoaWNoIG1hcmsgdG8gZHJhdy4gQGRlZmF1bHQgJ2xpbmUnICovXG4gIEBJbnB1dCgpIHR5cGU6ICdsaW5lJyB8ICdhcmVhJyB8ICdiYXInID0gJ2xpbmUnO1xuICAvKiogSW50ZXJwb2xhdGlvbiBmb3IgbGluZS9hcmVhLiBAZGVmYXVsdCAnbGluZWFyJyAqL1xuICBASW5wdXQoKSBjdXJ2ZTogJ2xpbmVhcicgfCAnc21vb3RoJyA9ICdsaW5lYXInO1xuICAvKiogTGFyZ2VzdCBiYXIgdGhpY2tuZXNzIGluIHB4LCB1c2VkIHdoZW4gYHR5cGVgIGlzICdiYXInLiBAZGVmYXVsdCA2ICovXG4gIEBJbnB1dCgpIG1heEJhcldpZHRoID0gNjtcbiAgLyoqIEhlaWdodCBpbiBweC4gQGRlZmF1bHQgMzIgKi9cbiAgQElucHV0KCkgaGVpZ2h0ID0gMzI7XG4gIC8qKiBSZW5kZXJzIHRoZSBjcm9zc2hhaXIsIGhpdCBsYXllciBhbmQgdG9vbHRpcC4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgaG92ZXIgPSBmYWxzZTtcbiAgLyoqIFNob3dzIHRoZSBkYXRhIHRhYmxlIGluc3RlYWQgb2YgbGVhdmluZyBpdCB2aXN1YWxseSBoaWRkZW4uIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHNob3dUYWJsZSA9IGZhbHNlO1xuICAvKiogQWNjZXNzaWJsZSBuYW1lLCB1c2VkIGFzIHRoZSBzdmcgPHRpdGxlPi4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgYXJpYUxhYmVsID0gJyc7XG4gIC8qKiBMb25nZXIgc3VtbWFyeSB1c2VkIGFzIHRoZSBzdmcgPGRlc2M+LiBGYWxscyBiYWNrIHRvIGBhcmlhTGFiZWxgLiBAZGVmYXVsdCAnJyAqL1xuICBASW5wdXQoKSBkZXNjcmlwdGlvbiA9ICcnO1xuICAvKiogU3BhY2UgcmVzZXJ2ZWQgYXJvdW5kIHRoZSBwbG90IOKAlCBhIHNwYXJrbGluZSBoYXMgbm8gYXhpcyBsYWJlbHMgdG8gZml0LiBAZGVmYXVsdCB7IHRvcDogMiwgcmlnaHQ6IDIsIGJvdHRvbTogMiwgbGVmdDogMiB9ICovXG4gIEBJbnB1dCgpIG1hcmdpbjogQ2hhcnRNYXJnaW4gPSB7IHRvcDogMiwgcmlnaHQ6IDIsIGJvdHRvbTogMiwgbGVmdDogMiB9O1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgY2hhcnQgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgLyoqIEFsd2F5cyBleGFjdGx5IG9uZSBzZXJpZXMsIHJlYWRpbmcgYHZhbHVlS2V5YCBvZmYgZWFjaCByb3cuICovXG4gIGdldCBzZXJpZXMoKTogQ2hhcnRTZXJpZXNbXSB7XG4gICAgcmV0dXJuIFt7IGtleTogdGhpcy52YWx1ZUtleSwgbGFiZWw6IHRoaXMuYXJpYUxhYmVsIHx8IHRoaXMudmFsdWVLZXkgfV07XG4gIH1cbn1cbiJdfQ==