@aquera/nile-visualization 2.9.5 → 2.9.7
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/dist/src/nile-chart/nile-chart-config.d.ts +2 -0
- package/dist/src/nile-chart/nile-chart-skeleton.d.ts +2 -0
- package/dist/src/nile-chart/nile-chart-skeleton.js +188 -0
- package/dist/src/nile-chart/nile-chart.css.js +399 -36
- package/dist/src/nile-chart/nile-chart.js +3 -16
- package/dist/src/nile-filter-chart/nile-filter-chart.css.js +11 -18
- package/dist/src/nile-filter-chart/nile-filter-chart.d.ts +5 -0
- package/dist/src/nile-filter-chart/nile-filter-chart.js +28 -0
- package/dist/src/nile-filter-chart/utils/prompt.js +120 -44
- package/dist/src/nile-filter-chart/utils/types.d.ts +4 -0
- package/dist/src/nile-kpi-chart/nile-kpi-chart.css.js +310 -17
- package/dist/src/nile-kpi-chart/nile-kpi-chart.d.ts +4 -2
- package/dist/src/nile-kpi-chart/nile-kpi-chart.js +145 -26
- package/package.json +1 -1
|
@@ -421,6 +421,13 @@ export const styles = css `
|
|
|
421
421
|
overflow-y: auto;
|
|
422
422
|
-webkit-overflow-scrolling: touch;
|
|
423
423
|
contain: none;
|
|
424
|
+
display: flex;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
:host([fit]) .nile-chart-inner--kpi > nile-kpi-chart {
|
|
428
|
+
flex: 1 1 auto;
|
|
429
|
+
min-height: 0;
|
|
430
|
+
height: 100%;
|
|
424
431
|
}
|
|
425
432
|
|
|
426
433
|
.nile-chart-inner--filter {
|
|
@@ -459,19 +466,36 @@ export const styles = css `
|
|
|
459
466
|
pointer-events: none;
|
|
460
467
|
}
|
|
461
468
|
|
|
469
|
+
/* When loading, the card becomes a flex column that fills the host so the
|
|
470
|
+
skeleton can shrink with the container instead of forcing a fixed size. */
|
|
471
|
+
.nile-chart-card--loading {
|
|
472
|
+
display: flex;
|
|
473
|
+
flex-direction: column;
|
|
474
|
+
height: 100%;
|
|
475
|
+
}
|
|
476
|
+
.nile-chart-card--loading .nile-chart-wrapper {
|
|
477
|
+
flex: 1 1 auto;
|
|
478
|
+
min-height: 0;
|
|
479
|
+
}
|
|
480
|
+
.nile-chart-card--loading .nile-chart-inner {
|
|
481
|
+
height: 100%;
|
|
482
|
+
}
|
|
483
|
+
|
|
462
484
|
.nile-chart-skeleton {
|
|
463
485
|
display: flex;
|
|
464
486
|
flex-direction: column;
|
|
465
487
|
gap: 0;
|
|
466
488
|
padding: var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
467
|
-
|
|
489
|
+
height: 100%;
|
|
490
|
+
box-sizing: border-box;
|
|
468
491
|
}
|
|
469
492
|
|
|
470
493
|
.nile-chart-skeleton-body {
|
|
471
494
|
display: flex;
|
|
472
495
|
flex-direction: column;
|
|
473
496
|
justify-content: space-around;
|
|
474
|
-
flex: 1;
|
|
497
|
+
flex: 1 1 auto;
|
|
498
|
+
min-height: 0;
|
|
475
499
|
gap: var(--nile-spacing-14px, var(--ng-spacing-lg));
|
|
476
500
|
padding-left: 44px;
|
|
477
501
|
position: relative;
|
|
@@ -484,8 +508,8 @@ export const styles = css `
|
|
|
484
508
|
left: 34px;
|
|
485
509
|
top: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
486
510
|
bottom: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
487
|
-
width:
|
|
488
|
-
border-radius:
|
|
511
|
+
width: 4px;
|
|
512
|
+
border-radius: 2px;
|
|
489
513
|
background: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
490
514
|
}
|
|
491
515
|
|
|
@@ -493,59 +517,398 @@ export const styles = css `
|
|
|
493
517
|
display: flex;
|
|
494
518
|
align-items: center;
|
|
495
519
|
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
496
|
-
|
|
520
|
+
flex: 1 1 var(--nile-spacing-3xl, var(--ng-spacing-3xl));
|
|
521
|
+
min-height: 0;
|
|
522
|
+
max-height: var(--nile-spacing-3xl, var(--ng-spacing-3xl));
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.nile-chart-skeleton-row .nile-chart-skeleton-ylabel-sk { flex-shrink: 0; }
|
|
526
|
+
/* Horizontal bar — uses <nile-skeleton-loader>. The host takes flex-basis
|
|
527
|
+
w% (inline style); ::part(base) forces the inner wrapper to fill the
|
|
528
|
+
host so the shimmer rectangle spans the full w% of the row. */
|
|
529
|
+
.nile-chart-skeleton-bar-sk::part(base) {
|
|
530
|
+
width: 100%;
|
|
531
|
+
height: 100%;
|
|
497
532
|
}
|
|
533
|
+
.nile-chart-skeleton-row:nth-child(1) .nile-chart-skeleton-bar-rect { animation-delay: 0ms; }
|
|
534
|
+
.nile-chart-skeleton-row:nth-child(2) .nile-chart-skeleton-bar-rect { animation-delay: 100ms; }
|
|
535
|
+
.nile-chart-skeleton-row:nth-child(3) .nile-chart-skeleton-bar-rect { animation-delay: 200ms; }
|
|
536
|
+
.nile-chart-skeleton-row:nth-child(4) .nile-chart-skeleton-bar-rect { animation-delay: 300ms; }
|
|
537
|
+
.nile-chart-skeleton-row:nth-child(5) .nile-chart-skeleton-bar-rect { animation-delay: 400ms; }
|
|
498
538
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
539
|
+
/* Horizontal x-axis labels row */
|
|
540
|
+
.nile-chart-skeleton-xaxis-row {
|
|
541
|
+
display: flex;
|
|
542
|
+
justify-content: space-around;
|
|
543
|
+
padding-left: 44px;
|
|
544
|
+
margin-top: var(--nile-spacing-14px, var(--ng-spacing-lg));
|
|
503
545
|
flex-shrink: 0;
|
|
546
|
+
min-width: 0;
|
|
547
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
548
|
+
}
|
|
549
|
+
.nile-chart-skeleton-xaxis-row nile-skeleton-loader { flex-shrink: 1; min-width: 0; }
|
|
550
|
+
|
|
551
|
+
/* Compact paddings + y-axis offset for narrow widths so the skeleton
|
|
552
|
+
doesn't overflow when the chart is shrunk. */
|
|
553
|
+
@container (max-width: 400px) {
|
|
554
|
+
.nile-chart-skeleton {
|
|
555
|
+
padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-2xl, var(--ng-spacing-2xl)) var(--nile-spacing-lg, var(--ng-spacing-lg));
|
|
556
|
+
}
|
|
557
|
+
.nile-chart-skeleton-body { padding-left: 32px; }
|
|
558
|
+
.nile-chart-skeleton-body::before { left: 24px; }
|
|
559
|
+
.nile-chart-skeleton-xaxis-row { padding-left: 32px; }
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
@container (max-width: 280px) {
|
|
563
|
+
.nile-chart-skeleton {
|
|
564
|
+
padding: var(--nile-spacing-lg, var(--ng-spacing-lg)) var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
565
|
+
}
|
|
566
|
+
.nile-chart-skeleton-body { padding-left: 22px; }
|
|
567
|
+
.nile-chart-skeleton-body::before { left: 14px; }
|
|
568
|
+
.nile-chart-skeleton-xaxis-row { padding-left: 22px; }
|
|
569
|
+
.nile-chart-skeleton-ylabel { display: none; }
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
@keyframes nile-skeleton-blink {
|
|
573
|
+
0%, 100% { opacity: 0.5; }
|
|
574
|
+
50% { opacity: 1; }
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/* ── Variant: columns (vertical bars) — wraps nile-skeleton-loader ── */
|
|
578
|
+
.nile-chart-skeleton-columns {
|
|
579
|
+
display: flex;
|
|
580
|
+
align-items: flex-end;
|
|
581
|
+
justify-content: space-between;
|
|
582
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
583
|
+
flex: 1 1 auto;
|
|
584
|
+
min-height: 0;
|
|
585
|
+
padding-left: 28px;
|
|
586
|
+
position: relative;
|
|
587
|
+
}
|
|
588
|
+
.nile-chart-skeleton-columns::before,
|
|
589
|
+
.nile-chart-skeleton-columns::after {
|
|
590
|
+
content: '';
|
|
591
|
+
position: absolute;
|
|
504
592
|
background: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
505
|
-
|
|
593
|
+
border-radius: 1px;
|
|
506
594
|
}
|
|
595
|
+
.nile-chart-skeleton-columns::before { left: 18px; top: 0; bottom: 0; width: 2px; }
|
|
596
|
+
.nile-chart-skeleton-columns::after { left: 18px; right: 0; bottom: 0; height: 2px; }
|
|
597
|
+
.nile-chart-skeleton-col-cell {
|
|
598
|
+
flex: 1 1 0;
|
|
599
|
+
min-width: 0;
|
|
600
|
+
height: 60%;
|
|
601
|
+
display: flex;
|
|
602
|
+
align-items: stretch;
|
|
603
|
+
border-radius: var(--nile-radius-radius-sm, var(--ng-radius-xs)) var(--nile-radius-radius-sm, var(--ng-radius-xs)) 0 0;
|
|
604
|
+
overflow: hidden;
|
|
605
|
+
}
|
|
606
|
+
.nile-chart-skeleton-col-cell nile-skeleton-loader {
|
|
607
|
+
width: 100%;
|
|
608
|
+
height: 100%;
|
|
609
|
+
display: block;
|
|
610
|
+
}
|
|
611
|
+
/* Percentage heights don't pass through the loader's shadow DOM by default.
|
|
612
|
+
Use ::part() to push height: 100% all the way to the shimmer rectangle. */
|
|
613
|
+
.nile-chart-skeleton-col-cell nile-skeleton-loader::part(base),
|
|
614
|
+
.nile-chart-skeleton-col-cell nile-skeleton-loader::part(skeleton),
|
|
615
|
+
.nile-chart-skeleton-heatmap-cell nile-skeleton-loader::part(base),
|
|
616
|
+
.nile-chart-skeleton-heatmap-cell nile-skeleton-loader::part(skeleton) {
|
|
617
|
+
height: 100%;
|
|
618
|
+
width: 100%;
|
|
619
|
+
}
|
|
620
|
+
.nile-chart-skeleton-xaxis-row--columns { padding-left: 28px; }
|
|
507
621
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
622
|
+
/* ── Variant: line ── */
|
|
623
|
+
.nile-chart-skeleton-line {
|
|
624
|
+
flex: 1 1 auto;
|
|
625
|
+
min-height: 0;
|
|
626
|
+
padding-left: 28px;
|
|
627
|
+
position: relative;
|
|
628
|
+
}
|
|
629
|
+
.nile-chart-skeleton-line::before {
|
|
630
|
+
content: '';
|
|
631
|
+
position: absolute;
|
|
632
|
+
left: 18px; top: 0; bottom: 0;
|
|
633
|
+
width: 2px;
|
|
634
|
+
border-radius: 1px;
|
|
512
635
|
background: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
636
|
+
}
|
|
637
|
+
.nile-chart-skeleton-line svg { width: 100%; height: 100%; display: block; }
|
|
638
|
+
.nile-chart-skeleton-line-area {
|
|
639
|
+
fill: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
640
|
+
opacity: 0.35;
|
|
641
|
+
animation: nile-skeleton-blink 1.6s ease-in-out infinite;
|
|
642
|
+
}
|
|
643
|
+
.nile-chart-skeleton-line-stroke {
|
|
644
|
+
fill: none;
|
|
645
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
646
|
+
stroke-width: 1.6;
|
|
647
|
+
stroke-linecap: round;
|
|
648
|
+
stroke-linejoin: round;
|
|
513
649
|
animation: nile-skeleton-blink 1.2s ease-in-out infinite;
|
|
514
650
|
}
|
|
515
651
|
|
|
516
|
-
/*
|
|
517
|
-
.nile-chart-skeleton-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
652
|
+
/* Trendline: faint guide line + actuals stroke + dashed forecast + split rule */
|
|
653
|
+
.nile-chart-skeleton-trend-line {
|
|
654
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
655
|
+
stroke-width: 0.8;
|
|
656
|
+
opacity: 0.45;
|
|
657
|
+
}
|
|
658
|
+
.nile-chart-skeleton-trend-forecast {
|
|
659
|
+
fill: none;
|
|
660
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
661
|
+
stroke-width: 1.6;
|
|
662
|
+
stroke-linecap: round;
|
|
663
|
+
stroke-dasharray: 3 3;
|
|
664
|
+
animation: nile-skeleton-blink 1.2s ease-in-out infinite;
|
|
665
|
+
animation-delay: 200ms;
|
|
666
|
+
}
|
|
667
|
+
.nile-chart-skeleton-trend-divider {
|
|
668
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
669
|
+
stroke-width: 0.5;
|
|
670
|
+
stroke-dasharray: 1 2;
|
|
671
|
+
opacity: 0.5;
|
|
672
|
+
}
|
|
522
673
|
|
|
523
|
-
/*
|
|
524
|
-
.nile-chart-skeleton-
|
|
674
|
+
/* Anomaly: halo pulses around outlier dots, dot itself blinks */
|
|
675
|
+
.nile-chart-skeleton-anomaly-dot {
|
|
676
|
+
fill: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
677
|
+
animation: nile-skeleton-blink 1.1s ease-in-out infinite;
|
|
678
|
+
}
|
|
679
|
+
.nile-chart-skeleton-anomaly-halo {
|
|
680
|
+
fill: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
681
|
+
opacity: 0.25;
|
|
682
|
+
transform-origin: center;
|
|
683
|
+
transform-box: fill-box;
|
|
684
|
+
animation: nile-skeleton-anomaly-pulse 1.8s ease-in-out infinite;
|
|
685
|
+
}
|
|
686
|
+
.nile-chart-skeleton-anomaly-halo:nth-of-type(1) { animation-delay: 0ms; }
|
|
687
|
+
.nile-chart-skeleton-anomaly-halo:nth-of-type(2) { animation-delay: 300ms; }
|
|
688
|
+
.nile-chart-skeleton-anomaly-halo:nth-of-type(3) { animation-delay: 600ms; }
|
|
689
|
+
@keyframes nile-skeleton-anomaly-pulse {
|
|
690
|
+
0%, 100% { opacity: 0.15; transform: scale(0.7); }
|
|
691
|
+
50% { opacity: 0.35; transform: scale(1.2); }
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/* ── Variant: pie / donut ── */
|
|
695
|
+
.nile-chart-skeleton-pie-wrap {
|
|
525
696
|
display: flex;
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
697
|
+
align-items: center;
|
|
698
|
+
justify-content: center;
|
|
699
|
+
gap: var(--nile-spacing-3xl, var(--ng-spacing-3xl));
|
|
700
|
+
flex: 1 1 auto;
|
|
701
|
+
min-height: 0;
|
|
529
702
|
}
|
|
703
|
+
.nile-chart-skeleton-pie {
|
|
704
|
+
width: min(60%, 220px);
|
|
705
|
+
aspect-ratio: 1;
|
|
706
|
+
border-radius: 50%;
|
|
707
|
+
background: conic-gradient(
|
|
708
|
+
var(--nile-colors-neutral-400, var(--ng-colors-border-secondary)) 0 25%,
|
|
709
|
+
var(--nile-colors-neutral-300, #e5e7eb) 25% 55%,
|
|
710
|
+
var(--nile-colors-neutral-400, var(--ng-colors-border-secondary)) 55% 80%,
|
|
711
|
+
var(--nile-colors-neutral-300, #e5e7eb) 80% 100%
|
|
712
|
+
);
|
|
713
|
+
mask: radial-gradient(circle, transparent 28%, black 30%);
|
|
714
|
+
-webkit-mask: radial-gradient(circle, transparent 28%, black 30%);
|
|
715
|
+
animation: nile-skeleton-spin 6s linear infinite, nile-skeleton-blink 1.6s ease-in-out infinite;
|
|
716
|
+
}
|
|
717
|
+
.nile-chart-skeleton-legend {
|
|
718
|
+
display: flex;
|
|
719
|
+
flex-direction: column;
|
|
720
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
721
|
+
flex-shrink: 0;
|
|
722
|
+
}
|
|
723
|
+
.nile-chart-skeleton-legend-row {
|
|
724
|
+
display: flex;
|
|
725
|
+
align-items: center;
|
|
726
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
727
|
+
}
|
|
728
|
+
@container (max-width: 320px) {
|
|
729
|
+
.nile-chart-skeleton-legend { display: none; }
|
|
730
|
+
}
|
|
731
|
+
@keyframes nile-skeleton-spin { to { transform: rotate(360deg); } }
|
|
530
732
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
733
|
+
/* ── Variant: scatter ── */
|
|
734
|
+
.nile-chart-skeleton-scatter {
|
|
735
|
+
flex: 1 1 auto;
|
|
736
|
+
min-height: 0;
|
|
737
|
+
position: relative;
|
|
738
|
+
padding-left: 28px;
|
|
739
|
+
}
|
|
740
|
+
.nile-chart-skeleton-scatter::before,
|
|
741
|
+
.nile-chart-skeleton-scatter::after {
|
|
742
|
+
content: '';
|
|
743
|
+
position: absolute;
|
|
535
744
|
background: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
745
|
+
border-radius: 1px;
|
|
746
|
+
}
|
|
747
|
+
.nile-chart-skeleton-scatter::before { left: 18px; top: 0; bottom: 0; width: 2px; }
|
|
748
|
+
.nile-chart-skeleton-scatter::after { left: 18px; right: 0; bottom: 0; height: 2px; }
|
|
749
|
+
.nile-chart-skeleton-dot-pos {
|
|
750
|
+
position: absolute;
|
|
751
|
+
transform: translate(-50%, -50%);
|
|
752
|
+
display: inline-flex;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/* ── Variant: heatmap ── */
|
|
756
|
+
.nile-chart-skeleton-heatmap {
|
|
757
|
+
display: flex;
|
|
758
|
+
flex-direction: column;
|
|
759
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
760
|
+
flex: 1 1 auto;
|
|
761
|
+
min-height: 0;
|
|
762
|
+
}
|
|
763
|
+
.nile-chart-skeleton-heatmap-row {
|
|
764
|
+
display: flex;
|
|
765
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
766
|
+
flex: 1 1 0;
|
|
767
|
+
min-height: 0;
|
|
768
|
+
}
|
|
769
|
+
.nile-chart-skeleton-heatmap-cell {
|
|
770
|
+
flex: 1 1 0;
|
|
771
|
+
min-width: 0;
|
|
772
|
+
display: flex;
|
|
773
|
+
}
|
|
774
|
+
.nile-chart-skeleton-heatmap-cell nile-skeleton-loader { width: 100%; height: 100%; }
|
|
775
|
+
|
|
776
|
+
/* ── Variant: radar ── */
|
|
777
|
+
.nile-chart-skeleton-radar-wrap {
|
|
778
|
+
display: flex;
|
|
779
|
+
align-items: center;
|
|
780
|
+
justify-content: center;
|
|
781
|
+
flex: 1 1 auto;
|
|
782
|
+
min-height: 0;
|
|
783
|
+
}
|
|
784
|
+
.nile-chart-skeleton-radar-svg {
|
|
785
|
+
width: min(78%, 260px);
|
|
786
|
+
aspect-ratio: 1;
|
|
787
|
+
display: block;
|
|
788
|
+
}
|
|
789
|
+
.nile-chart-skeleton-radar-grid {
|
|
790
|
+
fill: none;
|
|
791
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
792
|
+
stroke-width: 0.8;
|
|
793
|
+
stroke-linejoin: round;
|
|
794
|
+
opacity: 0.7;
|
|
795
|
+
}
|
|
796
|
+
.nile-chart-skeleton-radar-spoke {
|
|
797
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
798
|
+
stroke-width: 0.6;
|
|
799
|
+
opacity: 0.5;
|
|
800
|
+
}
|
|
801
|
+
.nile-chart-skeleton-radar-data {
|
|
802
|
+
fill: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
803
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
804
|
+
stroke-width: 1.2;
|
|
805
|
+
stroke-linejoin: round;
|
|
806
|
+
opacity: 0.45;
|
|
807
|
+
animation: nile-skeleton-blink 1.4s ease-in-out infinite;
|
|
808
|
+
transform-origin: 50px 50px;
|
|
809
|
+
transform-box: fill-box;
|
|
810
|
+
}
|
|
811
|
+
.nile-chart-skeleton-radar-dot {
|
|
812
|
+
fill: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
536
813
|
animation: nile-skeleton-blink 1.2s ease-in-out infinite;
|
|
537
|
-
animation-delay: var(--d, 0ms);
|
|
538
814
|
}
|
|
815
|
+
.nile-chart-skeleton-radar-dot:nth-child(5) { animation-delay: 0ms; }
|
|
816
|
+
.nile-chart-skeleton-radar-dot:nth-child(6) { animation-delay: 120ms; }
|
|
817
|
+
.nile-chart-skeleton-radar-dot:nth-child(7) { animation-delay: 240ms; }
|
|
818
|
+
.nile-chart-skeleton-radar-dot:nth-child(8) { animation-delay: 360ms; }
|
|
819
|
+
.nile-chart-skeleton-radar-dot:nth-child(9) { animation-delay: 480ms; }
|
|
539
820
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
821
|
+
/* ── Variant: timeline ── */
|
|
822
|
+
.nile-chart-skeleton-timeline {
|
|
823
|
+
display: flex;
|
|
824
|
+
flex-direction: column;
|
|
825
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
826
|
+
flex: 1 1 auto;
|
|
827
|
+
min-height: 0;
|
|
828
|
+
justify-content: space-around;
|
|
829
|
+
}
|
|
830
|
+
.nile-chart-skeleton-tl-row {
|
|
831
|
+
position: relative;
|
|
832
|
+
height: 12px;
|
|
833
|
+
}
|
|
834
|
+
.nile-chart-skeleton-tl-bar-pos {
|
|
835
|
+
position: absolute;
|
|
836
|
+
top: 0; bottom: 0;
|
|
837
|
+
display: inline-flex;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* ── Variant: kpi ── */
|
|
841
|
+
.nile-chart-skeleton-kpi {
|
|
842
|
+
display: flex;
|
|
843
|
+
flex-direction: column;
|
|
844
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
845
|
+
flex: 1 1 auto;
|
|
846
|
+
min-height: 0;
|
|
847
|
+
justify-content: center;
|
|
848
|
+
}
|
|
849
|
+
.nile-chart-skeleton-kpi-spark {
|
|
850
|
+
width: 100%;
|
|
851
|
+
height: 40px;
|
|
852
|
+
margin-top: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
853
|
+
}
|
|
854
|
+
.nile-chart-skeleton-kpi-spark path {
|
|
855
|
+
fill: none;
|
|
856
|
+
stroke: var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
857
|
+
stroke-width: 1.6;
|
|
858
|
+
stroke-linecap: round;
|
|
859
|
+
stroke-linejoin: round;
|
|
860
|
+
animation: nile-skeleton-blink 1.2s ease-in-out infinite;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/* ── Variant: grid (table) ── */
|
|
864
|
+
.nile-chart-skeleton-grid {
|
|
865
|
+
display: flex;
|
|
866
|
+
flex-direction: column;
|
|
867
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
868
|
+
flex: 1 1 auto;
|
|
869
|
+
min-height: 0;
|
|
870
|
+
}
|
|
871
|
+
.nile-chart-skeleton-grid-head,
|
|
872
|
+
.nile-chart-skeleton-grid-row {
|
|
873
|
+
display: flex;
|
|
874
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
875
|
+
align-items: center;
|
|
876
|
+
flex: 1 1 0;
|
|
877
|
+
min-height: 0;
|
|
878
|
+
max-height: 28px;
|
|
879
|
+
}
|
|
880
|
+
.nile-chart-skeleton-grid-head {
|
|
881
|
+
border-bottom: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
882
|
+
padding-bottom: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
883
|
+
}
|
|
884
|
+
.nile-chart-skeleton-grid-head nile-skeleton-loader,
|
|
885
|
+
.nile-chart-skeleton-grid-row nile-skeleton-loader {
|
|
886
|
+
flex: 1 1 0;
|
|
887
|
+
min-width: 0;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/* ── Variant: filter ── */
|
|
891
|
+
.nile-chart-skeleton-filter {
|
|
892
|
+
display: flex;
|
|
893
|
+
flex-direction: column;
|
|
894
|
+
gap: var(--nile-spacing-lg, var(--ng-spacing-lg));
|
|
895
|
+
flex: 1 1 auto;
|
|
896
|
+
min-height: 0;
|
|
897
|
+
justify-content: center;
|
|
898
|
+
}
|
|
899
|
+
.nile-chart-skeleton-filter-chips {
|
|
900
|
+
display: flex;
|
|
901
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
902
|
+
flex-wrap: wrap;
|
|
543
903
|
}
|
|
544
904
|
|
|
545
905
|
@media (prefers-reduced-motion: reduce) {
|
|
546
|
-
.nile-chart-skeleton-
|
|
547
|
-
.nile-chart-skeleton-
|
|
548
|
-
.nile-chart-skeleton-
|
|
906
|
+
.nile-chart-skeleton-line-area,
|
|
907
|
+
.nile-chart-skeleton-line-stroke,
|
|
908
|
+
.nile-chart-skeleton-pie,
|
|
909
|
+
.nile-chart-skeleton-radar-data,
|
|
910
|
+
.nile-chart-skeleton-radar-dot,
|
|
911
|
+
.nile-chart-skeleton-kpi-spark path {
|
|
549
912
|
animation: none;
|
|
550
913
|
opacity: 0.7;
|
|
551
914
|
}
|
|
@@ -4,6 +4,7 @@ import { html, nothing } from 'lit';
|
|
|
4
4
|
import NileElement from '../internal/nile-element.js';
|
|
5
5
|
import { styles, tooltipCss } from './nile-chart.css.js';
|
|
6
6
|
import { nileChartConfig } from './nile-chart-config-builder.js';
|
|
7
|
+
import { renderChartSkeleton } from './nile-chart-skeleton.js';
|
|
7
8
|
import { convertConfig } from '../internal/chart-adapters.js';
|
|
8
9
|
import { deepMerge } from '../internal/utils.js';
|
|
9
10
|
import { initNileChartExporting, getHighcharts } from '../internal/highcharts-provider.js';
|
|
@@ -1710,27 +1711,13 @@ let NileChart = class NileChart extends NileElement {
|
|
|
1710
1711
|
}
|
|
1711
1712
|
}
|
|
1712
1713
|
renderSkeleton() {
|
|
1713
|
-
return
|
|
1714
|
-
<div class="nile-chart-skeleton" aria-busy="true" aria-label="Loading chart">
|
|
1715
|
-
<div class="nile-chart-skeleton-body">
|
|
1716
|
-
${[78, 55, 91, 42, 68].map(w => html `
|
|
1717
|
-
<div class="nile-chart-skeleton-row">
|
|
1718
|
-
<div class="nile-chart-skeleton-ylabel"></div>
|
|
1719
|
-
<div class="nile-chart-skeleton-bar" style="--w: ${w}%"></div>
|
|
1720
|
-
</div>
|
|
1721
|
-
`)}
|
|
1722
|
-
</div>
|
|
1723
|
-
<div class="nile-chart-skeleton-xaxis-row">
|
|
1724
|
-
${[0, 1, 2, 3, 4].map(i => html `<div class="nile-chart-skeleton-xlabel" style="--d: ${i * 80}ms"></div>`)}
|
|
1725
|
-
</div>
|
|
1726
|
-
</div>
|
|
1727
|
-
`;
|
|
1714
|
+
return renderChartSkeleton(this.activeConfig?.type);
|
|
1728
1715
|
}
|
|
1729
1716
|
render() {
|
|
1730
1717
|
const isLoading = this.loading || (this.activeConfig?.loading ?? false);
|
|
1731
1718
|
const isGrid = this.activeConfig?.type === 'grid';
|
|
1732
1719
|
return html `
|
|
1733
|
-
<div class="nile-chart-card ${isGrid ? 'nile-chart-card--grid' : ''}" part="chart-card">
|
|
1720
|
+
<div class="nile-chart-card ${isGrid ? 'nile-chart-card--grid' : ''} ${isLoading ? 'nile-chart-card--loading' : ''}" part="chart-card">
|
|
1734
1721
|
${this.renderHeader()}
|
|
1735
1722
|
<div class="nile-chart-wrapper">
|
|
1736
1723
|
<div class="nile-chart-inner ${this.activeConfig?.type === 'kpi' ? 'nile-chart-inner--kpi' : ''} ${this.activeConfig?.type === 'filter' ? 'nile-chart-inner--filter' : ''}" part="chart-inner">
|
|
@@ -490,9 +490,10 @@ export const styles = css `
|
|
|
490
490
|
outline: none;
|
|
491
491
|
background: transparent;
|
|
492
492
|
border-radius: inherit;
|
|
493
|
-
padding: var(--nile-spacing-
|
|
493
|
+
padding: var(--nile-spacing-md, var(--ng-spacing-2)) var(--nile-spacing-xl, var(--ng-spacing-4));
|
|
494
494
|
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
495
|
-
font-size: var(--nile-font-size-
|
|
495
|
+
font-size: var(--nile-type-scale-4, var(--ng-font-size-text-md));
|
|
496
|
+
font-weight: 400;
|
|
496
497
|
color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
|
|
497
498
|
line-height: 1.4;
|
|
498
499
|
box-sizing: border-box;
|
|
@@ -605,18 +606,14 @@ export const styles = css `
|
|
|
605
606
|
color: transparent;
|
|
606
607
|
}
|
|
607
608
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
top: calc(100% + 6px);
|
|
617
|
-
left: 0;
|
|
618
|
-
right: 0;
|
|
619
|
-
z-index: 20;
|
|
609
|
+
.fc-prompt__dropdown {
|
|
610
|
+
flex: 1;
|
|
611
|
+
min-width: 0;
|
|
612
|
+
display: block;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.fc-prompt__dropdown::part(panel) {
|
|
616
|
+
display: flex;
|
|
620
617
|
flex-direction: column;
|
|
621
618
|
max-height: 280px;
|
|
622
619
|
overflow-y: auto;
|
|
@@ -628,10 +625,6 @@ export const styles = css `
|
|
|
628
625
|
padding: var(--nile-spacing-4px, var(--ng-spacing-1));
|
|
629
626
|
}
|
|
630
627
|
|
|
631
|
-
.fc-prompt__inner:focus-within .fc-prompt__suggestions {
|
|
632
|
-
display: flex;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
628
|
.fc-prompt__suggestion {
|
|
636
629
|
display: flex;
|
|
637
630
|
align-items: center;
|
|
@@ -18,6 +18,9 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
18
18
|
promptModes: Map<string, PromptMode>;
|
|
19
19
|
/** Highlighted suggestion index per prompt control id (-1 = none highlighted). */
|
|
20
20
|
promptActiveIndex: Map<string, number>;
|
|
21
|
+
/** Id of the prompt control whose input currently has focus (drives the
|
|
22
|
+
* nile-dropdown panel open state). null when no prompt is focused. */
|
|
23
|
+
promptFocusedId: string | null;
|
|
21
24
|
/** Active typewriter timers per prompt control id (so we can stop them). */
|
|
22
25
|
private _promptTimers;
|
|
23
26
|
/** Compiled filtrex predicates per prompt control id (strict-mode successes). */
|
|
@@ -33,6 +36,7 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
33
36
|
connectedCallback(): void;
|
|
34
37
|
disconnectedCallback(): void;
|
|
35
38
|
updated(changed: Map<string, unknown>): void;
|
|
39
|
+
private _syncPortalDropdowns;
|
|
36
40
|
setValue(id: string, value: unknown): void;
|
|
37
41
|
/**
|
|
38
42
|
* Update a prompt control's value. The value lands in `selectedValues`
|
|
@@ -55,6 +59,7 @@ export declare class NileFilterChart extends NileElement implements FilterChartH
|
|
|
55
59
|
*/
|
|
56
60
|
submitPrompt(ctrl: NormalizedFilterControl): void;
|
|
57
61
|
setPromptActiveIndex(id: string, idx: number): void;
|
|
62
|
+
setPromptFocused(id: string, focused: boolean): void;
|
|
58
63
|
private _validateOrClear;
|
|
59
64
|
private _clearPromptValidation;
|
|
60
65
|
private _syncPromptAnimations;
|
|
@@ -34,6 +34,9 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
34
34
|
this.promptModes = new Map();
|
|
35
35
|
/** Highlighted suggestion index per prompt control id (-1 = none highlighted). */
|
|
36
36
|
this.promptActiveIndex = new Map();
|
|
37
|
+
/** Id of the prompt control whose input currently has focus (drives the
|
|
38
|
+
* nile-dropdown panel open state). null when no prompt is focused. */
|
|
39
|
+
this.promptFocusedId = null;
|
|
37
40
|
/** Active typewriter timers per prompt control id (so we can stop them). */
|
|
38
41
|
this._promptTimers = new Map();
|
|
39
42
|
/** Compiled filtrex predicates per prompt control id (strict-mode successes). */
|
|
@@ -69,6 +72,20 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
69
72
|
this._initValues();
|
|
70
73
|
this._syncPromptAnimations();
|
|
71
74
|
}
|
|
75
|
+
// Keep portaled suggestion panels in sync with the latest panel content.
|
|
76
|
+
// nile-dropdown clones the panel once at open-time and never re-clones,
|
|
77
|
+
// so without this the suggestions appear frozen at the value they had
|
|
78
|
+
// when the dropdown first opened.
|
|
79
|
+
this._syncPortalDropdowns();
|
|
80
|
+
}
|
|
81
|
+
_syncPortalDropdowns() {
|
|
82
|
+
const dropdowns = this.shadowRoot?.querySelectorAll('nile-dropdown.fc-prompt__dropdown');
|
|
83
|
+
dropdowns?.forEach((dd) => {
|
|
84
|
+
const d = dd;
|
|
85
|
+
if (d.open && d.portal && d.portalManager?.clonedPanel) {
|
|
86
|
+
d.portalManager.updatePortalPanel?.();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
72
89
|
}
|
|
73
90
|
// ── FilterChartHost surface ─────────────────────────────────────────────────
|
|
74
91
|
setValue(id, value) {
|
|
@@ -127,6 +144,14 @@ let NileFilterChart = NileFilterChart_1 = class NileFilterChart extends NileElem
|
|
|
127
144
|
setPromptActiveIndex(id, idx) {
|
|
128
145
|
this.promptActiveIndex = new Map(this.promptActiveIndex).set(id, idx);
|
|
129
146
|
}
|
|
147
|
+
setPromptFocused(id, focused) {
|
|
148
|
+
if (focused) {
|
|
149
|
+
this.promptFocusedId = id;
|
|
150
|
+
}
|
|
151
|
+
else if (this.promptFocusedId === id) {
|
|
152
|
+
this.promptFocusedId = null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
130
155
|
_validateOrClear(ctrl, value, opts = {}) {
|
|
131
156
|
const isNql = this.promptModes.get(ctrl.id) === 'nql';
|
|
132
157
|
if (value.trim() === '') {
|
|
@@ -566,6 +591,9 @@ __decorate([
|
|
|
566
591
|
__decorate([
|
|
567
592
|
state()
|
|
568
593
|
], NileFilterChart.prototype, "promptActiveIndex", void 0);
|
|
594
|
+
__decorate([
|
|
595
|
+
state()
|
|
596
|
+
], NileFilterChart.prototype, "promptFocusedId", void 0);
|
|
569
597
|
NileFilterChart = NileFilterChart_1 = __decorate([
|
|
570
598
|
customElement('nile-filter-chart')
|
|
571
599
|
], NileFilterChart);
|