cats-charts 0.0.76 → 0.0.78
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/README.md +73 -0
- package/fesm2022/cats-charts.mjs +278 -28
- package/fesm2022/cats-charts.mjs.map +1 -1
- package/index.d.ts +113 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -637,3 +637,76 @@ Feel free to submit a pull request.
|
|
|
637
637
|
# 📄 License
|
|
638
638
|
|
|
639
639
|
MIT License
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
# Status Timeline
|
|
644
|
+
|
|
645
|
+
`StatusTimelineComponent` renders generic categorical intervals in chronological order. Segment
|
|
646
|
+
widths are proportional to duration, and dense datasets scroll horizontally without aggregation.
|
|
647
|
+
|
|
648
|
+
## Import and usage
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
import { StatusTimelineComponent, type StatusTimelineConfig } from 'cats-charts';
|
|
652
|
+
|
|
653
|
+
@Component({
|
|
654
|
+
standalone: true,
|
|
655
|
+
imports: [StatusTimelineComponent],
|
|
656
|
+
template: `
|
|
657
|
+
<lib-status-timeline
|
|
658
|
+
[config]="timelineConfig"
|
|
659
|
+
(chartEvent)="onTimelineEvent($event)"
|
|
660
|
+
/>
|
|
661
|
+
`,
|
|
662
|
+
})
|
|
663
|
+
export class ExampleComponent {
|
|
664
|
+
timelineConfig: StatusTimelineConfig = {
|
|
665
|
+
startLabel: 'Monday',
|
|
666
|
+
endLabel: 'Today',
|
|
667
|
+
statuses: [
|
|
668
|
+
{ value: 'ready', label: 'Ready', color: '#2f8f3a' },
|
|
669
|
+
{ value: 'deploying', label: 'Deploying', color: '#d0a020' },
|
|
670
|
+
{ value: 'blocked', label: 'Blocked', color: '#a43b35' },
|
|
671
|
+
],
|
|
672
|
+
data: [
|
|
673
|
+
{ start: '2026-08-24T00:00:00Z', end: '2026-08-25T00:00:00Z', status: 'ready' },
|
|
674
|
+
{
|
|
675
|
+
start: '2026-08-25T00:00:00Z',
|
|
676
|
+
end: '2026-08-25T06:00:00Z',
|
|
677
|
+
status: 'deploying',
|
|
678
|
+
label: 'Release deployment',
|
|
679
|
+
},
|
|
680
|
+
{ start: '2026-08-25T06:00:00Z', end: '2026-08-26T00:00:00Z', status: 'ready' },
|
|
681
|
+
],
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
## Configuration
|
|
687
|
+
|
|
688
|
+
| Option | Description |
|
|
689
|
+
| --- | --- |
|
|
690
|
+
| `data` | Dynamic intervals with `start`, `end`, `status`, and optional `label`/`metadata` |
|
|
691
|
+
| `statuses` | Text and optional color for each status value |
|
|
692
|
+
| `showLegend`, `showTooltip` | Toggle supporting UI (both default to `true`) |
|
|
693
|
+
| `legendPosition` | Places the legend at `top`, `bottom`, `left`, or `right` |
|
|
694
|
+
| `legendLayout` | Arranges legend items `horizontal` or `vertical` |
|
|
695
|
+
| `legendAlign` | Aligns the legend at `start`/`left`, `center`, `end`/`right`, or `space-between` |
|
|
696
|
+
| `legendLabelAlign` | Aligns text within vertical legend items to `left`, `center`, or `right` |
|
|
697
|
+
| `legendInteractive` | Enables clicking legend labels to dim/restore matching intervals; defaults to `true` |
|
|
698
|
+
| `legendDimmedOpacity` | Opacity used for inactive legend items and intervals; defaults to `0.3` |
|
|
699
|
+
| `legendScrollable` | Enables bounded legend overflow scrolling; defaults to `true` |
|
|
700
|
+
| `legendMaxWidth`, `legendMaxHeight` | Optional scroll viewport limits |
|
|
701
|
+
| `legendNote` | Optional explanatory text displayed beside the legend |
|
|
702
|
+
| `startLabel`, `endLabel` | Endpoint text; dates are derived when omitted |
|
|
703
|
+
| `showEndpointLabels` | Shows or hides the endpoint-label row; defaults to `true` |
|
|
704
|
+
| `endpointLabelsAlign` | Aligns endpoint labels at `start`/`left`, `center`, `end`/`right`, or `space-between` |
|
|
705
|
+
| `loading`, `loadingLabel`, `emptyLabel`, `error` | Timeline state presentation |
|
|
706
|
+
| `minSegmentWidth`, `segmentGap` | Dense-data and spacing controls in pixels |
|
|
707
|
+
| `dateFormatter`, `durationFormatter`, `tooltipFormatter` | Display customization hooks |
|
|
708
|
+
| `unknownStatus` | Fallback label/color for unconfigured status values |
|
|
709
|
+
| `ariaLabel` | Accessible name for the timeline |
|
|
710
|
+
|
|
711
|
+
The component emits `chartEvent` with `{ type: 'itemClick', item, index }`. Its appearance can be
|
|
712
|
+
themed with the `--status-timeline-*` CSS custom properties defined in the component stylesheet.
|
package/fesm2022/cats-charts.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Output, Input, Component, Injectable, PLATFORM_ID, ViewChild, Inject, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
|
2
|
+
import { EventEmitter, Output, Input, Component, Injectable, PLATFORM_ID, ViewChild, Inject, ChangeDetectionStrategy, HostListener, inject, APP_ID } from '@angular/core';
|
|
3
3
|
import * as echarts from 'echarts/core';
|
|
4
4
|
import { NgxEchartsDirective, provideEchartsCore } from 'ngx-echarts';
|
|
5
5
|
import { LineChart, BarChart as BarChart$1, PieChart as PieChart$1, CustomChart, SankeyChart as SankeyChart$1, HeatmapChart, ScatterChart } from 'echarts/charts';
|
|
@@ -1564,59 +1564,83 @@ class LinesChart {
|
|
|
1564
1564
|
type: 'category',
|
|
1565
1565
|
// boundaryGap: false,
|
|
1566
1566
|
data: this.config?.xAxisData,
|
|
1567
|
+
name: this.config?.xAxisName || '',
|
|
1568
|
+
nameLocation: 'center',
|
|
1569
|
+
...(this.config?.xAxis || {}),
|
|
1567
1570
|
axisLine: {
|
|
1568
1571
|
show: this.config?.showXAxisLine ?? true,
|
|
1572
|
+
...(this.config?.xAxis?.axisLine || {}),
|
|
1569
1573
|
lineStyle: {
|
|
1570
1574
|
color: '#C0C2C5',
|
|
1571
1575
|
width: 1,
|
|
1576
|
+
...(this.config?.xAxis?.axisLine?.lineStyle || {}),
|
|
1572
1577
|
},
|
|
1573
1578
|
},
|
|
1574
1579
|
axisTick: {
|
|
1575
1580
|
show: false,
|
|
1581
|
+
...(this.config?.xAxis?.axisTick || {}),
|
|
1576
1582
|
},
|
|
1577
1583
|
axisLabel: {
|
|
1578
1584
|
show: this.config?.showXAxisLabel ?? true,
|
|
1579
1585
|
color: '#434A51',
|
|
1580
1586
|
fontSize: 12,
|
|
1587
|
+
alignMinLabel: 'left',
|
|
1588
|
+
alignMaxLabel: 'right',
|
|
1589
|
+
...(this.config?.xAxis?.axisLabel || {}),
|
|
1581
1590
|
},
|
|
1582
|
-
name: this.config?.xAxisName || '',
|
|
1583
|
-
nameLocation: 'center',
|
|
1584
1591
|
nameTextStyle: {
|
|
1585
1592
|
color: '#434A51',
|
|
1586
1593
|
fontSize: 14,
|
|
1587
1594
|
fontWeight: 400,
|
|
1595
|
+
...(this.config?.xAxis?.nameTextStyle || {}),
|
|
1588
1596
|
},
|
|
1589
1597
|
splitLine: {
|
|
1590
1598
|
show: this.config?.showXAxisSplitLine ?? true,
|
|
1599
|
+
...(this.config?.xAxis?.splitLine || {}),
|
|
1591
1600
|
lineStyle: {
|
|
1592
1601
|
type: 'dashed',
|
|
1593
1602
|
color: '#C0C2C5',
|
|
1594
1603
|
width: 1,
|
|
1604
|
+
...(this.config?.xAxis?.splitLine?.lineStyle || {}),
|
|
1595
1605
|
},
|
|
1596
1606
|
},
|
|
1597
|
-
...(this.config?.xAxis || {}),
|
|
1598
1607
|
},
|
|
1599
1608
|
yAxis: [
|
|
1600
1609
|
{
|
|
1601
1610
|
show: !this.config?.isTrendChart,
|
|
1602
1611
|
type: 'value',
|
|
1603
1612
|
boundaryGap: this.config?.isTrendChart ? [0.2] : undefined,
|
|
1613
|
+
name: this.config?.yAxisName || '',
|
|
1614
|
+
nameLocation: 'center',
|
|
1615
|
+
...(this.config?.yAxis || {}),
|
|
1604
1616
|
axisLine: {
|
|
1605
1617
|
show: this.config?.showYAxisLine ?? true,
|
|
1618
|
+
...(this.config?.yAxis?.axisLine || {}),
|
|
1606
1619
|
lineStyle: {
|
|
1607
1620
|
color: '#C0C2C5',
|
|
1608
1621
|
width: 1,
|
|
1622
|
+
...(this.config?.yAxis?.axisLine?.lineStyle || {}),
|
|
1609
1623
|
},
|
|
1610
1624
|
},
|
|
1611
1625
|
axisTick: {
|
|
1612
1626
|
show: false,
|
|
1627
|
+
...(this.config?.yAxis?.axisTick || {}),
|
|
1613
1628
|
},
|
|
1614
|
-
name: this.config?.yAxisName || '',
|
|
1615
|
-
nameLocation: 'center',
|
|
1616
1629
|
nameTextStyle: {
|
|
1617
1630
|
color: '#434A51',
|
|
1618
1631
|
fontSize: 14,
|
|
1619
1632
|
fontWeight: 400,
|
|
1633
|
+
...(this.config?.yAxis?.nameTextStyle || {}),
|
|
1634
|
+
},
|
|
1635
|
+
splitLine: {
|
|
1636
|
+
show: this.config?.showYAxisSplitLine ?? true,
|
|
1637
|
+
...(this.config?.yAxis?.splitLine || {}),
|
|
1638
|
+
lineStyle: {
|
|
1639
|
+
type: 'dashed',
|
|
1640
|
+
color: '#C0C2C5',
|
|
1641
|
+
width: 1,
|
|
1642
|
+
...(this.config?.yAxis?.splitLine?.lineStyle || {}),
|
|
1643
|
+
},
|
|
1620
1644
|
},
|
|
1621
1645
|
axisLabel: {
|
|
1622
1646
|
show: this.config?.showYAxisLabel ?? true,
|
|
@@ -1653,16 +1677,8 @@ class LinesChart {
|
|
|
1653
1677
|
}
|
|
1654
1678
|
return value;
|
|
1655
1679
|
},
|
|
1680
|
+
...(this.config?.yAxis?.axisLabel || {}),
|
|
1656
1681
|
},
|
|
1657
|
-
splitLine: {
|
|
1658
|
-
show: this.config?.showYAxisSplitLine ?? true,
|
|
1659
|
-
lineStyle: {
|
|
1660
|
-
type: 'dashed',
|
|
1661
|
-
color: '#C0C2C5',
|
|
1662
|
-
width: 1,
|
|
1663
|
-
},
|
|
1664
|
-
},
|
|
1665
|
-
...(this.config?.yAxis || {}),
|
|
1666
1682
|
},
|
|
1667
1683
|
...(this.config?.secondaryYAxis
|
|
1668
1684
|
? [
|
|
@@ -1670,15 +1686,21 @@ class LinesChart {
|
|
|
1670
1686
|
show: !this.config?.isTrendChart,
|
|
1671
1687
|
type: 'value',
|
|
1672
1688
|
boundaryGap: this.config?.isTrendChart ? [0.2] : undefined,
|
|
1689
|
+
name: this.config?.secondaryYAxisName || '',
|
|
1690
|
+
nameLocation: 'center',
|
|
1691
|
+
...(this.config?.secondaryYAxisConfig || {}),
|
|
1673
1692
|
axisLine: {
|
|
1674
1693
|
show: this.config?.showYAxisLine ?? true,
|
|
1694
|
+
...(this.config?.secondaryYAxisConfig?.axisLine || {}),
|
|
1675
1695
|
lineStyle: {
|
|
1676
1696
|
color: '#C0C2C5',
|
|
1677
1697
|
width: 1,
|
|
1698
|
+
...(this.config?.secondaryYAxisConfig?.axisLine?.lineStyle || {}),
|
|
1678
1699
|
},
|
|
1679
1700
|
},
|
|
1680
1701
|
axisTick: {
|
|
1681
1702
|
show: false,
|
|
1703
|
+
...(this.config?.secondaryYAxisConfig?.axisTick || {}),
|
|
1682
1704
|
},
|
|
1683
1705
|
axisLabel: {
|
|
1684
1706
|
show: this.config?.showSecondaryYAxisLabel ?? true,
|
|
@@ -1715,23 +1737,24 @@ class LinesChart {
|
|
|
1715
1737
|
}
|
|
1716
1738
|
return value;
|
|
1717
1739
|
},
|
|
1740
|
+
...(this.config?.secondaryYAxisConfig?.axisLabel || {}),
|
|
1718
1741
|
},
|
|
1719
|
-
name: this.config?.secondaryYAxisName || '',
|
|
1720
|
-
nameLocation: 'center',
|
|
1721
1742
|
nameTextStyle: {
|
|
1722
1743
|
color: '#434A51',
|
|
1723
1744
|
fontSize: 14,
|
|
1724
1745
|
fontWeight: 400,
|
|
1746
|
+
...(this.config?.secondaryYAxisConfig?.nameTextStyle || {}),
|
|
1725
1747
|
},
|
|
1726
1748
|
splitLine: {
|
|
1727
1749
|
show: this.config?.showSecondaryYAxisSplitLine ?? true,
|
|
1750
|
+
...(this.config?.secondaryYAxisConfig?.splitLine || {}),
|
|
1728
1751
|
lineStyle: {
|
|
1729
1752
|
type: 'dashed',
|
|
1730
1753
|
color: '#C0C2C5',
|
|
1731
1754
|
width: 1,
|
|
1755
|
+
...(this.config?.secondaryYAxisConfig?.splitLine?.lineStyle || {}),
|
|
1732
1756
|
},
|
|
1733
1757
|
},
|
|
1734
|
-
...(this.config?.secondaryYAxisConfig || {}),
|
|
1735
1758
|
},
|
|
1736
1759
|
]
|
|
1737
1760
|
: []),
|
|
@@ -2115,57 +2138,71 @@ class BarChart {
|
|
|
2115
2138
|
xAxis: {
|
|
2116
2139
|
type: 'category',
|
|
2117
2140
|
data: this.config?.xAxisData,
|
|
2141
|
+
name: this.config?.xAxisName || '',
|
|
2142
|
+
nameLocation: 'center',
|
|
2143
|
+
...(this.config?.xAxis || {}),
|
|
2118
2144
|
axisLine: {
|
|
2119
2145
|
show: this.config?.showXAxisLine ?? true,
|
|
2146
|
+
...(this.config?.xAxis?.axisLine || {}),
|
|
2120
2147
|
lineStyle: {
|
|
2121
2148
|
color: '#C0C2C5',
|
|
2122
2149
|
width: 1,
|
|
2150
|
+
...(this.config?.xAxis?.axisLine?.lineStyle || {}),
|
|
2123
2151
|
},
|
|
2124
2152
|
},
|
|
2125
2153
|
axisTick: {
|
|
2126
2154
|
show: false,
|
|
2155
|
+
...(this.config?.xAxis?.axisTick || {}),
|
|
2127
2156
|
},
|
|
2128
2157
|
axisLabel: {
|
|
2129
2158
|
show: this.config?.showXAxisLabel ?? true,
|
|
2130
2159
|
color: '#434A51',
|
|
2131
2160
|
fontSize: 12,
|
|
2161
|
+
alignMinLabel: 'left',
|
|
2162
|
+
alignMaxLabel: 'right',
|
|
2163
|
+
...(this.config?.xAxis?.axisLabel || {}),
|
|
2132
2164
|
},
|
|
2133
|
-
name: this.config?.xAxisName || '',
|
|
2134
|
-
nameLocation: 'center',
|
|
2135
2165
|
nameTextStyle: {
|
|
2136
2166
|
color: '#434A51',
|
|
2137
2167
|
fontSize: 14,
|
|
2138
2168
|
fontWeight: 400,
|
|
2169
|
+
...(this.config?.xAxis?.nameTextStyle || {}),
|
|
2139
2170
|
},
|
|
2140
2171
|
splitLine: {
|
|
2141
2172
|
show: this.config?.showXAxisSplitLine ?? true,
|
|
2173
|
+
...(this.config?.xAxis?.splitLine || {}),
|
|
2142
2174
|
lineStyle: {
|
|
2143
2175
|
type: 'dashed',
|
|
2144
2176
|
color: '#C0C2C5',
|
|
2145
2177
|
width: 1,
|
|
2178
|
+
...(this.config?.xAxis?.splitLine?.lineStyle || {}),
|
|
2146
2179
|
},
|
|
2147
2180
|
},
|
|
2148
|
-
...(this.config?.xAxis || {}),
|
|
2149
2181
|
},
|
|
2150
2182
|
yAxis: [
|
|
2151
2183
|
{
|
|
2152
2184
|
type: 'value',
|
|
2185
|
+
name: this.config?.yAxisName || '',
|
|
2186
|
+
nameLocation: 'center',
|
|
2187
|
+
...(this.config?.yAxis || {}),
|
|
2153
2188
|
axisLine: {
|
|
2154
2189
|
show: this.config?.showYAxisLine ?? true,
|
|
2190
|
+
...(this.config?.yAxis?.axisLine || {}),
|
|
2155
2191
|
lineStyle: {
|
|
2156
2192
|
color: '#C0C2C5',
|
|
2157
2193
|
width: 1,
|
|
2194
|
+
...(this.config?.yAxis?.lineStyle || {}),
|
|
2158
2195
|
},
|
|
2159
2196
|
},
|
|
2160
2197
|
axisTick: {
|
|
2161
2198
|
show: false,
|
|
2199
|
+
...(this.config?.yAxis?.axisTick || {}),
|
|
2162
2200
|
},
|
|
2163
|
-
name: this.config?.yAxisName || '',
|
|
2164
|
-
nameLocation: 'center',
|
|
2165
2201
|
nameTextStyle: {
|
|
2166
2202
|
color: '#434A51',
|
|
2167
2203
|
fontSize: 14,
|
|
2168
2204
|
fontWeight: 400,
|
|
2205
|
+
...(this.config?.yAxis?.nameTextStyle || {}),
|
|
2169
2206
|
},
|
|
2170
2207
|
axisLabel: {
|
|
2171
2208
|
show: this.config?.showYAxisLabel ?? true,
|
|
@@ -2202,30 +2239,38 @@ class BarChart {
|
|
|
2202
2239
|
}
|
|
2203
2240
|
return value;
|
|
2204
2241
|
},
|
|
2242
|
+
...(this.config?.yAxis?.axisLabel || {}),
|
|
2205
2243
|
},
|
|
2206
2244
|
splitLine: {
|
|
2207
2245
|
show: this.config?.showYAxisSplitLine ?? true,
|
|
2246
|
+
...(this.config?.yAxis?.splitLine || {}),
|
|
2208
2247
|
lineStyle: {
|
|
2209
2248
|
type: 'dashed',
|
|
2210
2249
|
color: '#C0C2C5',
|
|
2211
2250
|
width: 1,
|
|
2251
|
+
...(this.config?.yAxis?.splitLine?.lineStyle || {}),
|
|
2212
2252
|
},
|
|
2213
2253
|
},
|
|
2214
|
-
...(this.config?.yAxis || {}),
|
|
2215
2254
|
},
|
|
2216
2255
|
...(this.config?.secondaryYAxis
|
|
2217
2256
|
? [
|
|
2218
2257
|
{
|
|
2219
2258
|
type: 'value',
|
|
2259
|
+
name: this.config?.secondaryYAxisName || '',
|
|
2260
|
+
nameLocation: 'center',
|
|
2261
|
+
...(this.config?.secondaryYAxisConfig || {}),
|
|
2220
2262
|
axisLine: {
|
|
2221
2263
|
show: this.config?.showYAxisLine ?? true,
|
|
2264
|
+
...(this.config?.secondaryYAxisConfig?.axisLine || {}),
|
|
2222
2265
|
lineStyle: {
|
|
2223
2266
|
color: '#C0C2C5',
|
|
2224
2267
|
width: 1,
|
|
2268
|
+
...(this.config?.secondaryYAxisConfig?.axisLine?.lineStyle || {}),
|
|
2225
2269
|
},
|
|
2226
2270
|
},
|
|
2227
2271
|
axisTick: {
|
|
2228
2272
|
show: false,
|
|
2273
|
+
...(this.config?.secondaryYAxisConfig?.axisTick || {}),
|
|
2229
2274
|
},
|
|
2230
2275
|
axisLabel: {
|
|
2231
2276
|
show: this.config?.showSecondaryYAxisLabel ?? true,
|
|
@@ -2262,23 +2307,24 @@ class BarChart {
|
|
|
2262
2307
|
}
|
|
2263
2308
|
return value;
|
|
2264
2309
|
},
|
|
2310
|
+
...(this.config?.secondaryYAxisConfig?.axisLabel || {}),
|
|
2265
2311
|
},
|
|
2266
|
-
name: this.config?.secondaryYAxisName || '',
|
|
2267
|
-
nameLocation: 'center',
|
|
2268
2312
|
nameTextStyle: {
|
|
2269
2313
|
color: '#434A51',
|
|
2270
2314
|
fontSize: 14,
|
|
2271
2315
|
fontWeight: 400,
|
|
2316
|
+
...(this.config?.secondaryYAxisConfig?.nameTextStyle || {}),
|
|
2272
2317
|
},
|
|
2273
2318
|
splitLine: {
|
|
2274
2319
|
show: this.config?.showSecondaryYAxisSplitLine ?? true,
|
|
2320
|
+
...(this.config?.secondaryYAxisConfig?.splitLine || {}),
|
|
2275
2321
|
lineStyle: {
|
|
2276
2322
|
type: 'dashed',
|
|
2277
2323
|
color: '#C0C2C5',
|
|
2278
2324
|
width: 1,
|
|
2325
|
+
...(this.config?.secondaryYAxisConfig?.splitLine?.lineStyle || {}),
|
|
2279
2326
|
},
|
|
2280
2327
|
},
|
|
2281
|
-
...(this.config?.secondaryYAxisConfig || {}),
|
|
2282
2328
|
},
|
|
2283
2329
|
]
|
|
2284
2330
|
: []),
|
|
@@ -4059,9 +4105,213 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4059
4105
|
type: Output
|
|
4060
4106
|
}] } });
|
|
4061
4107
|
|
|
4108
|
+
const DEFAULT_COLORS = ['#2f8f3a', '#d0a020', '#dc8a1f', '#a43b35', '#d9dde1'];
|
|
4109
|
+
const DEFAULT_UNKNOWN_STATUS = {
|
|
4110
|
+
value: '__unknown__',
|
|
4111
|
+
label: 'Unknown status',
|
|
4112
|
+
color: '#7b8491',
|
|
4113
|
+
};
|
|
4114
|
+
let statusTimelineInstanceSequence = 0;
|
|
4115
|
+
class StatusTimelineComponent {
|
|
4116
|
+
config;
|
|
4117
|
+
chartEvent = new EventEmitter();
|
|
4118
|
+
renderedItems = [];
|
|
4119
|
+
legendStatuses = [];
|
|
4120
|
+
activeIndex = null;
|
|
4121
|
+
timelineMinWidth = '100%';
|
|
4122
|
+
resolvedStartLabel = '';
|
|
4123
|
+
resolvedEndLabel = '';
|
|
4124
|
+
tooltipIdPrefix = `${inject(APP_ID).replace(/[^a-zA-Z0-9_-]/g, '-')}-status-timeline-${statusTimelineInstanceSequence++}-tooltip`;
|
|
4125
|
+
dimmedStatuses = new Set();
|
|
4126
|
+
get legendPosition() {
|
|
4127
|
+
return this.config.legendPosition ?? 'bottom';
|
|
4128
|
+
}
|
|
4129
|
+
get legendLayout() {
|
|
4130
|
+
return (this.config.legendLayout ??
|
|
4131
|
+
(this.legendPosition === 'left' || this.legendPosition === 'right' ? 'vertical' : 'horizontal'));
|
|
4132
|
+
}
|
|
4133
|
+
get legendScrollable() {
|
|
4134
|
+
return this.config.legendScrollable !== false;
|
|
4135
|
+
}
|
|
4136
|
+
get legendInteractive() {
|
|
4137
|
+
return this.config.legendInteractive !== false;
|
|
4138
|
+
}
|
|
4139
|
+
get legendAlign() {
|
|
4140
|
+
if (this.config.legendAlign === 'left')
|
|
4141
|
+
return 'start';
|
|
4142
|
+
if (this.config.legendAlign === 'right')
|
|
4143
|
+
return 'end';
|
|
4144
|
+
return this.config.legendAlign ?? 'start';
|
|
4145
|
+
}
|
|
4146
|
+
get legendLabelAlign() {
|
|
4147
|
+
return this.config.legendLabelAlign ?? 'left';
|
|
4148
|
+
}
|
|
4149
|
+
get legendLabelJustify() {
|
|
4150
|
+
if (this.legendLabelAlign === 'center')
|
|
4151
|
+
return 'center';
|
|
4152
|
+
if (this.legendLabelAlign === 'right')
|
|
4153
|
+
return 'flex-end';
|
|
4154
|
+
return 'flex-start';
|
|
4155
|
+
}
|
|
4156
|
+
get endpointLabelsAlign() {
|
|
4157
|
+
if (this.config.endpointLabelsAlign === 'left')
|
|
4158
|
+
return 'start';
|
|
4159
|
+
if (this.config.endpointLabelsAlign === 'right')
|
|
4160
|
+
return 'end';
|
|
4161
|
+
return this.config.endpointLabelsAlign ?? 'space-between';
|
|
4162
|
+
}
|
|
4163
|
+
get legendMaxWidth() {
|
|
4164
|
+
return this.config.legendMaxWidth ?? null;
|
|
4165
|
+
}
|
|
4166
|
+
get legendMaxHeight() {
|
|
4167
|
+
return this.config.legendMaxHeight ?? (this.legendLayout === 'vertical' ? '240px' : null);
|
|
4168
|
+
}
|
|
4169
|
+
ngOnChanges() {
|
|
4170
|
+
this.rebuild();
|
|
4171
|
+
}
|
|
4172
|
+
activate(index) {
|
|
4173
|
+
this.activeIndex = index;
|
|
4174
|
+
}
|
|
4175
|
+
deactivate(index) {
|
|
4176
|
+
if (this.activeIndex === index)
|
|
4177
|
+
this.activeIndex = null;
|
|
4178
|
+
}
|
|
4179
|
+
selectItem(item) {
|
|
4180
|
+
this.chartEvent.emit({
|
|
4181
|
+
type: 'itemClick',
|
|
4182
|
+
item: item.source,
|
|
4183
|
+
index: item.originalIndex,
|
|
4184
|
+
});
|
|
4185
|
+
}
|
|
4186
|
+
isStatusSelected(value) {
|
|
4187
|
+
return !this.dimmedStatuses.has(value);
|
|
4188
|
+
}
|
|
4189
|
+
toggleStatus(status) {
|
|
4190
|
+
if (!this.legendInteractive)
|
|
4191
|
+
return;
|
|
4192
|
+
if (this.dimmedStatuses.has(status.value)) {
|
|
4193
|
+
this.dimmedStatuses.delete(status.value);
|
|
4194
|
+
}
|
|
4195
|
+
else {
|
|
4196
|
+
this.dimmedStatuses.add(status.value);
|
|
4197
|
+
}
|
|
4198
|
+
this.chartEvent.emit({
|
|
4199
|
+
type: 'legendToggle',
|
|
4200
|
+
status,
|
|
4201
|
+
selected: this.isStatusSelected(status.value),
|
|
4202
|
+
});
|
|
4203
|
+
}
|
|
4204
|
+
tooltipId(index) {
|
|
4205
|
+
return `${this.tooltipIdPrefix}-${index}`;
|
|
4206
|
+
}
|
|
4207
|
+
trackItem(_, item) {
|
|
4208
|
+
return `${item.start.getTime()}-${item.end.getTime()}-${item.status.value}-${item.originalIndex}`;
|
|
4209
|
+
}
|
|
4210
|
+
trackStatus(_, status) {
|
|
4211
|
+
return status.value;
|
|
4212
|
+
}
|
|
4213
|
+
rebuild() {
|
|
4214
|
+
const config = this.config;
|
|
4215
|
+
if (!config) {
|
|
4216
|
+
this.renderedItems = [];
|
|
4217
|
+
this.legendStatuses = [];
|
|
4218
|
+
return;
|
|
4219
|
+
}
|
|
4220
|
+
const statusMap = new Map();
|
|
4221
|
+
this.legendStatuses = (config.statuses ?? []).map((status, index) => {
|
|
4222
|
+
const resolved = { ...status, color: status.color ?? DEFAULT_COLORS[index % DEFAULT_COLORS.length] };
|
|
4223
|
+
statusMap.set(resolved.value, resolved);
|
|
4224
|
+
return resolved;
|
|
4225
|
+
});
|
|
4226
|
+
const configuredStatusValues = new Set(this.legendStatuses.map((status) => status.value));
|
|
4227
|
+
this.dimmedStatuses = new Set([...this.dimmedStatuses].filter((value) => configuredStatusValues.has(value)));
|
|
4228
|
+
const unknownStatus = {
|
|
4229
|
+
...DEFAULT_UNKNOWN_STATUS,
|
|
4230
|
+
...config.unknownStatus,
|
|
4231
|
+
value: config.unknownStatus?.value ?? DEFAULT_UNKNOWN_STATUS.value,
|
|
4232
|
+
label: config.unknownStatus?.label ?? DEFAULT_UNKNOWN_STATUS.label,
|
|
4233
|
+
color: config.unknownStatus?.color ?? DEFAULT_UNKNOWN_STATUS.color,
|
|
4234
|
+
};
|
|
4235
|
+
this.renderedItems = (config.data ?? [])
|
|
4236
|
+
.map((item, originalIndex) => {
|
|
4237
|
+
const start = this.toDate(item.start);
|
|
4238
|
+
const end = this.toDate(item.end);
|
|
4239
|
+
if (!start || !end || end.getTime() <= start.getTime())
|
|
4240
|
+
return null;
|
|
4241
|
+
const status = statusMap.get(item.status) ?? {
|
|
4242
|
+
...unknownStatus,
|
|
4243
|
+
value: item.status,
|
|
4244
|
+
label: config.unknownStatus?.label ?? `Unknown (${item.status})`,
|
|
4245
|
+
};
|
|
4246
|
+
const durationMs = end.getTime() - start.getTime();
|
|
4247
|
+
const context = { item, status, start, end, durationMs };
|
|
4248
|
+
const tooltip = config.tooltipFormatter?.(context) ?? this.defaultTooltip(context);
|
|
4249
|
+
const accessibleLabel = [item.label, status.label, tooltip].filter(Boolean).join('. ');
|
|
4250
|
+
const tooltipLines = tooltip
|
|
4251
|
+
.split(/\r?\n/)
|
|
4252
|
+
.map((line) => line.trim())
|
|
4253
|
+
.filter(Boolean);
|
|
4254
|
+
return {
|
|
4255
|
+
source: item,
|
|
4256
|
+
originalIndex,
|
|
4257
|
+
start,
|
|
4258
|
+
end,
|
|
4259
|
+
durationMs,
|
|
4260
|
+
status,
|
|
4261
|
+
tooltip,
|
|
4262
|
+
tooltipLines,
|
|
4263
|
+
accessibleLabel,
|
|
4264
|
+
};
|
|
4265
|
+
})
|
|
4266
|
+
.filter((item) => item !== null)
|
|
4267
|
+
.sort((left, right) => left.start.getTime() - right.start.getTime());
|
|
4268
|
+
const gap = Math.max(config.segmentGap ?? 2, 0);
|
|
4269
|
+
const minimum = Math.max(config.minSegmentWidth ?? 6, 1);
|
|
4270
|
+
const requiredWidth = this.renderedItems.length * minimum + Math.max(this.renderedItems.length - 1, 0) * gap;
|
|
4271
|
+
this.timelineMinWidth = `max(100%, ${requiredWidth}px)`;
|
|
4272
|
+
this.resolvedStartLabel = config.startLabel ?? this.formatDate(this.renderedItems[0]?.start);
|
|
4273
|
+
this.resolvedEndLabel = config.endLabel ?? this.formatDate(this.renderedItems.at(-1)?.end);
|
|
4274
|
+
this.activeIndex = null;
|
|
4275
|
+
}
|
|
4276
|
+
toDate(value) {
|
|
4277
|
+
const date = value instanceof Date ? new Date(value.getTime()) : new Date(value);
|
|
4278
|
+
return Number.isFinite(date.getTime()) ? date : null;
|
|
4279
|
+
}
|
|
4280
|
+
formatDate(date) {
|
|
4281
|
+
if (!date)
|
|
4282
|
+
return '';
|
|
4283
|
+
return (this.config.dateFormatter?.(date) ??
|
|
4284
|
+
new Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(date));
|
|
4285
|
+
}
|
|
4286
|
+
defaultTooltip(context) {
|
|
4287
|
+
const duration = this.config.durationFormatter?.(context.durationMs) ?? this.formatDuration(context.durationMs);
|
|
4288
|
+
return `${context.status.label}. Start: ${this.formatDate(context.start)}. End: ${this.formatDate(context.end)}. Duration: ${duration}`;
|
|
4289
|
+
}
|
|
4290
|
+
formatDuration(durationMs) {
|
|
4291
|
+
const totalMinutes = Math.max(Math.round(durationMs / 60_000), 1);
|
|
4292
|
+
const days = Math.floor(totalMinutes / 1_440);
|
|
4293
|
+
const hours = Math.floor((totalMinutes % 1_440) / 60);
|
|
4294
|
+
const minutes = totalMinutes % 60;
|
|
4295
|
+
return [days ? `${days}d` : '', hours ? `${hours}h` : '', minutes || (!days && !hours) ? `${minutes}m` : '']
|
|
4296
|
+
.filter(Boolean)
|
|
4297
|
+
.join(' ');
|
|
4298
|
+
}
|
|
4299
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: StatusTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4300
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: StatusTimelineComponent, isStandalone: true, selector: "lib-status-timeline", inputs: { config: "config" }, outputs: { chartEvent: "chartEvent" }, usesOnChanges: true, ngImport: i0, template: "<section\n class=\"status-timeline\"\n [style.--status-timeline-gap]=\"config.segmentGap ?? 2\"\n [style.--status-timeline-min-segment-width]=\"config.minSegmentWidth ?? 6\"\n [style.--status-timeline-dimmed-opacity]=\"config.legendDimmedOpacity ?? 0.3\"\n [class.status-timeline--legend-top]=\"legendPosition === 'top'\"\n [class.status-timeline--legend-bottom]=\"legendPosition === 'bottom'\"\n [class.status-timeline--legend-left]=\"legendPosition === 'left'\"\n [class.status-timeline--legend-right]=\"legendPosition === 'right'\"\n [attr.aria-label]=\"config.ariaLabel || 'Status timeline'\"\n>\n @if (config.loading) {\n <div class=\"status-timeline__state\" role=\"status\" aria-live=\"polite\">\n <span class=\"status-timeline__skeleton\" aria-hidden=\"true\"></span>\n <span>{{ config.loadingLabel || 'Loading timeline' }}</span>\n </div>\n } @else if (config.error) {\n <div class=\"status-timeline__state status-timeline__state--error\" role=\"alert\">\n {{ config.error }}\n </div>\n } @else if (!renderedItems.length) {\n <div class=\"status-timeline__state\" role=\"status\">\n {{ config.emptyLabel || 'No timeline data available' }}\n </div>\n } @else {\n <div class=\"status-timeline__visual\">\n <div class=\"status-timeline__scroll\" tabindex=\"0\" aria-label=\"Scrollable status intervals\">\n <div class=\"status-timeline__content\" [style.min-width]=\"timelineMinWidth\">\n <div class=\"status-timeline__segments\" role=\"list\">\n @for (item of renderedItems; track trackItem($index, item); let index = $index) {\n <button\n type=\"button\"\n role=\"listitem\"\n class=\"status-timeline__segment\"\n [class.status-timeline__segment--dimmed]=\"!isStatusSelected(item.status.value)\"\n [style.background-color]=\"item.status.color\"\n [style.flex-grow]=\"item.durationMs\"\n [attr.aria-label]=\"item.accessibleLabel\"\n [attr.aria-describedby]=\"config.showTooltip !== false ? tooltipId(index) : null\"\n (mouseenter)=\"activate(index)\"\n (mouseleave)=\"deactivate(index)\"\n (focus)=\"activate(index)\"\n (blur)=\"deactivate(index)\"\n (click)=\"selectItem(item)\"\n >\n <span class=\"status-timeline__sr-only\">{{ item.status.label }}</span>\n @if (config.showTooltip !== false && activeIndex === index) {\n <span\n class=\"status-timeline__tooltip\"\n [class.status-timeline__tooltip--start]=\"index === 0\"\n [class.status-timeline__tooltip--end]=\"index === renderedItems.length - 1\"\n [id]=\"tooltipId(index)\"\n role=\"tooltip\"\n >\n @for (line of item.tooltipLines; track $index) {\n <span\n class=\"status-timeline__tooltip-line\"\n [class.status-timeline__tooltip-title]=\"$index === 0\"\n >{{ line }}</span\n >\n }\n </span>\n }\n </button>\n }\n </div>\n\n @if (config.showEndpointLabels !== false) {\n <div\n class=\"status-timeline__labels\"\n [class.status-timeline__labels--start]=\"endpointLabelsAlign === 'start'\"\n [class.status-timeline__labels--center]=\"endpointLabelsAlign === 'center'\"\n [class.status-timeline__labels--end]=\"endpointLabelsAlign === 'end'\"\n aria-hidden=\"true\"\n >\n <span>{{ resolvedStartLabel }}</span>\n <span>{{ resolvedEndLabel }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n\n @if (config.showLegend !== false && legendStatuses.length) {\n <div\n class=\"status-timeline__legend-row\"\n [class.status-timeline__legend-row--vertical]=\"legendLayout === 'vertical'\"\n >\n <ul\n class=\"status-timeline__legend\"\n [class.status-timeline__legend--vertical]=\"legendLayout === 'vertical'\"\n [class.status-timeline__legend--scrollable]=\"legendScrollable\"\n [class.status-timeline__legend--align-center]=\"legendAlign === 'center'\"\n [class.status-timeline__legend--align-end]=\"legendAlign === 'end'\"\n [class.status-timeline__legend--align-space-between]=\"legendAlign === 'space-between'\"\n [style.max-width]=\"legendMaxWidth\"\n [style.max-height]=\"legendMaxHeight\"\n aria-label=\"Status legend\"\n tabindex=\"0\"\n >\n @for (status of legendStatuses; track trackStatus($index, status)) {\n <li\n class=\"status-timeline__legend-item\"\n [class.status-timeline__legend-item--dimmed]=\"!isStatusSelected(status.value)\"\n [style.justify-content]=\"legendLabelJustify\"\n [style.text-align]=\"legendLabelAlign\"\n >\n <button\n type=\"button\"\n class=\"status-timeline__legend-button\"\n role=\"switch\"\n [attr.aria-checked]=\"isStatusSelected(status.value)\"\n [attr.aria-label]=\"\n (isStatusSelected(status.value) ? 'Hide ' : 'Show ') + status.label + ' intervals'\n \"\n [disabled]=\"!legendInteractive\"\n (click)=\"toggleStatus(status)\"\n >\n <span\n class=\"status-timeline__legend-swatch\"\n [style.background-color]=\"status.color\"\n aria-hidden=\"true\"\n ></span>\n <span>{{ status.label }}</span>\n </button>\n </li>\n }\n </ul>\n @if (config.legendNote) {\n <p class=\"status-timeline__legend-note\">{{ config.legendNote }}</p>\n }\n </div>\n }\n }\n</section>\n", styles: [":host{display:block;width:100%;max-width:100%;min-width:0;box-sizing:border-box;color:var(--status-timeline-text-color, #344054);font-family:var(--status-timeline-font-family, inherit)}.status-timeline{display:flex;flex-direction:column;width:100%;min-width:0}.status-timeline__visual{flex:1 1 auto;width:100%;min-width:0}.status-timeline__scroll{display:block;max-width:100%;min-width:0;width:100%;overflow-x:auto;overflow-y:visible;overscroll-behavior-inline:contain;padding:var(--status-timeline-tooltip-space, 90px) 1px 4px;box-sizing:border-box;scrollbar-width:thin}.status-timeline__scroll:focus-visible{outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__content{box-sizing:border-box}.status-timeline__segments{display:flex;align-items:stretch;gap:calc(var(--status-timeline-gap, 2) * 1px);height:var(--status-timeline-height, 36px)}.status-timeline__segment{position:relative;flex-basis:0;min-width:calc(var(--status-timeline-min-segment-width, 6) * 1px);min-height:24px;padding:0;border:0;border-radius:var(--status-timeline-segment-radius, 2px);cursor:pointer;transition:opacity .14s ease,filter .14s ease,box-shadow .14s ease}.status-timeline__segment--dimmed{opacity:var(--status-timeline-dimmed-opacity, .3);filter:saturate(.35)}.status-timeline__segment:hover,.status-timeline__segment:focus-visible{z-index:2;box-shadow:0 0 0 2px var(--status-timeline-focus-ring, rgba(37, 99, 235, .45));outline:none}.status-timeline__tooltip{position:absolute;z-index:10;display:flex;flex-direction:column;gap:2px;left:50%;bottom:calc(100% + 8px);width:max-content;min-width:var(--status-timeline-tooltip-min-width, 166px);max-width:min(300px,80vw);transform:translate(-50%);padding:8px 10px;border-radius:var(--status-timeline-tooltip-radius, 4px);background:var(--status-timeline-tooltip-background, #101828);color:var(--status-timeline-tooltip-color, #fff);box-shadow:0 4px 12px #10182833;font-size:var(--status-timeline-tooltip-font-size, 12px);line-height:1.5;text-align:left;pointer-events:none}.status-timeline__tooltip-line{display:block;white-space:normal}.status-timeline__tooltip-title{font-weight:700;white-space:nowrap}.status-timeline__tooltip--start{left:0;transform:none}.status-timeline__tooltip--end{right:0;left:auto;transform:none}.status-timeline__labels{display:flex;justify-content:space-between;gap:16px;margin-top:8px;color:var(--status-timeline-muted-color, #667085);font-size:var(--status-timeline-label-font-size, 12px)}.status-timeline__labels--start{justify-content:flex-start}.status-timeline__labels--center{justify-content:center}.status-timeline__labels--end{justify-content:flex-end}.status-timeline__legend-row{display:flex;flex-wrap:wrap;align-items:center;gap:18px;margin:12px 0 0;padding:12px 0 0;border-top:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline__legend{display:flex;flex:1 1 520px;min-width:0;flex-wrap:wrap;align-items:center;gap:8px 18px;margin:0;padding:0;list-style:none;scrollbar-width:thin}.status-timeline__legend--vertical{flex:0 1 auto;flex-direction:column;flex-wrap:nowrap;align-items:flex-start}.status-timeline__legend--align-center{justify-content:safe center}.status-timeline__legend--align-end{justify-content:safe flex-end}.status-timeline__legend--align-space-between{justify-content:space-between}.status-timeline__legend--scrollable:not(.status-timeline__legend--vertical){flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;overscroll-behavior-inline:contain}.status-timeline__legend--scrollable.status-timeline__legend--vertical{overflow-x:hidden;overflow-y:auto;overscroll-behavior-block:contain}.status-timeline__legend:focus-visible{outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__legend-item{display:inline-flex;align-items:center;font-size:var(--status-timeline-legend-font-size, 12px);white-space:nowrap;transition:opacity .14s ease}.status-timeline__legend-item--dimmed{opacity:var(--status-timeline-dimmed-opacity, .3)}.status-timeline__legend-button{display:inline-flex;align-items:center;justify-content:inherit;width:100%;gap:6px;margin:0;padding:2px 0;border:0;background:transparent;color:inherit;font:inherit;text-align:inherit;white-space:inherit;cursor:pointer}.status-timeline__legend-button:disabled{opacity:1;cursor:default}.status-timeline__legend-button:focus-visible{border-radius:2px;outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__legend--vertical .status-timeline__legend-item{width:100%;box-sizing:border-box}.status-timeline__legend-swatch{width:10px;height:10px;flex:0 0 10px;border-radius:var(--status-timeline-legend-radius, 2px)}.status-timeline__legend-note{flex:1 1 300px;margin:0;color:var(--status-timeline-muted-color, #667085);font-size:var(--status-timeline-legend-font-size, 12px);text-align:right}.status-timeline--legend-top .status-timeline__legend-row{order:-1;margin:0 0 12px;padding:0 0 12px;border-top:0;border-bottom:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-left,.status-timeline--legend-right{flex-direction:row;align-items:stretch;gap:12px}.status-timeline--legend-left .status-timeline__legend-row,.status-timeline--legend-right .status-timeline__legend-row{flex:0 1 auto;flex-direction:column;align-items:flex-start;width:max-content;max-width:min(280px,40%);margin:0}.status-timeline--legend-left .status-timeline__legend-row{order:-1;padding:0 12px 0 0;border-top:0;border-right:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-right .status-timeline__legend-row{padding:0 0 0 12px;border-top:0;border-left:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline__legend-row--vertical .status-timeline__legend-note{text-align:left}.status-timeline__state{min-height:var(--status-timeline-state-height, 72px);display:flex;align-items:center;justify-content:center;gap:10px;padding:12px;box-sizing:border-box;color:var(--status-timeline-muted-color, #667085);border:1px dashed var(--status-timeline-divider-color, #d0d5dd);border-radius:4px;font-size:13px}.status-timeline__state--error{color:var(--status-timeline-error-color, #b42318);background:var(--status-timeline-error-background, #fef3f2)}.status-timeline__skeleton{width:min(180px,45%);height:12px;border-radius:3px;background:linear-gradient(90deg,#eaecf0 25%,#f9fafb,#eaecf0 75%);background-size:200% 100%;animation:status-timeline-shimmer 1.5s infinite}.status-timeline__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes status-timeline-shimmer{to{background-position-x:-200%}}@media (prefers-reduced-motion: reduce){.status-timeline__skeleton{animation:none}.status-timeline__segment,.status-timeline__legend-item{transition:none}}@media (max-width: 720px){.status-timeline--legend-left,.status-timeline--legend-right{flex-direction:column}.status-timeline--legend-left .status-timeline__legend-row,.status-timeline--legend-right .status-timeline__legend-row{width:100%;max-width:100%}.status-timeline--legend-left .status-timeline__legend-row{margin:0 0 12px;padding:0 0 12px;border-right:0;border-bottom:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-right .status-timeline__legend-row{margin:12px 0 0;padding:12px 0 0;border-top:1px solid var(--status-timeline-divider-color, #eaecf0);border-left:0}.status-timeline__legend-row{align-items:flex-start;flex-direction:column}.status-timeline__legend-note{text-align:left}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4301
|
+
}
|
|
4302
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: StatusTimelineComponent, decorators: [{
|
|
4303
|
+
type: Component,
|
|
4304
|
+
args: [{ selector: 'lib-status-timeline', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section\n class=\"status-timeline\"\n [style.--status-timeline-gap]=\"config.segmentGap ?? 2\"\n [style.--status-timeline-min-segment-width]=\"config.minSegmentWidth ?? 6\"\n [style.--status-timeline-dimmed-opacity]=\"config.legendDimmedOpacity ?? 0.3\"\n [class.status-timeline--legend-top]=\"legendPosition === 'top'\"\n [class.status-timeline--legend-bottom]=\"legendPosition === 'bottom'\"\n [class.status-timeline--legend-left]=\"legendPosition === 'left'\"\n [class.status-timeline--legend-right]=\"legendPosition === 'right'\"\n [attr.aria-label]=\"config.ariaLabel || 'Status timeline'\"\n>\n @if (config.loading) {\n <div class=\"status-timeline__state\" role=\"status\" aria-live=\"polite\">\n <span class=\"status-timeline__skeleton\" aria-hidden=\"true\"></span>\n <span>{{ config.loadingLabel || 'Loading timeline' }}</span>\n </div>\n } @else if (config.error) {\n <div class=\"status-timeline__state status-timeline__state--error\" role=\"alert\">\n {{ config.error }}\n </div>\n } @else if (!renderedItems.length) {\n <div class=\"status-timeline__state\" role=\"status\">\n {{ config.emptyLabel || 'No timeline data available' }}\n </div>\n } @else {\n <div class=\"status-timeline__visual\">\n <div class=\"status-timeline__scroll\" tabindex=\"0\" aria-label=\"Scrollable status intervals\">\n <div class=\"status-timeline__content\" [style.min-width]=\"timelineMinWidth\">\n <div class=\"status-timeline__segments\" role=\"list\">\n @for (item of renderedItems; track trackItem($index, item); let index = $index) {\n <button\n type=\"button\"\n role=\"listitem\"\n class=\"status-timeline__segment\"\n [class.status-timeline__segment--dimmed]=\"!isStatusSelected(item.status.value)\"\n [style.background-color]=\"item.status.color\"\n [style.flex-grow]=\"item.durationMs\"\n [attr.aria-label]=\"item.accessibleLabel\"\n [attr.aria-describedby]=\"config.showTooltip !== false ? tooltipId(index) : null\"\n (mouseenter)=\"activate(index)\"\n (mouseleave)=\"deactivate(index)\"\n (focus)=\"activate(index)\"\n (blur)=\"deactivate(index)\"\n (click)=\"selectItem(item)\"\n >\n <span class=\"status-timeline__sr-only\">{{ item.status.label }}</span>\n @if (config.showTooltip !== false && activeIndex === index) {\n <span\n class=\"status-timeline__tooltip\"\n [class.status-timeline__tooltip--start]=\"index === 0\"\n [class.status-timeline__tooltip--end]=\"index === renderedItems.length - 1\"\n [id]=\"tooltipId(index)\"\n role=\"tooltip\"\n >\n @for (line of item.tooltipLines; track $index) {\n <span\n class=\"status-timeline__tooltip-line\"\n [class.status-timeline__tooltip-title]=\"$index === 0\"\n >{{ line }}</span\n >\n }\n </span>\n }\n </button>\n }\n </div>\n\n @if (config.showEndpointLabels !== false) {\n <div\n class=\"status-timeline__labels\"\n [class.status-timeline__labels--start]=\"endpointLabelsAlign === 'start'\"\n [class.status-timeline__labels--center]=\"endpointLabelsAlign === 'center'\"\n [class.status-timeline__labels--end]=\"endpointLabelsAlign === 'end'\"\n aria-hidden=\"true\"\n >\n <span>{{ resolvedStartLabel }}</span>\n <span>{{ resolvedEndLabel }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n\n @if (config.showLegend !== false && legendStatuses.length) {\n <div\n class=\"status-timeline__legend-row\"\n [class.status-timeline__legend-row--vertical]=\"legendLayout === 'vertical'\"\n >\n <ul\n class=\"status-timeline__legend\"\n [class.status-timeline__legend--vertical]=\"legendLayout === 'vertical'\"\n [class.status-timeline__legend--scrollable]=\"legendScrollable\"\n [class.status-timeline__legend--align-center]=\"legendAlign === 'center'\"\n [class.status-timeline__legend--align-end]=\"legendAlign === 'end'\"\n [class.status-timeline__legend--align-space-between]=\"legendAlign === 'space-between'\"\n [style.max-width]=\"legendMaxWidth\"\n [style.max-height]=\"legendMaxHeight\"\n aria-label=\"Status legend\"\n tabindex=\"0\"\n >\n @for (status of legendStatuses; track trackStatus($index, status)) {\n <li\n class=\"status-timeline__legend-item\"\n [class.status-timeline__legend-item--dimmed]=\"!isStatusSelected(status.value)\"\n [style.justify-content]=\"legendLabelJustify\"\n [style.text-align]=\"legendLabelAlign\"\n >\n <button\n type=\"button\"\n class=\"status-timeline__legend-button\"\n role=\"switch\"\n [attr.aria-checked]=\"isStatusSelected(status.value)\"\n [attr.aria-label]=\"\n (isStatusSelected(status.value) ? 'Hide ' : 'Show ') + status.label + ' intervals'\n \"\n [disabled]=\"!legendInteractive\"\n (click)=\"toggleStatus(status)\"\n >\n <span\n class=\"status-timeline__legend-swatch\"\n [style.background-color]=\"status.color\"\n aria-hidden=\"true\"\n ></span>\n <span>{{ status.label }}</span>\n </button>\n </li>\n }\n </ul>\n @if (config.legendNote) {\n <p class=\"status-timeline__legend-note\">{{ config.legendNote }}</p>\n }\n </div>\n }\n }\n</section>\n", styles: [":host{display:block;width:100%;max-width:100%;min-width:0;box-sizing:border-box;color:var(--status-timeline-text-color, #344054);font-family:var(--status-timeline-font-family, inherit)}.status-timeline{display:flex;flex-direction:column;width:100%;min-width:0}.status-timeline__visual{flex:1 1 auto;width:100%;min-width:0}.status-timeline__scroll{display:block;max-width:100%;min-width:0;width:100%;overflow-x:auto;overflow-y:visible;overscroll-behavior-inline:contain;padding:var(--status-timeline-tooltip-space, 90px) 1px 4px;box-sizing:border-box;scrollbar-width:thin}.status-timeline__scroll:focus-visible{outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__content{box-sizing:border-box}.status-timeline__segments{display:flex;align-items:stretch;gap:calc(var(--status-timeline-gap, 2) * 1px);height:var(--status-timeline-height, 36px)}.status-timeline__segment{position:relative;flex-basis:0;min-width:calc(var(--status-timeline-min-segment-width, 6) * 1px);min-height:24px;padding:0;border:0;border-radius:var(--status-timeline-segment-radius, 2px);cursor:pointer;transition:opacity .14s ease,filter .14s ease,box-shadow .14s ease}.status-timeline__segment--dimmed{opacity:var(--status-timeline-dimmed-opacity, .3);filter:saturate(.35)}.status-timeline__segment:hover,.status-timeline__segment:focus-visible{z-index:2;box-shadow:0 0 0 2px var(--status-timeline-focus-ring, rgba(37, 99, 235, .45));outline:none}.status-timeline__tooltip{position:absolute;z-index:10;display:flex;flex-direction:column;gap:2px;left:50%;bottom:calc(100% + 8px);width:max-content;min-width:var(--status-timeline-tooltip-min-width, 166px);max-width:min(300px,80vw);transform:translate(-50%);padding:8px 10px;border-radius:var(--status-timeline-tooltip-radius, 4px);background:var(--status-timeline-tooltip-background, #101828);color:var(--status-timeline-tooltip-color, #fff);box-shadow:0 4px 12px #10182833;font-size:var(--status-timeline-tooltip-font-size, 12px);line-height:1.5;text-align:left;pointer-events:none}.status-timeline__tooltip-line{display:block;white-space:normal}.status-timeline__tooltip-title{font-weight:700;white-space:nowrap}.status-timeline__tooltip--start{left:0;transform:none}.status-timeline__tooltip--end{right:0;left:auto;transform:none}.status-timeline__labels{display:flex;justify-content:space-between;gap:16px;margin-top:8px;color:var(--status-timeline-muted-color, #667085);font-size:var(--status-timeline-label-font-size, 12px)}.status-timeline__labels--start{justify-content:flex-start}.status-timeline__labels--center{justify-content:center}.status-timeline__labels--end{justify-content:flex-end}.status-timeline__legend-row{display:flex;flex-wrap:wrap;align-items:center;gap:18px;margin:12px 0 0;padding:12px 0 0;border-top:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline__legend{display:flex;flex:1 1 520px;min-width:0;flex-wrap:wrap;align-items:center;gap:8px 18px;margin:0;padding:0;list-style:none;scrollbar-width:thin}.status-timeline__legend--vertical{flex:0 1 auto;flex-direction:column;flex-wrap:nowrap;align-items:flex-start}.status-timeline__legend--align-center{justify-content:safe center}.status-timeline__legend--align-end{justify-content:safe flex-end}.status-timeline__legend--align-space-between{justify-content:space-between}.status-timeline__legend--scrollable:not(.status-timeline__legend--vertical){flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;overscroll-behavior-inline:contain}.status-timeline__legend--scrollable.status-timeline__legend--vertical{overflow-x:hidden;overflow-y:auto;overscroll-behavior-block:contain}.status-timeline__legend:focus-visible{outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__legend-item{display:inline-flex;align-items:center;font-size:var(--status-timeline-legend-font-size, 12px);white-space:nowrap;transition:opacity .14s ease}.status-timeline__legend-item--dimmed{opacity:var(--status-timeline-dimmed-opacity, .3)}.status-timeline__legend-button{display:inline-flex;align-items:center;justify-content:inherit;width:100%;gap:6px;margin:0;padding:2px 0;border:0;background:transparent;color:inherit;font:inherit;text-align:inherit;white-space:inherit;cursor:pointer}.status-timeline__legend-button:disabled{opacity:1;cursor:default}.status-timeline__legend-button:focus-visible{border-radius:2px;outline:2px solid var(--status-timeline-focus-color, #2563eb);outline-offset:2px}.status-timeline__legend--vertical .status-timeline__legend-item{width:100%;box-sizing:border-box}.status-timeline__legend-swatch{width:10px;height:10px;flex:0 0 10px;border-radius:var(--status-timeline-legend-radius, 2px)}.status-timeline__legend-note{flex:1 1 300px;margin:0;color:var(--status-timeline-muted-color, #667085);font-size:var(--status-timeline-legend-font-size, 12px);text-align:right}.status-timeline--legend-top .status-timeline__legend-row{order:-1;margin:0 0 12px;padding:0 0 12px;border-top:0;border-bottom:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-left,.status-timeline--legend-right{flex-direction:row;align-items:stretch;gap:12px}.status-timeline--legend-left .status-timeline__legend-row,.status-timeline--legend-right .status-timeline__legend-row{flex:0 1 auto;flex-direction:column;align-items:flex-start;width:max-content;max-width:min(280px,40%);margin:0}.status-timeline--legend-left .status-timeline__legend-row{order:-1;padding:0 12px 0 0;border-top:0;border-right:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-right .status-timeline__legend-row{padding:0 0 0 12px;border-top:0;border-left:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline__legend-row--vertical .status-timeline__legend-note{text-align:left}.status-timeline__state{min-height:var(--status-timeline-state-height, 72px);display:flex;align-items:center;justify-content:center;gap:10px;padding:12px;box-sizing:border-box;color:var(--status-timeline-muted-color, #667085);border:1px dashed var(--status-timeline-divider-color, #d0d5dd);border-radius:4px;font-size:13px}.status-timeline__state--error{color:var(--status-timeline-error-color, #b42318);background:var(--status-timeline-error-background, #fef3f2)}.status-timeline__skeleton{width:min(180px,45%);height:12px;border-radius:3px;background:linear-gradient(90deg,#eaecf0 25%,#f9fafb,#eaecf0 75%);background-size:200% 100%;animation:status-timeline-shimmer 1.5s infinite}.status-timeline__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes status-timeline-shimmer{to{background-position-x:-200%}}@media (prefers-reduced-motion: reduce){.status-timeline__skeleton{animation:none}.status-timeline__segment,.status-timeline__legend-item{transition:none}}@media (max-width: 720px){.status-timeline--legend-left,.status-timeline--legend-right{flex-direction:column}.status-timeline--legend-left .status-timeline__legend-row,.status-timeline--legend-right .status-timeline__legend-row{width:100%;max-width:100%}.status-timeline--legend-left .status-timeline__legend-row{margin:0 0 12px;padding:0 0 12px;border-right:0;border-bottom:1px solid var(--status-timeline-divider-color, #eaecf0)}.status-timeline--legend-right .status-timeline__legend-row{margin:12px 0 0;padding:12px 0 0;border-top:1px solid var(--status-timeline-divider-color, #eaecf0);border-left:0}.status-timeline__legend-row{align-items:flex-start;flex-direction:column}.status-timeline__legend-note{text-align:left}}\n"] }]
|
|
4305
|
+
}], propDecorators: { config: [{
|
|
4306
|
+
type: Input,
|
|
4307
|
+
args: [{ required: true }]
|
|
4308
|
+
}], chartEvent: [{
|
|
4309
|
+
type: Output
|
|
4310
|
+
}] } });
|
|
4311
|
+
|
|
4062
4312
|
/**
|
|
4063
4313
|
* Generated bundle index. Do not edit.
|
|
4064
4314
|
*/
|
|
4065
4315
|
|
|
4066
|
-
export { BarChart, ChartLegendAdapter, ChartLegendComponent, Charts, CustomChartComponent, DoughnutChart, Heatmap, LinesChart, PieChart, RightClickCard, SankeyChart, ScatterChartComp, StackedAreaChart };
|
|
4316
|
+
export { BarChart, ChartLegendAdapter, ChartLegendComponent, Charts, CustomChartComponent, DoughnutChart, Heatmap, LinesChart, PieChart, RightClickCard, SankeyChart, ScatterChartComp, StackedAreaChart, StatusTimelineComponent };
|
|
4067
4317
|
//# sourceMappingURL=cats-charts.mjs.map
|