@circutor/charts 0.1.0 → 0.3.0
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/bundler/index.d.ts +35 -0
- package/dist/bundler/index.js +1 -0
- package/dist/bundler/itic-chart.d.ts +11 -0
- package/dist/bundler/itic-chart.js +1 -0
- package/dist/charts/charts.esm.js +1 -1
- package/dist/charts/p-7d11d611.entry.js +25 -0
- package/dist/charts/p-BPCJmLvQ.js +3 -0
- package/dist/cjs/charts.cjs.js +2 -2
- package/dist/cjs/{index-_N-tWlJj.js → index-dJHivNOd.js} +21 -0
- package/dist/cjs/itic-chart.cjs.entry.js +489 -77
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/components/itic-chart/index.js +133 -6
- package/dist/collection/components/itic-chart/itic-chart.css +5 -0
- package/dist/collection/components/itic-chart/itic-chart.i18n.js +26 -0
- package/dist/collection/components/itic-chart/itic-chart.options.js +115 -32
- package/dist/collection/components/itic-chart/itic-chart.phases.js +55 -0
- package/dist/components/index.js +1 -1
- package/dist/components/itic-chart.js +3 -3
- package/dist/esm/charts.js +3 -3
- package/dist/esm/{index--cwjvYaF.js → index-BPCJmLvQ.js} +20 -1
- package/dist/esm/itic-chart.entry.js +489 -77
- package/dist/esm/loader.js +3 -3
- package/dist/types/components/itic-chart/index.d.ts +29 -2
- package/dist/types/components/itic-chart/itic-chart.i18n.d.ts +13 -0
- package/dist/types/components/itic-chart/itic-chart.options.d.ts +53 -4
- package/dist/types/components/itic-chart/itic-chart.phases.d.ts +17 -0
- package/dist/types/components.d.ts +43 -4
- package/dist/types/index.d.ts +1 -1
- package/package.json +11 -7
- package/readme.md +273 -37
- package/dist/charts/p--cwjvYaF.js +0 -3
- package/dist/charts/p-35caac53.entry.js +0 -25
package/readme.md
CHANGED
|
@@ -13,17 +13,24 @@ This repository aims to make the charts used by the Cloud team in their web appl
|
|
|
13
13
|
To use the chart as a Web Component, simply import it from the CDN in your HTML code.
|
|
14
14
|
|
|
15
15
|
```html
|
|
16
|
-
<script
|
|
16
|
+
<script
|
|
17
|
+
type="module"
|
|
18
|
+
src="https://unpkg.com/@circutor/charts@0.3.0/dist/charts/charts.esm.js"
|
|
19
|
+
></script>
|
|
17
20
|
```
|
|
18
21
|
|
|
19
22
|
Then, you can directly insert the chart into your HTML:
|
|
20
23
|
|
|
21
24
|
```html
|
|
22
25
|
<itic-chart
|
|
23
|
-
|
|
26
|
+
locale="es"
|
|
27
|
+
time-zone="Europe/Madrid"
|
|
28
|
+
groups='[{"phase":"AN,BN,CN","assetName":"Cuadro general","points":[{"duration":230,"voltage":93.46,"ts":"2024-06-26T20:23:45.220000+02:00","eventType":"VOLTAGE_DIP"}]},{"phase":"BN","assetName":"Cuadro general","points":[{"duration":20,"voltage":0.4000000000000057,"ts":"2025-01-26T23:04:34.840000+01:00","eventType":"POWER_INTERRUPT"}]}]'
|
|
24
29
|
></itic-chart>
|
|
25
30
|
```
|
|
26
31
|
|
|
32
|
+
The CDN files include ECharts, so there is nothing else to load. Charts on the same page share a single copy.
|
|
33
|
+
|
|
27
34
|
<details>
|
|
28
35
|
<summary>Complete example</summary>
|
|
29
36
|
|
|
@@ -35,7 +42,10 @@ Then, you can directly insert the chart into your HTML:
|
|
|
35
42
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
36
43
|
<title>Charts</title>
|
|
37
44
|
|
|
38
|
-
<script
|
|
45
|
+
<script
|
|
46
|
+
type="module"
|
|
47
|
+
src="https://unpkg.com/@circutor/charts@0.3.0/dist/charts/charts.esm.js"
|
|
48
|
+
></script>
|
|
39
49
|
|
|
40
50
|
<style>
|
|
41
51
|
body {
|
|
@@ -51,7 +61,9 @@ Then, you can directly insert the chart into your HTML:
|
|
|
51
61
|
</head>
|
|
52
62
|
<body>
|
|
53
63
|
<itic-chart
|
|
54
|
-
|
|
64
|
+
locale="es"
|
|
65
|
+
time-zone="Europe/Madrid"
|
|
66
|
+
groups='[{"phase":"AN,BN,CN","assetName":"Cuadro general","points":[{"duration":230,"voltage":93.46,"ts":"2024-06-26T20:23:45.220000+02:00","eventType":"VOLTAGE_DIP"}]},{"phase":"BN","assetName":"Cuadro general","points":[{"duration":20,"voltage":0.4000000000000057,"ts":"2025-01-26T23:04:34.840000+01:00","eventType":"POWER_INTERRUPT"}]}]'
|
|
55
67
|
></itic-chart>
|
|
56
68
|
</body>
|
|
57
69
|
</html>
|
|
@@ -59,13 +71,55 @@ Then, you can directly insert the chart into your HTML:
|
|
|
59
71
|
|
|
60
72
|
</details>
|
|
61
73
|
|
|
74
|
+
#### Loading only the charts you need
|
|
75
|
+
|
|
76
|
+
There are two ways to load the Web Components from a CDN. Both download only the code of the charts your page uses.
|
|
77
|
+
|
|
78
|
+
| Script | What it loads | Use it when |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `dist/charts/charts.esm.js` | A small loader that registers every chart tag. Each chart's code is downloaded the first time its tag appears in the page. | You want a single URL for all charts. |
|
|
81
|
+
| `dist/components/<tag>.js` | Only that chart, registered as soon as the script loads. | You want to load specific charts explicitly. |
|
|
82
|
+
|
|
83
|
+
For example, to load only the ITIC chart:
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<script
|
|
87
|
+
type="module"
|
|
88
|
+
src="https://unpkg.com/@circutor/charts@0.3.0/dist/components/itic-chart.js"
|
|
89
|
+
></script>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- Pin the version in the URL (`@circutor/charts@0.3.0`). Without it, the CDN serves the latest release, which may include breaking changes.
|
|
93
|
+
- Use one method per page. If a tag is loaded both ways, the first script to register it wins and the other is downloaded for nothing.
|
|
94
|
+
|
|
95
|
+
#### With a bundler (without React)
|
|
96
|
+
|
|
97
|
+
Install the package and **ECharts 6**, which is a peer dependency: the charts use your application's copy, so it isn't bundled twice when your app also uses ECharts.
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
npm install @circutor/charts echarts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Import each chart from `@circutor/charts/components/<tag>`; importing it registers the tag:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
import '@circutor/charts/components/itic-chart';
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Events (`pointClick`) are listened to from JavaScript:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
const chart = document.querySelector('itic-chart');
|
|
113
|
+
chart.addEventListener('pointClick', event => openWaveforms(event.detail.point));
|
|
114
|
+
```
|
|
115
|
+
|
|
62
116
|
#### From a React Application
|
|
63
117
|
|
|
64
118
|
1. **Install the package**
|
|
65
|
-
|
|
119
|
+
Install `@circutor/charts-react` and **ECharts 6** (a peer dependency of `@circutor/charts`, which is installed automatically):
|
|
66
120
|
|
|
67
121
|
```
|
|
68
|
-
npm install @circutor/charts-react
|
|
122
|
+
npm install @circutor/charts-react echarts
|
|
69
123
|
```
|
|
70
124
|
|
|
71
125
|
2. **Import the component**
|
|
@@ -75,42 +129,224 @@ npm install @circutor/charts-react
|
|
|
75
129
|
import { IticChart } from '@circutor/charts-react';
|
|
76
130
|
```
|
|
77
131
|
|
|
132
|
+
Each wrapper imports only its own Web Component, so your bundler only includes the charts you import. ECharts comes from your application, shared with any other ECharts chart.
|
|
133
|
+
|
|
78
134
|
3. **Use the component**
|
|
79
|
-
Now, you can use the chart in your application like any other React component.
|
|
135
|
+
Now, you can use the chart in your application like any other React component. Pass the data, the user's language and time zone:
|
|
80
136
|
|
|
81
|
-
```
|
|
137
|
+
```tsx
|
|
82
138
|
<IticChart
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
locale="es"
|
|
140
|
+
timeZone="Europe/Madrid"
|
|
141
|
+
groups={[
|
|
142
|
+
{
|
|
143
|
+
phase: "AN,BN,CN",
|
|
144
|
+
assetName: "Cuadro general",
|
|
145
|
+
points: [
|
|
146
|
+
{
|
|
147
|
+
duration: 230,
|
|
148
|
+
voltage: 93.46,
|
|
149
|
+
ts: "2024-06-26T20:23:45.220000+02:00",
|
|
150
|
+
eventType: "VOLTAGE_DIP",
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
phase: "BN",
|
|
156
|
+
assetName: "Cuadro general",
|
|
157
|
+
points: [
|
|
158
|
+
{
|
|
159
|
+
duration: 20,
|
|
160
|
+
voltage: 0.4000000000000057,
|
|
161
|
+
ts: "2025-01-26T23:04:34.840000+01:00",
|
|
162
|
+
eventType: "POWER_INTERRUPT",
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
]}
|
|
167
|
+
onPointClick={({ detail }) => openWaveforms(detail.point)}
|
|
168
|
+
/>
|
|
108
169
|
```
|
|
109
170
|
|
|
110
|
-
|
|
171
|
+
`@circutor/charts-react` expects `react` and `react-dom` 18 or 19 to be installed in your application.
|
|
172
|
+
|
|
173
|
+
### ITIC chart options
|
|
174
|
+
|
|
175
|
+
The ITIC chart only takes data, plus the language and time zone. The chart decides what is shown and how: the tooltip, the translations, the axis names, the accessible name, and each phase's name, color and order. Every prop is data or a string, so the chart is the same in plain HTML and React.
|
|
176
|
+
|
|
177
|
+
| Property (React prop) | Attribute | Type | Default | Description |
|
|
178
|
+
|---|---|---|---|---|
|
|
179
|
+
| `groups` | `groups` | `ITICChartMarks[] \| string` | – | Point groups (see [Data](#data)). As an attribute, a JSON string. |
|
|
180
|
+
| `locale` | `locale` | `string` | `'en'` | Language of the texts, event types, axes, `aria-label`, translated phases, dates and numbers. Only the language is used (`es-ES` → `es`); anything other than `ca`, `de`, `en`, `es`, `fr` or `pt` falls back to `en`. |
|
|
181
|
+
| `timeZone` | `time-zone` | `string` (IANA) | The browser's | Time zone of the dates in the tooltip, e.g. `Europe/Madrid`. An invalid value uses the browser's and logs a `console.error`. |
|
|
182
|
+
|
|
183
|
+
| Event (React prop) | `detail` | Description |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `pointClick` (`onPointClick`) | `{ point, group }` | A clickable point was clicked. `point` and `group` are the objects you passed in `groups`, with all their fields. |
|
|
186
|
+
|
|
187
|
+
| CSS custom property | Default | Description |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `--itic-chart-background` | `transparent` | Background behind the whole chart. |
|
|
190
|
+
|
|
191
|
+
#### Data
|
|
192
|
+
|
|
193
|
+
Each group holds the events of one phase of an asset:
|
|
194
|
+
|
|
195
|
+
| Group field | Type | Description |
|
|
196
|
+
|---|---|---|
|
|
197
|
+
| `phase` | `string` | Phase code (`AN`, `AB,BC,CA`, `ALL`, `NONE`…). Sets the group's name, color and order (see [Phases](#phases)). |
|
|
198
|
+
| `assetName` | `string`, optional | Asset name, shown in the tooltip. |
|
|
199
|
+
| `points` | `ITICPoint[]` | The voltage events. |
|
|
200
|
+
|
|
201
|
+
| Point field | Type | Description |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| `duration` | `number` | Duration, in ms. |
|
|
204
|
+
| `voltage` | `number` | Voltage, in % of the nominal voltage. |
|
|
205
|
+
| `ts` | `string` | Date of the event, ISO 8601. |
|
|
206
|
+
| `clickable` | `boolean`, optional | `false` hides the pointer cursor and emits no `pointClick`. Defaults to `true`. |
|
|
207
|
+
| `eventType` | `string`, optional | Event type code from the backend (see [Event types](#event-types)), translated in the tooltip. |
|
|
208
|
+
| `status` | `string`, optional | Status code from the backend, shown as is. |
|
|
209
|
+
| `min` / `max` | `number`, optional | Minimum and maximum voltage, in V. |
|
|
210
|
+
|
|
211
|
+
The axes have fixed ranges: duration from 1 to 100,000 ms (logarithmic) and voltage from 0 to 200%. **Points outside them aren't drawn** (e.g. a duration below 1 ms or a voltage above 200%).
|
|
212
|
+
|
|
213
|
+
#### Tooltip
|
|
214
|
+
|
|
215
|
+
The tooltip shows these rows, in this order, in the chart's `locale`. Rows without a value are left out, and every value is escaped, so data can't inject HTML.
|
|
216
|
+
|
|
217
|
+
| Row (`en`) | Value | Left out when |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| Asset | `assetName` | missing or empty |
|
|
220
|
+
| Date | `ts` with milliseconds, in `timeZone` (e.g. `Jun 26, 20:23:45.220`, `26 jun, 20:23:45,220`) | never; an invalid date is shown as is |
|
|
221
|
+
| Event | translated `eventType`; unknown codes as is | missing or empty |
|
|
222
|
+
| Duration | e.g. `1,500 ms` (`1500 ms` in `es`) | never |
|
|
223
|
+
| Voltage | rounded to 1 decimal, e.g. `93.5%` (`93,5 %` in `es`) | never |
|
|
224
|
+
| Status | `status` as is | missing or empty |
|
|
225
|
+
| Phase | phase name; `-` for `NONE` | never |
|
|
226
|
+
| Min / Max | 2 decimals, e.g. `207.12 V` | missing or `0` |
|
|
227
|
+
|
|
228
|
+
Numbers use the separators of each language, also in the axis labels: in `es` the duration axis reads `1000`, `10.000`, `100.000` (Spanish doesn't group 4-digit numbers).
|
|
229
|
+
|
|
230
|
+
The tooltip is added to `document.body`, not inside the chart, so containers with `overflow: hidden` don't clip it. Its styles are inline, so it looks the same.
|
|
231
|
+
|
|
232
|
+
#### Phases
|
|
233
|
+
|
|
234
|
+
The chart names, colors and sorts the groups from their `phase` code, so every app draws the same phases the same way:
|
|
235
|
+
|
|
236
|
+
| Code | Name | Color |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `AN`, `AB` | L1 | `#a67c52` |
|
|
239
|
+
| `BN`, `BC` | L2 | `#20262C` |
|
|
240
|
+
| `CN`, `CA` | L3 | `#B9BDC0` |
|
|
241
|
+
| `AN,BN,CN`, `AB,BC,CA` | L1,L2,L3 | `#00B388` |
|
|
242
|
+
| `ALL` | Translated: All, Todas, Totes, Alle, Toutes | `#4C5CC5` |
|
|
243
|
+
| `A`, `B`, `C` | L1, L2, L3 | ECharts palette |
|
|
244
|
+
| `AN,BN`, `AN,CN`, `BN,CN`, `AB,BC`, `AB,CA`, `BC,CA` | L1,L2 · L1,L3 · L2,L3 | ECharts palette |
|
|
245
|
+
| `NONE` | No name | ECharts palette |
|
|
246
|
+
| Any other | The code as is | ECharts palette |
|
|
247
|
+
|
|
248
|
+
- Groups are sorted by name (`L1`, `L1,L2,L3`, `L2`, `L3`), then by code, whatever order they come in, with `NONE` and then `ALL` last. Groups with the same code keep their order.
|
|
249
|
+
- Phase-neutral and phase-phase codes share names and colors: `AN` and `AB` in the same chart are two "L1" groups you can't tell apart, and one legend item toggles both.
|
|
250
|
+
- `NONE` groups have no name, so they don't appear in the legend (their points are drawn) and their tooltip shows `-` as phase.
|
|
251
|
+
- Phases without a fixed color take the next one of the ECharts palette, so the same code may get different colors in different charts.
|
|
252
|
+
|
|
253
|
+
#### Event types
|
|
254
|
+
|
|
255
|
+
`eventType` codes with a translation (in `ca`, `de`, `en`, `es`, `fr` and `pt`). Any other code is shown as is.
|
|
256
|
+
|
|
257
|
+
| Code | `en` | `es` |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| `VOLTAGE_DIP` | Voltage dip | Hueco de tensión |
|
|
260
|
+
| `VOLTAGE_SWELL` | Voltage swell | Aumento de tensión |
|
|
261
|
+
| `POWER_INTERRUPT` | Power interruption | Interrupción |
|
|
262
|
+
| `VOLTAGE_TRANSIENT` | Voltage transient | Transitorio de voltaje |
|
|
263
|
+
| `VOLTAGE_VARIATION` | Voltage variation | Variación de voltaje |
|
|
264
|
+
| `OVER_VOLTAGE` | Overvoltage | Sobretensión |
|
|
265
|
+
| `SUB_VOLTAGE` | Subvoltage | Subtensión |
|
|
266
|
+
|
|
267
|
+
#### Clickable points
|
|
268
|
+
|
|
269
|
+
Every point is clickable by default: it shows a pointer cursor and emits `pointClick`. Set `clickable: false` on a point to turn both off, e.g. for events without waveforms. Clicks on the ITIC curve or on non-clickable points emit nothing.
|
|
270
|
+
|
|
271
|
+
#### Your own data in points and groups
|
|
272
|
+
|
|
273
|
+
Points and groups accept any extra field (e.g. `waveforms`). The chart doesn't read or validate them; it passes them back in `pointClick`. Cast them to your own types there:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { IticChart, type ITICChartMarks, type ITICPoint } from '@circutor/charts-react';
|
|
277
|
+
|
|
278
|
+
// Use `extends` (or `&`) so your types are assignable to the chart's
|
|
279
|
+
interface EventPoint extends ITICPoint {
|
|
280
|
+
waveforms: Waveform[];
|
|
281
|
+
}
|
|
282
|
+
interface AssetGroup extends ITICChartMarks {
|
|
283
|
+
points: EventPoint[];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
<IticChart
|
|
287
|
+
groups={groups}
|
|
288
|
+
locale={locale}
|
|
289
|
+
timeZone={timeZone}
|
|
290
|
+
onPointClick={({ detail }) => openWaveforms(detail.point as EventPoint, detail.group as AssetGroup)}
|
|
291
|
+
/>;
|
|
292
|
+
```
|
|
111
293
|
|
|
112
294
|
### Size and data updates
|
|
113
295
|
|
|
114
|
-
- The chart takes the full width of its container and is `400px` high by default.
|
|
115
|
-
|
|
116
|
-
|
|
296
|
+
- The chart takes the full width of its container and is `400px` high by default. Any CSS rule on `itic-chart` in your page wins over that default, e.g. `itic-chart { height: 300px; }`, or, to grow with a flex container:
|
|
297
|
+
```css
|
|
298
|
+
.card { display: flex; flex-direction: column; }
|
|
299
|
+
.card itic-chart { flex: 1; min-height: 400px; }
|
|
300
|
+
```
|
|
301
|
+
The chart redraws automatically whenever its size changes.
|
|
302
|
+
- Updating `groups` (a new array from JS/React or a new JSON string in the attribute), `locale` or `timeZone` redraws the chart; groups that are no longer present are removed.
|
|
303
|
+
|
|
304
|
+
### Accessibility
|
|
305
|
+
|
|
306
|
+
The chart is drawn on a canvas, so the element gets `role="img"` (unless you set another `role`) and a translated `aria-label` ("ITIC chart", "Curva ITIC"…) that follows `locale`. Set your own `aria-label` to describe it better; the chart then leaves it alone:
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
<IticChart groups={groups} locale="es" aria-label="Curva ITIC de los eventos de tensión del cuadro general" />
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Next.js (App Router)
|
|
313
|
+
|
|
314
|
+
- The React wrappers are client components (`'use client'`). A Server Component can render `<IticChart>` with serializable props (`groups`, `locale`, `timeZone`, `aria-label`), but `onPointClick` is a function: pass it from your own `'use client'` component.
|
|
315
|
+
- Server-side rendering works without `next/dynamic` or `ssr: false`: importing the wrappers doesn't touch the DOM, the server renders an empty `<itic-chart>` and the chart draws in the browser after hydration, without hydration warnings.
|
|
316
|
+
|
|
317
|
+
### Testing with Vitest and jsdom
|
|
318
|
+
|
|
319
|
+
jsdom has no canvas, so ECharts can't draw there and logs `getContext()` errors. Mock the wrappers in a setup file (`setupFiles` in your Vitest config), so every test gets a plain element instead:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
// vitest.setup.tsx
|
|
323
|
+
import { vi } from 'vitest';
|
|
324
|
+
import type { ITICChartMarks, ITICPointClickDetail } from '@circutor/charts-react';
|
|
325
|
+
|
|
326
|
+
vi.mock('@circutor/charts-react', () => ({
|
|
327
|
+
// One button per point, so tests can find points and click them. `locale` and `timeZone` are ignored.
|
|
328
|
+
IticChart: ({ groups = [], onPointClick, 'aria-label': ariaLabel = 'ITIC chart' }: {
|
|
329
|
+
groups?: ITICChartMarks[];
|
|
330
|
+
locale?: string;
|
|
331
|
+
timeZone?: string;
|
|
332
|
+
onPointClick?: (event: CustomEvent<ITICPointClickDetail>) => void;
|
|
333
|
+
'aria-label'?: string;
|
|
334
|
+
}) => (
|
|
335
|
+
<div role="img" aria-label={ariaLabel} data-testid="itic-chart">
|
|
336
|
+
{groups.flatMap(group =>
|
|
337
|
+
group.points.map((point, index) => (
|
|
338
|
+
<button
|
|
339
|
+
key={`${group.phase}-${index}`}
|
|
340
|
+
disabled={point.clickable === false}
|
|
341
|
+
onClick={() => onPointClick?.(new CustomEvent('pointClick', { detail: { point, group } }))}
|
|
342
|
+
>
|
|
343
|
+
{group.phase} {point.ts}
|
|
344
|
+
</button>
|
|
345
|
+
)),
|
|
346
|
+
)}
|
|
347
|
+
</div>
|
|
348
|
+
),
|
|
349
|
+
}));
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Then `fireEvent.click(screen.getByText('AN 2024-06-26T20:23:45.220000+02:00'))` calls your `onPointClick` with the original point.
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
function t(t,e,n){const o="undefined"!=typeof HTMLElement?HTMLElement.prototype:null;for(;t&&t!==o;){const o=Object.getOwnPropertyDescriptor(t,e);if(o&&(!n||o.get))return o;t=Object.getPrototypeOf(t)}}var e,n=(e,n)=>{var o;Object.entries(null!=(o=n.o.t)?o:{}).map((([o,[l]])=>{if(31&l||32&l){const l=e[o],i=t(Object.getPrototypeOf(e),o,!0)||Object.getOwnPropertyDescriptor(e,o);i&&Object.defineProperty(e,o,{get(){return i.get.call(this)},set(t){i.set.call(this,t)},configurable:!0,enumerable:!0}),n.l.has(o)?e[o]=n.l.get(o):void 0!==l&&(e[o]=l)}}))},o=t=>{if(t.__stencil__getHostRef)return t.__stencil__getHostRef()},l=(t,e)=>{e&&(t.__stencil__getHostRef=()=>e,e.i=t,512&e.o.u&&n(t,e))},i=(t,e)=>(0,console.error)(t,e),s=new Map,r=new Map,c=new Map,u="undefined"!=typeof window?window:{},f={u:0,h:"",jmp:t=>t(),raf:t=>requestAnimationFrame(t),ael:(t,e,n,o)=>t.addEventListener(e,n,o),rel:(t,e,n,o)=>t.removeEventListener(e,n,o),ce:(t,e)=>new CustomEvent(t,e)},a=t=>Promise.resolve(t),d=(()=>{try{return!!u.document.adoptedStyleSheets&&(new CSSStyleSheet,"function"==typeof(new CSSStyleSheet).replaceSync)}catch(t){}return!1})(),h=!!d&&(()=>!!u.document&&Object.getOwnPropertyDescriptor(u.document.adoptedStyleSheets,"length").writable)(),p=!1,m=[],v=[],y=()=>{var t;return(null==(t=u.document)?void 0:t.hidden)?setTimeout(w,16):f.raf(w)},b=(t,e)=>n=>{t.push(n),p||(p=!0,e&&4&f.u?j(w):y())},$=t=>{for(let e=0;e<t.length;e++)try{t[e](performance.now())}catch(t){i(t)}t.length=0},w=()=>{$(m),$(v),(p=m.length>0)&&y()},j=t=>a().then(t),g=b(v,!0);function O(){const t=this.attachShadow({mode:"open"});void 0===e&&(e=null),e&&(h?t.adoptedStyleSheets.push(e):t.adoptedStyleSheets=[...t.adoptedStyleSheets,e])}function S(t){var e,n,o;return null!=(o=null==(n=null==(e=t.head)?void 0:e.querySelector('meta[name="csp-nonce"]'))?void 0:n.getAttribute("content"))?o:void 0}var k,M=new WeakMap,E=t=>"sc-"+t.p,C=t=>"object"==(t=typeof t)||"function"===t,T=(t,e,...n)=>{let o=null,l=null,s=!1,r=!1;const c=[],u=e=>{for(let n=0;n<e.length;n++)if(o=e[n],Array.isArray(o))u(o);else if(null!=o&&"boolean"!=typeof o){if(s="function"!=typeof t&&!C(o))o+="";else if("function"!=typeof t&&void 0===o.u){i("Invalid vNode child");continue}s&&r?c[c.length-1].m+=o:c.push(s?L(null,o):o),r=s}};if(u(n),e){e.key&&(l=e.key);{const t=e.className||e.class;t&&(e.class="object"!=typeof t?t:Object.keys(t).filter((e=>t[e])).join(" "))}}const f=L(t,null);return f.v=e,c.length>0&&(f.$=c),f.j=l,f},L=(t,e)=>({u:0,O:t,m:null!=e?e:null,S:null,$:null,v:null,j:null}),x={},D=t=>{if(!t)return;const e=Object.keys(t);if(0===e.length)return;let n=!1;for(const o of e){if(n)break;for(const e of t[o])if("string"==typeof e){n=!0;break}}if(!n)return t;const o={};for(const n of e)o[n]=t[n].map((t=>"string"==typeof t?{[t]:0}:t));return o},N=(t,e)=>null==t||C(t)?t:1&e?t+"":t,P=(t,e,n,o)=>{if(n!==o)if(e.toLowerCase(),"class"===e){const e=t.classList,l=H(n);let i=H(o);{let t=l.filter((t=>t&&!i.includes(t)));e.remove(...t),e.add(...i.filter((t=>t&&!l.includes(t))))}}else"key"===e||"ref"===e&&o&&Y(o,t)},R=/\s/,H=t=>("object"==typeof t&&t&&"baseVal"in t&&(t=t.baseVal),t&&"string"==typeof t?t.split(R):[]),U=(t,e)=>{const n=11===e.S.nodeType&&e.S.host?e.S.host:e.S,o=t&&t.v||{},l=e.v||{};for(const t of A(Object.keys(o)))t in l||P(n,t,o[t],void 0);for(const t of A(Object.keys(l)))P(n,t,o[t],l[t])};function A(t){return t.includes("ref")?[...t.filter((t=>"ref"!==t)),"ref"]:t}var W=[],V=[],q=(t,e,n)=>{const o=e.$[n];let l,i,s=0;if(!u.document)throw Error("You are trying to render a Stencil component in an environment that doesn't support the DOM.");if(l=o.S=u.document.createElement(o.O),U(null,o),o.$){const e="template"===o.O?l.content:l;for(s=0;s<o.$.length;++s)i=q(t,o,s),i&&e.appendChild(i)}return l["s-hn"]=k,l},z=(t,e,n,o,l,i)=>{let s,r=t;for(r.shadowRoot&&r.tagName===k&&(r=r.shadowRoot),"template"===n.O&&(r=r.content);l<=i;++l)o[l]&&(s=q(null,n,l),s&&(o[l].S=s,_(r,s,e)))},F=(t,e,n)=>{for(let o=e;o<=n;++o){const e=t[o];if(e){const t=e.S;I(e),t&&t.remove()}}},B=(t,e,n=!1)=>t.O===e.O&&(n?(n&&!t.j&&e.j&&(t.j=e.j),!0):t.j===e.j),G=(t,e,n=!1)=>{const o=e.S=t.S,l=t.$,i=e.$;U(t,e),null!==l&&null!==i?((t,e,n,o,l=!1)=>{let i,s,r=0,c=0,u=0,f=0,a=e.length-1,d=e[0],h=e[a],p=o.length-1,m=o[0],v=o[p];const y="template"===n.O?t.content:t;for(;r<=a&&c<=p;)if(null==d)d=e[++r];else if(null==h)h=e[--a];else if(null==m)m=o[++c];else if(null==v)v=o[--p];else if(B(d,m,l))G(d,m,l),d=e[++r],m=o[++c];else if(B(h,v,l))G(h,v,l),h=e[--a],v=o[--p];else if(B(d,v,l))G(d,v,l),_(y,d.S,h.S.nextSibling),d=e[++r],v=o[--p];else if(B(h,m,l))G(h,m,l),_(y,h.S,d.S),h=e[--a],m=o[++c];else{for(u=-1,f=r;f<=a;++f)if(e[f]&&null!==e[f].j&&e[f].j===m.j){u=f;break}u>=0?(s=e[u],s.O!==m.O?i=q(e&&e[c],n,c):(G(s,m,l),e[u]=void 0,i=s.S),m=o[++c]):(i=q(e&&e[c],n,c),m=o[++c]),i&&_(d.S.parentNode,i,d.S)}r>a?z(t,null==o[p+1]?null:o[p+1].S,n,o,c,p):c>p&&F(e,r,a)})(o,l,e,i,n):null!==i?z(o,null,e,i,0,i.length-1):!n&&null!==l&&F(l,0,l.length-1)},I=t=>{t.v&&t.v.ref&&W.push((()=>t.v.ref(null))),t.$&&t.$.map(I)},Y=(t,e)=>{V.push((()=>t(e)))},_=(t,e,n)=>null==t?void 0:t.insertBefore(e,n),J=(t,e)=>{if(e&&!t.k&&e["s-p"]){const n=e["s-p"].push(new Promise((o=>t.k=()=>{e["s-p"].splice(n-1,1),o()})))}},K=(t,e)=>{if(t.u|=16,4&t.u)return void(t.u|=512);J(t,t.M);const n=()=>Q(t,e);if(!e)return g(n);queueMicrotask((()=>{n()}))},Q=(t,e)=>{const n=t.$hostElement$,o=t.i;if(!o)throw Error(`Can't render component <${n.tagName.toLowerCase()} /> with invalid Stencil runtime! Make sure this imported component is compiled with a \`externalRuntime: true\` flag. For more information, please refer to https://stenciljs.com/docs/custom-elements#externalruntime`);let l;return e?(t.C.length&&t.C.forEach((t=>t(n))),l=lt(o,"componentWillLoad",void 0,n)):l=lt(o,"componentWillUpdate",void 0,n),l=X(l,(()=>lt(o,"componentWillRender",void 0,n))),X(l,(()=>tt(t,o,e)))},X=(t,e)=>Z(t)?t.then(e).catch((t=>{console.error(t),e()})):e(),Z=t=>t instanceof Promise||t&&t.then&&"function"==typeof t.then,tt=async(t,e,n)=>{var o;const l=t.$hostElement$,i=l["s-rc"];n&&(t=>{const e=t.o,n=t.$hostElement$,o=e.u,l=((t,e)=>{var n,o,l;const i=E(e),s=c.get(i);if(!u.document)return i;if(t=11===t.nodeType?t:u.document,s)if("string"==typeof s){let l,r=M.get(t=t.head||t);if(r||M.set(t,r=new Set),!r.has(i)){l=u.document.createElement("style"),l.textContent=s;const c=null!=(n=f.T)?n:S(u.document);if(null!=c&&l.setAttribute("nonce",c),!(1&e.u))if("HEAD"===t.nodeName){const e=t.querySelectorAll("link[rel=preconnect]"),n=e.length>0?e[e.length-1].nextSibling:t.querySelector("style");t.insertBefore(l,(null==n?void 0:n.parentNode)===t?n:null)}else if("host"in t)if(d){const e=new(null!=(o=t.defaultView)?o:t.ownerDocument.defaultView).CSSStyleSheet;e.replaceSync(s),h?t.adoptedStyleSheets.unshift(e):t.adoptedStyleSheets=[e,...t.adoptedStyleSheets]}else{const e=t.querySelector("style");e?e.textContent=s+e.textContent:t.prepend(l)}else t.append(l);1&e.u&&t.insertBefore(l,null),4&e.u&&(l.textContent+="slot-fb{display:contents}slot-fb[hidden]{display:none}"),r&&r.add(i)}}else{let e=M.get(t);if(e||M.set(t,e=new Set),!e.has(i)){const n=null!=(l=t.defaultView)?l:t.ownerDocument.defaultView;let o;if(s.constructor===n.CSSStyleSheet)o=s;else{o=new n.CSSStyleSheet;for(let t=0;t<s.cssRules.length;t++)o.insertRule(s.cssRules[t].cssText,t)}h?t.adoptedStyleSheets.push(o):t.adoptedStyleSheets=[...t.adoptedStyleSheets,o],e.add(i)}}return i})(n.shadowRoot?n.shadowRoot:n.getRootNode(),e);10&o&&(n["s-sc"]=l,n.classList.add(l+"-h"))})(t);et(t,e,l,n),i&&(i.map((t=>t())),l["s-rc"]=void 0);{const e=null!=(o=l["s-p"])?o:[],n=()=>nt(t);0===e.length?n():(Promise.all(e).then(n).catch(n),t.u|=4,e.length=0)}},et=(t,e,n,o)=>{try{e=e.render(),t.u&=-17,t.u|=2,((t,e,n=!1)=>{const o=t.$hostElement$,l=t.L||L(null,null),i=(t=>t&&t.O===x)(e)?e:T(null,null,e);if(k=o.tagName,n&&i.v)for(const t of Object.keys(i.v))o.hasAttribute(t)&&!["key","ref","style","class"].includes(t)&&(i.v[t]=o[t]);i.O=null,i.u|=4,t.L=i,i.S=l.S=o.shadowRoot||o,G(l,i,n),W.forEach((t=>t())),W.length=0,V.forEach((t=>t())),V.length=0})(t,e,o)}catch(e){i(e,t.$hostElement$)}return null},nt=t=>{const e=t.$hostElement$,n=t.i,o=t.M;lt(n,"componentDidRender",void 0,e),64&t.u?lt(n,"componentDidUpdate",void 0,e):(t.u|=64,it(e),lt(n,"componentDidLoad",void 0,e),t.D(e),o||ot()),t.k&&(t.k(),t.k=void 0),512&t.u&&j((()=>K(t,!1))),t.u&=-517},ot=()=>{j((()=>(t=>{const e=f.ce("appload",{detail:{namespace:"charts"}});return t.dispatchEvent(e),e})(u)))},lt=(t,e,n,o)=>{if(t&&t[e])try{return t[e](n)}catch(t){i(t,o)}},it=t=>t.classList.add("hydrated"),st=(t,e)=>o(t).l.get(e),rt=(t,e,n,l)=>{const s=o(t);if(!s)return;if(!s)throw Error(`Couldn't find host element for "${l.p}" as it is unknown to this Stencil runtime. This usually happens when integrating a 3rd party Stencil component with another Stencil component or application. Please reach out to the maintainers of the 3rd party Stencil component or report this on the Stencil Discord server (https://chat.stenciljs.com) or comment on this similar [GitHub issue](https://github.com/stenciljs/core/issues/5457).`);const r=s.$hostElement$,c=s.l.get(e),u=s.u,f=s.i;if(n=N(n,l.t[e][0]),!(8&u&&void 0!==c||n===c||Number.isNaN(c)&&Number.isNaN(n))){if(s.l.set(e,n),l.N){const t=l.N[e];t&&t.map((t=>{try{const[[o,l]]=Object.entries(t);(128&u||1&l)&&(f?f[o](n,c,e):s.C.push((()=>{s.i[o](n,c,e)})))}catch(t){i(t,r)}}))}if(2&u){if(f.componentShouldUpdate&&!1===f.componentShouldUpdate(n,c,e)&&!(16&u))return;16&u||K(s,!1)}}},ct=(e,n,l)=>{var i,s;const r=e.prototype;{e.watchers&&!n.N&&(n.N=D(e.watchers)),e.deserializers&&!n.P&&(n.P=e.deserializers),e.serializers&&!n.R&&(n.R=e.serializers);const c=Object.entries(null!=(i=n.t)?i:{});if(c.map((([e,[i]])=>{if(31&i||2&l&&32&i){const{get:s,set:c}=t(r,e)||{};s&&(n.t[e][0]|=2048),c&&(n.t[e][0]|=4096),(1&l||!s)&&Object.defineProperty(r,e,{get(){{if(!(2048&n.t[e][0]))return st(this,e);const t=o(this);return t?t.i?t.i[e]:st(this,e):r[e]}},configurable:!0,enumerable:!0}),Object.defineProperty(r,e,{set(t){const s=o(this);if(s){if(c)return void 0===(32&i?this[e]:s.$hostElement$[e])&&s.l.get(e)&&(t=s.l.get(e)),c.call(this,N(t,i)),void rt(this,e,t=32&i?this[e]:s.$hostElement$[e],n);{if(!(1&l&&4096&n.t[e][0]))return void rt(this,e,t,n);const o=N(t,i);if(s.i){const t=s.i[e];!s.l.get(e)&&t&&s.l.set(e,t),s.i[e]=o,rt(this,e,s.i[e],n)}else s.l.set(e,o)}}}})}})),1&l){const t=new Map;r.attributeChangedCallback=function(e,l,i){f.jmp((()=>{var s;const u=t.get(e),f=o(this);if(this.hasOwnProperty(u)&&(i=this[u],delete this[u]),r.hasOwnProperty(u)&&"number"==typeof this[u]&&this[u]==i)return;if(null==u){const t=null==f?void 0:f.u;if(f&&t&&!(8&t)&&i!==l){const o=f.i,r=null==(s=n.N)?void 0:s[e];null==r||r.forEach((n=>{const[[s,r]]=Object.entries(n);null!=o[s]&&(128&t||1&r)&&o[s].call(o,i,l,e)}))}return}const a=c.find((([t])=>t===u)),d=4&(a?a[1][0]:0),h=d&&null===i&&void 0===this[u];d&&(i=null!==i&&"false"!==i);const p=Object.getOwnPropertyDescriptor(r,u);h||i==this[u]||p.get&&!p.set||(this[u]=i)}))},e.observedAttributes=Array.from(new Set([...Object.keys(null!=(s=n.N)?s:{}),...c.filter((([t,e])=>31&e[0])).map((([e,n])=>{const o=n[1]||e;return t.set(o,e),o}))]))}}return e},ut=async(t,e,n)=>{var o;let l;try{if(!(32&e.u)){if(e.u|=32,e.u&=-1025,n.H){const c=((t,e)=>{var n;const o=t.p.replace(/-/g,"_"),l=t.H;if(!l)return;const c=s.get(l);if(c)return c[o];const u=null!=(n=r.get(l))?n:0,f=[u>0?"s-retry="+u:"",""].filter(Boolean).join("&");
|
|
2
|
-
/*!__STENCIL_STATIC_IMPORT_SWITCH__*/
|
|
3
|
-
return import(`./${l}.entry.js${f?"?"+f:""}`).then((t=>(r.delete(l),s.set(l,t),t[o])),(t=>{r.set(l,u+1),i(t,e.$hostElement$)}))})(n,e);if(c&&"then"in c){const t=()=>{};l=await c,t()}else l=c;if(!l)throw e.u&=-33,e.U=(null!=(o=e.U)?o:0)+1,e.U<3&&(e.u|=1024),Error(`Constructor for "${n.p}#${e.A}" was not found`);l.isProxied||(n.N=D(l.watchers),n.R=l.serializers,n.P=l.deserializers,ct(l,n,2),l.isProxied=!0);const u=()=>{};e.u|=8;try{new l(e)}catch(e){i(e,t)}e.u&=-9,((t,e)=>{var n;const o=t.i;if(o)for(const[l,[i]]of Object.entries(null!=(n=e.t)?n:{}))if(4096&i&&t.l.has(l)){const e=t.l.get(l);o[l]!==e&&(o[l]=e)}})(e,n),e.u|=128,u(),ft(e.i,t)}else l=t.constructor,customElements.whenDefined(t.localName).then((()=>e.u|=128));if(l&&l.style){let t;"string"==typeof l.style&&(t=l.style);const e=E(n);if(!c.has(e)){const o=()=>{};((t,e,n)=>{let o=c.get(t);d&&n?(o=o||new CSSStyleSheet,"string"==typeof o?o=e:o.replaceSync(e)):o=e,c.set(t,o)})(e,t,!!(1&n.u)),o()}}}const u=e.M,f=()=>K(e,!0);u&&u["s-rc"]?u["s-rc"].push(f):f()}catch(n){i(n,t),e.k&&(e.k(),e.k=void 0),!e.D||1024&e.u||e.D(t)}},ft=(t,e)=>{lt(t,"connectedCallback",void 0,e)},at=(t,e)=>{lt(t,"disconnectedCallback",void 0,e||t)},dt=(t,e={})=>{var n;if(!u.document)return void console.warn("Stencil: No document found. Skipping bootstrapping lazy components.");const l=[],i=e.exclude||[],s=u.customElements,r=u.document.head,c=r.querySelector("meta[charset]"),a=u.document.createElement("style"),d=[];let h,p=!0;if(Object.assign(f,e),f.h=new URL(e.resourcesUrl||"./",u.document.baseURI).href,t.map((t=>{t[1].map((e=>{var n,r;const c={u:e[0],p:e[1],t:e[2],W:e[3]};c.t=e[2],c.N=D(e[4]),c.R=null!=(n=e[5])?n:{},c.P=null!=(r=e[6])?r:{};const u=c.p,a=class extends HTMLElement{"s-p";"s-rc";hasRegisteredEventListeners=!1;constructor(t){if(super(t),((t,e)=>{const n={u:0,$hostElement$:t,o:e,l:new Map,V:new Map};n.q=new Promise((t=>n.D=t)),t["s-p"]=[],t["s-rc"]=[],n.C=[];const o=n;t.__stencil__getHostRef=()=>o})(t=this,c),1&c.u)if(t.shadowRoot){if("open"!==t.shadowRoot.mode)throw Error(`Unable to re-use existing shadow root for ${c.p}! Mode is set to ${t.shadowRoot.mode} but Stencil only supports open shadow roots.`)}else O.call(t,c)}connectedCallback(){o(this)&&(this.hasRegisteredEventListeners||(this.hasRegisteredEventListeners=!0),h&&(clearTimeout(h),h=null),p?d.push(this):f.jmp((()=>(t=>{if(!(1&f.u)){const e=o(t);if(!e)return;const n=e.o,l=()=>{};if(1&e.u)(null==e?void 0:e.i)?ft(e.i,t):1024&e.u?setTimeout((()=>ut(t,e,n)),1e3):(null==e?void 0:e.q)&&e.q.then((()=>ft(e.i,t)));else{e.u|=1;{let n=t;for(;n=n.parentNode||n.host;)if(n["s-p"]){J(e,e.M=n);break}}n.t&&Object.entries(n.t).map((([e,[n]])=>{if(31&n&&Object.prototype.hasOwnProperty.call(t,e)){const n=t[e];delete t[e],t[e]=n}})),ut(t,e,n)}l()}})(this))))}disconnectedCallback(){f.jmp((()=>(async t=>{if(!(1&f.u)){const e=o(t);(null==e?void 0:e.i)?at(e.i,t):(null==e?void 0:e.q)&&e.q.then((()=>at(e.i,t)))}M.has(t)&&M.delete(t),t.shadowRoot&&M.has(t.shadowRoot)&&M.delete(t.shadowRoot)})(this))),j((()=>{var t;const e=o(this);if(!e)return;const n=d.findIndex((t=>t===this));n>-1&&d.splice(n,1),(null==(t=null==e?void 0:e.L)?void 0:t.S)instanceof Node&&!e.L.S.isConnected&&delete e.L.S}))}componentOnReady(){var t;return null==(t=o(this))?void 0:t.q}};c.H=t[0],i.includes(u)||s.get(u)||(l.push(u),s.define(u,ct(a,c,1)))}))})),l.length>0&&(a.textContent+=l.sort()+"{visibility:hidden}.hydrated{visibility:inherit}",a.innerHTML.length)){a.setAttribute("data-styles","");const t=null!=(n=f.T)?n:S(u.document);null!=t&&a.setAttribute("nonce",t),r.insertBefore(a,c?c.nextSibling:r.firstChild)}p=!1,d.length?d.map((t=>t.connectedCallback())):f.jmp((()=>h=setTimeout(ot,30)))},ht=t=>f.T=t;export{dt as b,T as h,a as p,l as r,ht as s}
|