@foxeltech/angular-ui 0.7.106 → 0.7.108

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.
package/components.css CHANGED
@@ -849,3 +849,186 @@ input[type='password'] {
849
849
  .fx-rs-busy > *:not(fx-ui-route-skeleton) {
850
850
  display: none !important;
851
851
  }
852
+
853
+ /* ============================================================================
854
+ Grid tables, badges and status dots to the reference HTML (Binary
855
+ Intelligence Dashboard, porcelain) — anh Tú 15/09, moved into the lib in
856
+ 0.7.107 from three identical copies in analyze/knowledge/host styles.scss.
857
+
858
+ The reference draws its lists as CSS-grid rows, not <table>: a sunken 10px
859
+ header in 10.5px/600 tracked faint, 11px rows split by hairlines, hover to
860
+ surface-sunken, a trailing caret that turns accent and slides 2px. Columns
861
+ come from the consumer as `--fx-cols` on `.fx-grid-table`.
862
+
863
+ Inside layer(components) like the rest of this file, so a Tailwind utility
864
+ on the same element still wins.
865
+ ============================================================================ */
866
+ .fx-grid-table {
867
+ border: 1px solid rgb(var(--og-border));
868
+ border-radius: var(--og-radius-card);
869
+ background: rgb(var(--og-surface));
870
+ overflow: hidden;
871
+ }
872
+ .fx-grid-table__head,
873
+ .fx-grid-table__row {
874
+ display: grid;
875
+ grid-template-columns: var(--fx-cols);
876
+ gap: 12px;
877
+ align-items: center;
878
+ padding: 10px 12px;
879
+ }
880
+ .fx-grid-table__head {
881
+ border-bottom: 1px solid rgb(var(--og-border));
882
+ background: rgb(var(--og-surface-sunken));
883
+ font-size: var(--og-fs-2xs);
884
+ font-weight: 600;
885
+ letter-spacing: var(--og-tracking-label);
886
+ color: rgb(var(--og-text-faint));
887
+ }
888
+ .fx-grid-table__row {
889
+ appearance: none;
890
+ width: 100%;
891
+ padding: 11px 12px;
892
+ border: 0;
893
+ border-bottom: 1px solid rgb(var(--og-border-subtle));
894
+ background: transparent;
895
+ text-align: left;
896
+ cursor: pointer;
897
+ font: inherit;
898
+ color: inherit;
899
+ transition: background-color 130ms ease;
900
+ }
901
+ .fx-grid-table__row:last-child {
902
+ border-bottom: 0;
903
+ }
904
+ .fx-grid-table__row:hover {
905
+ background: rgb(var(--og-surface-sunken));
906
+ }
907
+ .fx-grid-table__row--on {
908
+ background: rgb(var(--og-accent-soft-bg));
909
+ }
910
+ .fx-grid-table__row:focus-visible {
911
+ outline: 2px solid rgb(var(--og-accent));
912
+ outline-offset: -2px;
913
+ }
914
+ .fx-grid-caret {
915
+ font-size: 15px;
916
+ line-height: 1;
917
+ color: rgb(var(--og-text-faint));
918
+ justify-self: end;
919
+ transition:
920
+ color 130ms ease,
921
+ transform 130ms ease;
922
+ }
923
+ .fx-grid-table__row:hover .fx-grid-caret {
924
+ color: rgb(var(--og-accent));
925
+ transform: translateX(2px);
926
+ }
927
+ .fx-grid-table__num {
928
+ font-family: var(--og-font-mono);
929
+ font-size: var(--og-fs-sm);
930
+ color: rgb(var(--og-text-body));
931
+ text-align: right;
932
+ font-variant-numeric: tabular-nums;
933
+ }
934
+ .fx-grid-table__head .fx-grid-table__num {
935
+ font-family: inherit;
936
+ font-size: inherit;
937
+ color: inherit;
938
+ }
939
+ .fx-grid-table__strong {
940
+ font-size: var(--og-fs-sm);
941
+ font-weight: 600;
942
+ color: rgb(var(--og-text));
943
+ }
944
+ .fx-grid-table__muted {
945
+ font-size: var(--og-fs-xs);
946
+ color: rgb(var(--og-text-muted));
947
+ }
948
+ .fx-grid-table__mono {
949
+ font-family: var(--og-font-mono);
950
+ font-size: var(--og-fs-xs);
951
+ color: rgb(var(--og-text-faint));
952
+ }
953
+ .fx-grid-empty {
954
+ padding: 15px;
955
+ text-align: center;
956
+ color: rgb(var(--og-text-muted));
957
+ font-size: var(--og-fs-sm);
958
+ border: 1px dashed rgb(var(--og-border));
959
+ border-radius: var(--og-radius-card);
960
+ }
961
+
962
+ /* `.og-badge`: 3px 10px, pill, 11.5px, soft tint by tone; outline = the
963
+ neutral "Low" band; solid = Critical. Tone names are the SEMANTIC tokens
964
+ (`--og-negative`, not the chart ramp) — see the note above `.tone-tint-*`. */
965
+ .fx-badge {
966
+ display: inline-flex;
967
+ align-items: center;
968
+ gap: 5px;
969
+ padding: 3px 10px;
970
+ border-radius: var(--og-radius-pill);
971
+ font-size: var(--og-fs-xs);
972
+ line-height: 1.5;
973
+ white-space: nowrap;
974
+ font-weight: 500;
975
+ }
976
+ .fx-badge--negative {
977
+ background: rgb(var(--og-negative-soft-bg));
978
+ color: rgb(var(--og-negative));
979
+ }
980
+ .fx-badge--warning {
981
+ background: rgb(var(--og-warning-soft-bg));
982
+ color: rgb(var(--og-warning));
983
+ }
984
+ .fx-badge--positive {
985
+ background: rgb(var(--og-positive-soft-bg));
986
+ color: rgb(var(--og-positive));
987
+ }
988
+ .fx-badge--neutral {
989
+ background: rgb(var(--og-neutral-soft-bg));
990
+ color: rgb(var(--og-neutral-soft-fg));
991
+ }
992
+ .fx-badge--accent {
993
+ background: rgb(var(--og-accent-soft-bg));
994
+ color: rgb(var(--og-accent-soft-fg));
995
+ }
996
+ .fx-badge--outline {
997
+ background: none;
998
+ border: 1px solid rgb(var(--og-border));
999
+ color: rgb(var(--og-text-muted));
1000
+ }
1001
+ .fx-badge--solid {
1002
+ background: rgb(var(--og-text));
1003
+ color: rgb(var(--og-surface));
1004
+ }
1005
+
1006
+ /* `.og-statusdot`: a 7px mark and the state's name. */
1007
+ .fx-statusdot {
1008
+ display: inline-flex;
1009
+ align-items: center;
1010
+ gap: 6px;
1011
+ font-size: var(--og-fs-sm);
1012
+ color: rgb(var(--og-text-body));
1013
+ white-space: nowrap;
1014
+ }
1015
+ .fx-statusdot::before {
1016
+ content: '';
1017
+ width: 7px;
1018
+ height: 7px;
1019
+ border-radius: 50%;
1020
+ background: rgb(var(--og-text-faint));
1021
+ flex: none;
1022
+ }
1023
+ .fx-statusdot--positive::before {
1024
+ background: rgb(var(--og-positive));
1025
+ }
1026
+ .fx-statusdot--negative::before {
1027
+ background: rgb(var(--og-negative));
1028
+ }
1029
+ .fx-statusdot--warning::before {
1030
+ background: rgb(var(--og-warning));
1031
+ }
1032
+ .fx-statusdot--accent::before {
1033
+ background: rgb(var(--og-accent));
1034
+ }
@@ -28,6 +28,14 @@ class ChartComponent {
28
28
  * rather than an annotation.
29
29
  */
30
30
  pieCenterValueSize = input(24, ...(ngDevMode ? [{ debugName: "pieCenterValueSize" }] : /* istanbul ignore next */ []));
31
+ /**
32
+ * The donut's [inner, outer] radius — ECharts' own vocabulary, so either a
33
+ * percentage of the shorter side or a pixel count. The default is what the
34
+ * ring has always been. The reference dashboard draws a 140px ring with a
35
+ * 22px stroke, i.e. `[48, 70]` at `height="140px"` — the panel that wants it
36
+ * says so; the other pies keep their proportions.
37
+ */
38
+ pieRadius = input(['40%', '70%'], ...(ngDevMode ? [{ debugName: "pieRadius" }] : /* istanbul ignore next */ []));
31
39
  mobileWidth = input(350, ...(ngDevMode ? [{ debugName: "mobileWidth" }] : /* istanbul ignore next */ []));
32
40
  /** Override font for canvas text; empty = follow the theme's --og-font-figure. */
33
41
  labelFontFamily = input('', ...(ngDevMode ? [{ debugName: "labelFontFamily" }] : /* istanbul ignore next */ []));
@@ -94,6 +102,8 @@ class ChartComponent {
94
102
  */
95
103
  appearUntil = 0;
96
104
  static APPEAR_MS = 1100;
105
+ /** Quiet time a host size has to hold before a resize is acted on. */
106
+ static RESIZE_SETTLE_MS = 120;
97
107
  deferTimer;
98
108
  /**
99
109
  * Thay đổi kích thước ghi nhận TRONG cửa sổ appear, chờ áp sau. `measure()`
@@ -123,10 +133,15 @@ class ChartComponent {
123
133
  // resize() mù sau throttle 100ms, kể cả về 0×H khi phần tử display:none
124
134
  // (skeleton route ẩn nội dung cũ) rồi resize lại khi hiện → animation
125
135
  // xuất hiện bị giết (đo 05/09 khi đổi project trên chip breadcrumb).
136
+ // Coalesced: a host that is being ANIMATED (the drawer's 300ms width
137
+ // tween, a panel sliding open) fires one RO event per frame, and acting
138
+ // on each one resized + rebuilt the pie ~18 times and replayed its appear
139
+ // animation twice (anh Tú 15/09, donut on sidebar toggle). Wait until the
140
+ // size has been still for RESIZE_SETTLE_MS, then act once.
126
141
  this.resizeObserver = new ResizeObserver(() => {
127
142
  if (!this.canInit || this.destroyed)
128
143
  return;
129
- this.forceMediaRecalc();
144
+ this.deferResize(ChartComponent.RESIZE_SETTLE_MS);
130
145
  });
131
146
  this.resizeObserver.observe(this.ref.nativeElement);
132
147
  }
@@ -285,10 +300,18 @@ class ChartComponent {
285
300
  markAppear() {
286
301
  this.appearUntil = performance.now() + ChartComponent.APPEAR_MS;
287
302
  }
288
- /** Pie/sunburst đặt legend + số giữa theo px của containerWidth → phải dựng lại. */
303
+ /**
304
+ * Sunburst, and a pie WITH its built-in legend, place things in px of
305
+ * containerWidth → must rebuild on resize. A legend-less pie centres its
306
+ * ring at 50%/50% and its total in a `left: 'center' / top: 'middle'`
307
+ * graphic group, so `resize()` alone re-centres it — no rebuild, no
308
+ * second appear animation (15/09, donut on sidebar toggle).
309
+ */
289
310
  needsLayoutRebuild() {
290
311
  const type = this.detectType();
291
- return type === 'pie' || type === 'sunburst';
312
+ if (type === 'sunburst')
313
+ return true;
314
+ return type === 'pie' && this.showPieLegend();
292
315
  }
293
316
  deferResize(ms) {
294
317
  if (this.deferTimer !== undefined)
@@ -341,10 +364,19 @@ class ChartComponent {
341
364
  if (!chart)
342
365
  return;
343
366
  chart.resize();
344
- if (mobile || this.needsLayoutRebuild())
367
+ // A rebuild forced by GEOMETRY draws the same data at a new size: no
368
+ // appear animation, or the panel visibly redraws (that was the "renders
369
+ // twice" of 15/09). Only a preset change (mobile) keeps the animation.
370
+ if (mobile)
345
371
  this.rebuildChart();
372
+ else if (this.needsLayoutRebuild())
373
+ this.rebuildChart(true);
346
374
  }
347
- rebuildChart() {
375
+ /**
376
+ * @param silent redraw for a new size only — same data, no appear animation,
377
+ * and the appear window is not re-armed.
378
+ */
379
+ rebuildChart(silent = false) {
348
380
  if (this.destroyed)
349
381
  return;
350
382
  this.isEmpty = this.checkEmpty();
@@ -352,7 +384,7 @@ class ChartComponent {
352
384
  this.liveChart?.clear();
353
385
  return;
354
386
  }
355
- const options = this.buildOptions();
387
+ const options = silent ? { ...this.buildOptions(), animation: false } : this.buildOptions();
356
388
  const chart = this.liveChart;
357
389
  if (!chart) {
358
390
  if (this.awaitingFirstInit) {
@@ -370,7 +402,8 @@ class ChartComponent {
370
402
  this.hasOptions = true;
371
403
  chart.clear();
372
404
  chart.setOption(options, true);
373
- this.markAppear();
405
+ if (!silent)
406
+ this.markAppear();
374
407
  }
375
408
  checkEmpty() {
376
409
  const type = this.detectType();
@@ -489,7 +522,7 @@ class ChartComponent {
489
522
  series: [
490
523
  {
491
524
  type: 'pie',
492
- radius: ['40%', '70%'],
525
+ radius: this.pieRadius(),
493
526
  center: layout.pieCenter,
494
527
  data,
495
528
  label: {
@@ -509,46 +542,62 @@ class ChartComponent {
509
542
  },
510
543
  },
511
544
  ],
512
- // Centre figure: positioned by x/y in pixels graphic left/top
513
- // percentages place the element's bounding-box EDGE, which shifted the
514
- // total right/down by half its own size (mis-centred, caption clipped).
545
+ // Centre figure. With the built-in legend the ring sits off-centre
546
+ // (layout.pieCenter in px of containerWidth), so the texts are placed
547
+ // by x/y in pixels graphic left/top PERCENTAGES place the element's
548
+ // bounding-box EDGE and mis-centred the total. Without the legend the
549
+ // ring is at 50%/50% and the pair goes in a group with the KEYWORDS
550
+ // left: 'center' / top: 'middle', which ECharts re-lays out on
551
+ // `resize()` — so a legend-less donut never needs a rebuild to stay
552
+ // centred (15/09).
515
553
  graphic: (() => {
516
- const cx = (this.containerWidth || 400) * (parseFloat(layout.pieCenter[0]) / 100);
517
- const ch = this.ref.nativeElement.clientHeight || 300;
518
- const cy = ch * (parseFloat(layout.pieCenter[1]) / 100);
519
554
  const centre = this.pieCentreAnchors();
520
- return [
521
- {
555
+ const font = this.resolvedFontFamily();
556
+ const totalText = {
557
+ type: 'text',
558
+ style: {
559
+ text: total.toString(),
560
+ fontSize: this.pieCenterValueSize(),
561
+ fontWeight: 600,
562
+ fontFamily: font,
563
+ fill: FxUtils.convertColorFromVariable('--text-primary'),
564
+ align: 'center',
565
+ verticalAlign: 'middle',
566
+ },
567
+ };
568
+ const captionText = this.pieCenterLabel()
569
+ ? {
522
570
  type: 'text',
523
- x: cx,
524
- y: cy + centre.total,
525
571
  style: {
526
- text: total.toString(),
527
- fontSize: this.pieCenterValueSize(),
528
- fontWeight: 600,
529
- fontFamily: this.resolvedFontFamily(),
530
- fill: FxUtils.convertColorFromVariable('--text-primary'),
572
+ text: this.pieCenterLabel(),
573
+ fontSize: 11,
574
+ fontFamily: font,
575
+ fill: FxUtils.convertColorFromVariable('--text-secondary'),
531
576
  align: 'center',
532
577
  verticalAlign: 'middle',
533
578
  },
534
- },
535
- ...(this.pieCenterLabel()
536
- ? [
537
- {
538
- type: 'text',
539
- x: cx,
540
- y: cy + centre.caption,
541
- style: {
542
- text: this.pieCenterLabel(),
543
- fontSize: 11,
544
- fontFamily: this.resolvedFontFamily(),
545
- fill: FxUtils.convertColorFromVariable('--text-secondary'),
546
- align: 'center',
547
- verticalAlign: 'middle',
548
- },
549
- },
550
- ]
551
- : []),
579
+ }
580
+ : undefined;
581
+ if (!this.showPieLegend()) {
582
+ return [
583
+ {
584
+ type: 'group',
585
+ left: 'center',
586
+ top: 'middle',
587
+ silent: true,
588
+ children: [
589
+ { ...totalText, x: 0, y: centre.total },
590
+ ...(captionText ? [{ ...captionText, x: 0, y: centre.caption }] : []),
591
+ ],
592
+ },
593
+ ];
594
+ }
595
+ const cx = (this.containerWidth || 400) * (parseFloat(layout.pieCenter[0]) / 100);
596
+ const ch = this.ref.nativeElement.clientHeight || 300;
597
+ const cy = ch * (parseFloat(layout.pieCenter[1]) / 100);
598
+ return [
599
+ { ...totalText, x: cx, y: cy + centre.total },
600
+ ...(captionText ? [{ ...captionText, x: cx, y: cy + centre.caption }] : []),
552
601
  ];
553
602
  })(),
554
603
  };
@@ -858,12 +907,12 @@ class ChartComponent {
858
907
  });
859
908
  }
860
909
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ChartComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
861
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: ChartComponent, isStandalone: true, selector: "fx-ui-chart", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, pieLegendAlign: { classPropertyName: "pieLegendAlign", publicName: "pieLegendAlign", isSignal: true, isRequired: false, transformFunction: null }, pieLegendPosition: { classPropertyName: "pieLegendPosition", publicName: "pieLegendPosition", isSignal: true, isRequired: false, transformFunction: null }, showPieLabel: { classPropertyName: "showPieLabel", publicName: "showPieLabel", isSignal: true, isRequired: false, transformFunction: null }, showPieLegend: { classPropertyName: "showPieLegend", publicName: "showPieLegend", isSignal: true, isRequired: false, transformFunction: null }, pieCenterLabel: { classPropertyName: "pieCenterLabel", publicName: "pieCenterLabel", isSignal: true, isRequired: false, transformFunction: null }, pieCenterValueSize: { classPropertyName: "pieCenterValueSize", publicName: "pieCenterValueSize", isSignal: true, isRequired: false, transformFunction: null }, mobileWidth: { classPropertyName: "mobileWidth", publicName: "mobileWidth", isSignal: true, isRequired: false, transformFunction: null }, labelFontFamily: { classPropertyName: "labelFontFamily", publicName: "labelFontFamily", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, showPointLabels: { classPropertyName: "showPointLabels", publicName: "showPointLabels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartClick: "chartClick", chartInit: "chartInit" }, host: { listeners: { "window:theme-changed": "onThemeChange()" } }, providers: [provideEchartsCore({ echarts: () => import('echarts') })], usesOnChanges: true, ngImport: i0, template: "<div class=\"chart-wrapper\" [style.height]=\"height()\">\n @if (isEmpty) {\n <div class=\"chart-empty\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"chart-empty-icon\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z\" />\n </svg>\n <span class=\"chart-empty-text\">{{ emptyText() }}</span>\n </div>\n } @else if (hasOptions) {\n <div\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"false\"\n [loading]=\"loading()\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n class=\"fx-chart\"\n [style.height]=\"height()\"\n ></div>\n } @else {\n <!-- Until echarts is loaded + initialised (or the element scrolls into view)\n the panel keeps the chart's footprint with a quiet pulsing sketch\n instead of an empty box (anh T\u00FA 04/09: \"the page is too blank\"). -->\n <div class=\"chart-placeholder\" aria-hidden=\"true\">\n @for (h of placeholderBars; track $index) {\n <span class=\"chart-placeholder__bar\" [style.height.%]=\"h\"></span>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.chart-wrapper{position:relative;width:100%;height:100%}.chart-container{width:100%;height:100%}.chart-loader{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--bg-primary-hover)/.6);font-weight:500;font-size:1.1rem;z-index:2;border-radius:4px}.chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:12px;color:rgba(var(--text-secondary)/1)}.chart-empty-icon{width:48px;height:48px;opacity:.4}.chart-empty-text{font-size:14px;font-weight:500}.chart-placeholder{position:absolute;inset:0;display:flex;align-items:flex-end;gap:6px;padding:12px 8px 22px;animation:chart-placeholder-pulse 1.6s ease-in-out infinite}.chart-placeholder__bar{flex:1;border-radius:3px 3px 0 0;background:rgb(var(--og-track))}@keyframes chart-placeholder-pulse{0%,to{opacity:1}50%{opacity:.45}}@media(prefers-reduced-motion:reduce){.chart-placeholder{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
910
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: ChartComponent, isStandalone: true, selector: "fx-ui-chart", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, pieLegendAlign: { classPropertyName: "pieLegendAlign", publicName: "pieLegendAlign", isSignal: true, isRequired: false, transformFunction: null }, pieLegendPosition: { classPropertyName: "pieLegendPosition", publicName: "pieLegendPosition", isSignal: true, isRequired: false, transformFunction: null }, showPieLabel: { classPropertyName: "showPieLabel", publicName: "showPieLabel", isSignal: true, isRequired: false, transformFunction: null }, showPieLegend: { classPropertyName: "showPieLegend", publicName: "showPieLegend", isSignal: true, isRequired: false, transformFunction: null }, pieCenterLabel: { classPropertyName: "pieCenterLabel", publicName: "pieCenterLabel", isSignal: true, isRequired: false, transformFunction: null }, pieCenterValueSize: { classPropertyName: "pieCenterValueSize", publicName: "pieCenterValueSize", isSignal: true, isRequired: false, transformFunction: null }, pieRadius: { classPropertyName: "pieRadius", publicName: "pieRadius", isSignal: true, isRequired: false, transformFunction: null }, mobileWidth: { classPropertyName: "mobileWidth", publicName: "mobileWidth", isSignal: true, isRequired: false, transformFunction: null }, labelFontFamily: { classPropertyName: "labelFontFamily", publicName: "labelFontFamily", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, showPointLabels: { classPropertyName: "showPointLabels", publicName: "showPointLabels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chartClick: "chartClick", chartInit: "chartInit" }, host: { listeners: { "window:theme-changed": "onThemeChange()" } }, providers: [provideEchartsCore({ echarts: () => import('echarts') })], usesOnChanges: true, ngImport: i0, template: "<div class=\"chart-wrapper\" [style.height]=\"height()\">\n @if (isEmpty) {\n <div class=\"chart-empty\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"chart-empty-icon\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z\" />\n </svg>\n <span class=\"chart-empty-text\">{{ emptyText() }}</span>\n </div>\n } @else if (hasOptions) {\n <div\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"false\"\n [loading]=\"loading()\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n class=\"fx-chart\"\n [style.height]=\"height()\"\n ></div>\n } @else {\n <!-- Until echarts is loaded + initialised (or the element scrolls into view)\n the panel keeps the chart's footprint with a quiet pulsing sketch\n instead of an empty box (anh T\u00FA 04/09: \"the page is too blank\"). -->\n <div class=\"chart-placeholder\" aria-hidden=\"true\">\n @for (h of placeholderBars; track $index) {\n <span class=\"chart-placeholder__bar\" [style.height.%]=\"h\"></span>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.chart-wrapper{position:relative;width:100%;height:100%}.chart-container{width:100%;height:100%}.chart-loader{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--bg-primary-hover)/.6);font-weight:500;font-size:1.1rem;z-index:2;border-radius:4px}.chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:12px;color:rgba(var(--text-secondary)/1)}.chart-empty-icon{width:48px;height:48px;opacity:.4}.chart-empty-text{font-size:14px;font-weight:500}.chart-placeholder{position:absolute;inset:0;display:flex;align-items:flex-end;gap:6px;padding:12px 8px 22px;animation:chart-placeholder-pulse 1.6s ease-in-out infinite}.chart-placeholder__bar{flex:1;border-radius:3px 3px 0 0;background:rgb(var(--og-track))}@keyframes chart-placeholder-pulse{0%,to{opacity:1}50%{opacity:.45}}@media(prefers-reduced-motion:reduce){.chart-placeholder{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
862
911
  }
863
912
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ChartComponent, decorators: [{
864
913
  type: Component,
865
914
  args: [{ selector: 'fx-ui-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, InputComponent], providers: [provideEchartsCore({ echarts: () => import('echarts') })], template: "<div class=\"chart-wrapper\" [style.height]=\"height()\">\n @if (isEmpty) {\n <div class=\"chart-empty\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"chart-empty-icon\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z\" />\n </svg>\n <span class=\"chart-empty-text\">{{ emptyText() }}</span>\n </div>\n } @else if (hasOptions) {\n <div\n echarts\n [options]=\"chartOptions\"\n [autoResize]=\"false\"\n [loading]=\"loading()\"\n (chartInit)=\"onChartInit($event)\"\n (chartClick)=\"onChartClick($event)\"\n class=\"fx-chart\"\n [style.height]=\"height()\"\n ></div>\n } @else {\n <!-- Until echarts is loaded + initialised (or the element scrolls into view)\n the panel keeps the chart's footprint with a quiet pulsing sketch\n instead of an empty box (anh T\u00FA 04/09: \"the page is too blank\"). -->\n <div class=\"chart-placeholder\" aria-hidden=\"true\">\n @for (h of placeholderBars; track $index) {\n <span class=\"chart-placeholder__bar\" [style.height.%]=\"h\"></span>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.chart-wrapper{position:relative;width:100%;height:100%}.chart-container{width:100%;height:100%}.chart-loader{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--bg-primary-hover)/.6);font-weight:500;font-size:1.1rem;z-index:2;border-radius:4px}.chart-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:12px;color:rgba(var(--text-secondary)/1)}.chart-empty-icon{width:48px;height:48px;opacity:.4}.chart-empty-text{font-size:14px;font-weight:500}.chart-placeholder{position:absolute;inset:0;display:flex;align-items:flex-end;gap:6px;padding:12px 8px 22px;animation:chart-placeholder-pulse 1.6s ease-in-out infinite}.chart-placeholder__bar{flex:1;border-radius:3px 3px 0 0;background:rgb(var(--og-track))}@keyframes chart-placeholder-pulse{0%,to{opacity:1}50%{opacity:.45}}@media(prefers-reduced-motion:reduce){.chart-placeholder{animation:none}}\n"] }]
866
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], pieLegendAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieLegendAlign", required: false }] }], pieLegendPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieLegendPosition", required: false }] }], showPieLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPieLabel", required: false }] }], showPieLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPieLegend", required: false }] }], pieCenterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieCenterLabel", required: false }] }], pieCenterValueSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieCenterValueSize", required: false }] }], mobileWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileWidth", required: false }] }], labelFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelFontFamily", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], showPointLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPointLabels", required: false }] }], chartClick: [{ type: i0.Output, args: ["chartClick"] }], chartInit: [{ type: i0.Output, args: ["chartInit"] }], onThemeChange: [{
915
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], pieLegendAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieLegendAlign", required: false }] }], pieLegendPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieLegendPosition", required: false }] }], showPieLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPieLabel", required: false }] }], showPieLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPieLegend", required: false }] }], pieCenterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieCenterLabel", required: false }] }], pieCenterValueSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieCenterValueSize", required: false }] }], pieRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieRadius", required: false }] }], mobileWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileWidth", required: false }] }], labelFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelFontFamily", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], showPointLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPointLabels", required: false }] }], chartClick: [{ type: i0.Output, args: ["chartClick"] }], chartInit: [{ type: i0.Output, args: ["chartInit"] }], onThemeChange: [{
867
916
  type: HostListener,
868
917
  args: ['window:theme-changed']
869
918
  }] } });