@c2n/chart 0.0.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/area-chart.js +29 -0
  4. package/dist/bar-chart.js +65 -0
  5. package/dist/chart-adapter.js +0 -0
  6. package/dist/chart-base-C4-1TyKq.js +666 -0
  7. package/dist/chart-base.js +2 -0
  8. package/dist/chart-data.js +286 -0
  9. package/dist/chart-series-BnpHO3lm.js +83 -0
  10. package/dist/chart-series.js +2 -0
  11. package/dist/chart-theme.js +151 -0
  12. package/dist/chart-types.js +8 -0
  13. package/dist/chart.js +13 -0
  14. package/dist/echarts-chart-base-LogCQN10.js +228 -0
  15. package/dist/echarts-chart-base.js +2 -0
  16. package/dist/line-chart.js +31 -0
  17. package/dist/pie-chart.js +100 -0
  18. package/dist/sparkline.js +79 -0
  19. package/dist/uplot-chart-base-BWr0zJE2.js +253 -0
  20. package/dist/uplot-chart-base.js +2 -0
  21. package/dist/uplot-paths-ChKohvIX.js +95 -0
  22. package/package.json +146 -0
  23. package/react.d.ts +34 -0
  24. package/react.js +3 -0
  25. package/types/src/area-chart.d.ts +36 -0
  26. package/types/src/area-chart.d.ts.map +1 -0
  27. package/types/src/bar-chart.d.ts +46 -0
  28. package/types/src/bar-chart.d.ts.map +1 -0
  29. package/types/src/chart-adapter.d.ts +67 -0
  30. package/types/src/chart-adapter.d.ts.map +1 -0
  31. package/types/src/chart-base.d.ts +265 -0
  32. package/types/src/chart-base.d.ts.map +1 -0
  33. package/types/src/chart-data.d.ts +43 -0
  34. package/types/src/chart-data.d.ts.map +1 -0
  35. package/types/src/chart-series.d.ts +51 -0
  36. package/types/src/chart-series.d.ts.map +1 -0
  37. package/types/src/chart-theme.d.ts +64 -0
  38. package/types/src/chart-theme.d.ts.map +1 -0
  39. package/types/src/chart-types.d.ts +162 -0
  40. package/types/src/chart-types.d.ts.map +1 -0
  41. package/types/src/chart.d.ts +27 -0
  42. package/types/src/chart.d.ts.map +1 -0
  43. package/types/src/echarts-chart-base.d.ts +28 -0
  44. package/types/src/echarts-chart-base.d.ts.map +1 -0
  45. package/types/src/engines/echarts-adapter.d.ts +17 -0
  46. package/types/src/engines/echarts-adapter.d.ts.map +1 -0
  47. package/types/src/engines/echarts-loader.d.ts +16 -0
  48. package/types/src/engines/echarts-loader.d.ts.map +1 -0
  49. package/types/src/engines/uplot-adapter.d.ts +4 -0
  50. package/types/src/engines/uplot-adapter.d.ts.map +1 -0
  51. package/types/src/engines/uplot-loader.d.ts +20 -0
  52. package/types/src/engines/uplot-loader.d.ts.map +1 -0
  53. package/types/src/engines/uplot-paths.d.ts +25 -0
  54. package/types/src/engines/uplot-paths.d.ts.map +1 -0
  55. package/types/src/line-chart.d.ts +40 -0
  56. package/types/src/line-chart.d.ts.map +1 -0
  57. package/types/src/pie-chart.d.ts +59 -0
  58. package/types/src/pie-chart.d.ts.map +1 -0
  59. package/types/src/sparkline.d.ts +56 -0
  60. package/types/src/sparkline.d.ts.map +1 -0
  61. package/types/src/uplot-chart-base.d.ts +50 -0
  62. package/types/src/uplot-chart-base.d.ts.map +1 -0
  63. package/vue.d.ts +134 -0
  64. package/vue.js +3 -0
@@ -0,0 +1,228 @@
1
+ import { t as ChartBase } from "./chart-base-C4-1TyKq.js";
2
+ import { i as __decorate } from "./chart-series-BnpHO3lm.js";
3
+ import { property } from "lit/decorators.js";
4
+ //#region src/engines/echarts-loader.ts
5
+ var LOADERS = {
6
+ pie: () => import("echarts/charts").then((m) => [m.PieChart]),
7
+ gauge: () => import("echarts/charts").then((m) => [m.GaugeChart]),
8
+ scatter: () => import("echarts/charts").then((m) => [m.ScatterChart]),
9
+ heatmap: () => import("echarts/charts").then((m) => [m.HeatmapChart]),
10
+ candlestick: () => import("echarts/charts").then((m) => [m.CandlestickChart]),
11
+ bar: () => import("echarts/charts").then((m) => [m.BarChart]),
12
+ line: () => import("echarts/charts").then((m) => [m.LineChart]),
13
+ grid: () => import("echarts/components").then((m) => [m.GridComponent]),
14
+ legend: () => import("echarts/components").then((m) => [m.LegendComponent]),
15
+ tooltip: () => import("echarts/components").then((m) => [m.TooltipComponent]),
16
+ visualMap: () => import("echarts/components").then((m) => [m.VisualMapComponent]),
17
+ dataZoom: () => import("echarts/components").then((m) => [m.DataZoomComponent])
18
+ };
19
+ var corePending;
20
+ /** Registrations already applied, so a second chart of the same type registers nothing. */
21
+ var registered = /* @__PURE__ */ new Set();
22
+ /** Registrations in flight, so two charts mounting together do not both load the same chunk. */
23
+ var inflight = /* @__PURE__ */ new Map();
24
+ /**
25
+ * Loads `echarts/core`, registers `features` and the chosen renderer, and returns the core namespace.
26
+ * Registration is idempotent and deduped, so calling this per element is cheap after the first.
27
+ */
28
+ async function loadECharts(features, renderer) {
29
+ if (!corePending) corePending = import("echarts/core");
30
+ const core = await corePending;
31
+ const keys = [...features, `renderer:${renderer}`];
32
+ await Promise.all(keys.map((key) => {
33
+ if (registered.has(key)) return void 0;
34
+ let task = inflight.get(key);
35
+ if (!task) {
36
+ task = (key.startsWith("renderer:") ? import("echarts/renderers").then((m) => [renderer === "svg" ? m.SVGRenderer : m.CanvasRenderer]) : LOADERS[key]()).then((modules) => {
37
+ core.use(modules);
38
+ registered.add(key);
39
+ }).finally(() => inflight.delete(key));
40
+ inflight.set(key, task);
41
+ }
42
+ return task;
43
+ }));
44
+ return core;
45
+ }
46
+ //#endregion
47
+ //#region src/engines/echarts-adapter.ts
48
+ async function createEchartsAdapter(features, renderer) {
49
+ const echarts = await loadECharts(features, renderer);
50
+ let instance;
51
+ let events;
52
+ let hidden = /* @__PURE__ */ new Set();
53
+ /** Merges the projected data into whatever series the last option build produced. */
54
+ const withData = (options, data) => ({
55
+ ...options,
56
+ series: (options.series ?? []).map((series, index) => ({
57
+ ...series,
58
+ data: data[index] ?? []
59
+ }))
60
+ });
61
+ const adapter = {
62
+ engine: "echarts",
63
+ async create(host, options, data, handlers) {
64
+ events = handlers;
65
+ instance = echarts.init(host, void 0, {
66
+ renderer,
67
+ useDirtyRect: true
68
+ });
69
+ instance.setOption(withData(options, data), { notMerge: true });
70
+ instance.on("click", (params) => {
71
+ const point = params;
72
+ events?.click({
73
+ index: point.dataIndex ?? 0,
74
+ seriesIndex: point.seriesIndex ?? 0
75
+ });
76
+ });
77
+ instance.on("mouseover", (params) => {
78
+ const point = params;
79
+ events?.hover({
80
+ index: point.dataIndex ?? 0,
81
+ seriesIndex: point.seriesIndex ?? 0,
82
+ px: point.event?.offsetX ?? 0,
83
+ py: point.event?.offsetY ?? 0
84
+ });
85
+ });
86
+ instance.on("mouseout", () => events?.hover(null));
87
+ instance.on("dataZoom", () => {
88
+ const zoom = (instance?.getOption())?.dataZoom?.[0];
89
+ if (zoom?.startValue !== void 0 && zoom.endValue !== void 0) events?.rangeChange({
90
+ min: zoom.startValue,
91
+ max: zoom.endValue
92
+ });
93
+ });
94
+ },
95
+ /** Series data only: ECharts merges it without re-evaluating axes, colours or layout. */
96
+ setData(data) {
97
+ instance?.setOption({ series: data.map((series) => ({ data: series })) }, {
98
+ notMerge: false,
99
+ lazyUpdate: true,
100
+ silent: true
101
+ });
102
+ },
103
+ /**
104
+ * `replace` is required when the series set shrinks — a merge would leave the removed series on screen
105
+ * forever. A merge otherwise keeps the current data and zoom, which is what a theme change wants.
106
+ */
107
+ setOptions(options, mode) {
108
+ instance?.setOption(options, {
109
+ notMerge: mode === "replace",
110
+ lazyUpdate: true
111
+ });
112
+ if (mode === "replace") for (const index of hidden) adapter.setSeriesVisibility(index, false);
113
+ },
114
+ /**
115
+ * Goes through the legend action, which is why `LegendComponent` is registered even though the
116
+ * built-in legend is hidden — it is the only public way to toggle a series.
117
+ */
118
+ setSeriesVisibility(index, visible) {
119
+ const next = new Set(hidden);
120
+ if (visible) next.delete(index);
121
+ else next.add(index);
122
+ hidden = next;
123
+ const name = (instance?.getOption())?.series?.[index]?.name;
124
+ if (!name) return;
125
+ instance?.dispatchAction({
126
+ type: visible ? "legendSelect" : "legendUnSelect",
127
+ name
128
+ });
129
+ },
130
+ /** The same action: ECharts' legend selects by name, and a pie's names are its slices, not its series. */
131
+ setDatumVisibility(name, visible) {
132
+ instance?.dispatchAction({
133
+ type: visible ? "legendSelect" : "legendUnSelect",
134
+ name
135
+ });
136
+ },
137
+ resize(width, height) {
138
+ if (width > 0 && height > 0) instance?.resize({
139
+ width,
140
+ height
141
+ });
142
+ },
143
+ /** ECharts leaks its global resize and event handlers without an explicit dispose. */
144
+ destroy() {
145
+ instance?.dispose();
146
+ instance = void 0;
147
+ events = void 0;
148
+ }
149
+ };
150
+ return adapter;
151
+ }
152
+ //#endregion
153
+ //#region src/echarts-chart-base.ts
154
+ /**
155
+ * The ECharts half of the hierarchy. A concrete chart declares the engine modules it needs and how one
156
+ * series is configured; everything else — theme, text styles, the disabled built-in tooltip and legend —
157
+ * is settled here.
158
+ *
159
+ * Defines no tag and is never registered.
160
+ */
161
+ var EchartsChartBase = class extends ChartBase {
162
+ constructor(..._args) {
163
+ super(..._args);
164
+ this.engineName = "echarts";
165
+ this.renderer = "canvas";
166
+ }
167
+ /** Grid and axes for a cartesian chart. The pie and gauge charts override this to contribute neither. */
168
+ coordinateSystem(context) {
169
+ const { theme } = context;
170
+ const axisLine = { lineStyle: { color: theme.gridColor } };
171
+ const axisLabel = {
172
+ color: theme.axisColor,
173
+ fontSize: theme.fontSize
174
+ };
175
+ return {
176
+ grid: {
177
+ left: 48,
178
+ right: 16,
179
+ top: 16,
180
+ bottom: 32,
181
+ containLabel: false
182
+ },
183
+ xAxis: {
184
+ type: this.xType === "time" ? "time" : this.xType === "category" ? "category" : "value",
185
+ axisLine,
186
+ axisLabel,
187
+ data: context.labels
188
+ },
189
+ yAxis: {
190
+ type: "value",
191
+ axisLine,
192
+ axisLabel,
193
+ splitLine: { lineStyle: { color: theme.gridColor } }
194
+ }
195
+ };
196
+ }
197
+ createAdapter() {
198
+ return createEchartsAdapter([...this.features, "legend"], this.renderer);
199
+ }
200
+ projectData(frame, context) {
201
+ return this.frameBuilder.echartsView(frame, this.dataShape(context));
202
+ }
203
+ /** Cartesian charts want `[x, y]` pairs; the labelled ones want `{ name, value }`. */
204
+ dataShape(_context) {
205
+ return "pairs";
206
+ }
207
+ buildOptions(context) {
208
+ const { theme, series } = context;
209
+ return {
210
+ animation: this.animation === "auto",
211
+ color: theme.palette,
212
+ textStyle: {
213
+ fontFamily: theme.fontFamily === "inherit" ? void 0 : theme.fontFamily,
214
+ fontSize: theme.fontSize,
215
+ color: theme.color
216
+ },
217
+ legend: { show: false },
218
+ ...this.coordinateSystem(context),
219
+ series: series.map((item, index) => ({
220
+ name: item.label ?? item.field,
221
+ ...this.seriesOption(index, context)
222
+ }))
223
+ };
224
+ }
225
+ };
226
+ __decorate([property({ type: String })], EchartsChartBase.prototype, "renderer", void 0);
227
+ //#endregion
228
+ export { EchartsChartBase as t };
@@ -0,0 +1,2 @@
1
+ import { t as EchartsChartBase } from "./echarts-chart-base-LogCQN10.js";
2
+ export { EchartsChartBase };
@@ -0,0 +1,31 @@
1
+ import { i as __decorate } from "./chart-series-BnpHO3lm.js";
2
+ import { t as UplotChartBase } from "./uplot-chart-base-BWr0zJE2.js";
3
+ import { n as linePaths } from "./uplot-paths-ChKohvIX.js";
4
+ import { property } from "lit/decorators.js";
5
+ import { customElement } from "@c2n/core/element-helper.js";
6
+ //#region src/line-chart.ts
7
+ var LineChart = class LineChart extends UplotChartBase {
8
+ constructor(..._args) {
9
+ super(..._args);
10
+ this.curve = "linear";
11
+ this.points = "auto";
12
+ }
13
+ seriesStyle(series, index, context) {
14
+ const { theme } = context;
15
+ return {
16
+ stroke: this.colorOf(series, index, theme),
17
+ width: series.lineWidth ?? theme.lineWidth,
18
+ paths: linePaths(this.curve),
19
+ spanGaps: series.spanGaps ?? false,
20
+ points: {
21
+ show: this.points === "none" ? false : this.points === "always" ? true : void 0,
22
+ size: theme.pointRadius * 2
23
+ }
24
+ };
25
+ }
26
+ };
27
+ __decorate([property({ type: String })], LineChart.prototype, "curve", void 0);
28
+ __decorate([property({ type: String })], LineChart.prototype, "points", void 0);
29
+ LineChart = __decorate([customElement("c2-line-chart")], LineChart);
30
+ //#endregion
31
+ export { LineChart };
@@ -0,0 +1,100 @@
1
+ import { i as __decorate } from "./chart-series-BnpHO3lm.js";
2
+ import { t as EchartsChartBase } from "./echarts-chart-base-LogCQN10.js";
3
+ import { property, state } from "lit/decorators.js";
4
+ import { customElement } from "@c2n/core/element-helper.js";
5
+ //#region src/pie-chart.ts
6
+ var PieChart = class PieChart extends EchartsChartBase {
7
+ constructor() {
8
+ super();
9
+ this.features = ["pie"];
10
+ this.innerRadius = 0;
11
+ this.outerRadius = .75;
12
+ this.startAngle = 90;
13
+ this.labels = "none";
14
+ this.sort = "none";
15
+ this.hiddenSlices = /* @__PURE__ */ new Set();
16
+ this.tooltip = "item";
17
+ this.legend = "end";
18
+ }
19
+ /** A pie has no grid and no axes at all: contributing them would draw an empty cartesian frame. */
20
+ coordinateSystem() {
21
+ return {};
22
+ }
23
+ /**
24
+ * A pie's legend is its slices, not its series: there is only ever one series, so the inherited legend
25
+ * would render a single entry ("Revenue") above a four-slice donut.
26
+ */
27
+ legendItems() {
28
+ const labels = this.frame?.labels;
29
+ if (!labels || labels.length === 0) return super.legendItems();
30
+ const series = this.resolvedSeries[0] ?? { field: "" };
31
+ const theme = this.themeController.theme;
32
+ return labels.map((label, index) => ({
33
+ label,
34
+ color: theme.palette[index % theme.palette.length],
35
+ visible: !this.hiddenSlices.has(label),
36
+ toggle: () => this.setSliceVisible(label, this.hiddenSlices.has(label)),
37
+ series,
38
+ index
39
+ }));
40
+ }
41
+ /** Shows or hides one slice, as the legend does. ECharts selects by name, which is the slice's label. */
42
+ setSliceVisible(label, visible) {
43
+ const next = new Set(this.hiddenSlices);
44
+ if (visible) next.delete(label);
45
+ else next.add(label);
46
+ this.hiddenSlices = next;
47
+ this.adapter?.setDatumVisibility?.(label, visible);
48
+ }
49
+ dataShape() {
50
+ return "named";
51
+ }
52
+ seriesOption(_index, context) {
53
+ const { theme } = context;
54
+ return {
55
+ type: "pie",
56
+ radius: [`${this.innerRadius * 100}%`, `${this.outerRadius * 100}%`],
57
+ startAngle: this.startAngle,
58
+ label: {
59
+ show: this.labels !== "none",
60
+ position: this.labels === "inside" ? "inside" : "outside",
61
+ color: this.labels === "inside" ? theme.surface : theme.color,
62
+ fontSize: theme.fontSize
63
+ },
64
+ labelLine: { show: this.labels === "outside" },
65
+ itemStyle: sliceBorder(this, theme.surface),
66
+ sort: this.sort === "none" ? void 0 : this.sort === "asc" ? "ascending" : "descending"
67
+ };
68
+ }
69
+ };
70
+ __decorate([property({
71
+ type: Number,
72
+ attribute: "inner-radius"
73
+ })], PieChart.prototype, "innerRadius", void 0);
74
+ __decorate([property({
75
+ type: Number,
76
+ attribute: "outer-radius"
77
+ })], PieChart.prototype, "outerRadius", void 0);
78
+ __decorate([property({
79
+ type: Number,
80
+ attribute: "start-angle"
81
+ })], PieChart.prototype, "startAngle", void 0);
82
+ __decorate([property({ type: String })], PieChart.prototype, "labels", void 0);
83
+ __decorate([property({ type: String })], PieChart.prototype, "sort", void 0);
84
+ __decorate([state()], PieChart.prototype, "hiddenSlices", void 0);
85
+ PieChart = __decorate([customElement("c2-pie-chart")], PieChart);
86
+ /** Reads `--c2-chart__slice--border` off the host as ECharts' `{ borderColor, borderWidth }`. */
87
+ function sliceBorder(host, fallbackColor) {
88
+ const value = getComputedStyle(host).getPropertyValue("--c2-chart__slice--border").trim();
89
+ if (!value || value === "none") return {
90
+ borderColor: "transparent",
91
+ borderWidth: 0
92
+ };
93
+ const width = parseFloat(value);
94
+ return {
95
+ borderColor: value.replace(/^\s*[\d.]+[a-z%]*\s*/i, "").replace(/^(solid|dashed|dotted|double|groove|ridge|inset|outset)\s*/i, "") || fallbackColor,
96
+ borderWidth: Number.isFinite(width) ? width : 2
97
+ };
98
+ }
99
+ //#endregion
100
+ export { PieChart };
@@ -0,0 +1,79 @@
1
+ import { n as chart_default } from "./chart-base-C4-1TyKq.js";
2
+ import { i as __decorate } from "./chart-series-BnpHO3lm.js";
3
+ import { t as UplotChartBase } from "./uplot-chart-base-BWr0zJE2.js";
4
+ import { n as linePaths, r as withAlpha } from "./uplot-paths-ChKohvIX.js";
5
+ import { property } from "lit/decorators.js";
6
+ import { customElement } from "@c2n/core/element-helper.js";
7
+ import { css, unsafeCSS } from "lit";
8
+ //#region src/sparkline.ts
9
+ var Sparkline = class Sparkline extends UplotChartBase {
10
+ static {
11
+ this.styles = [unsafeCSS(chart_default), css`
12
+ :host {
13
+ /* Redefined, not merely defaulted: the base sets these variables, so a fallback would never apply.
14
+ An author rule on the element still wins, because it beats :host. */
15
+ --c2-chart--width: 120px;
16
+ --c2-chart--height: 32px;
17
+ --c2-chart--padding: 0;
18
+ display: inline-flex;
19
+ border: none;
20
+ background: none;
21
+ }
22
+ `];
23
+ }
24
+ constructor() {
25
+ super();
26
+ this.type = "line";
27
+ this.tone = "neutral";
28
+ this.axes = "none";
29
+ this.grid = "none";
30
+ this.cursor = "none";
31
+ this.legend = "none";
32
+ this.tooltip = "none";
33
+ }
34
+ seriesStyle(series, index, context) {
35
+ const color = this.resolveTone(series, index, context);
36
+ return {
37
+ stroke: color,
38
+ width: series.lineWidth ?? context.theme.lineWidth,
39
+ paths: linePaths("smooth"),
40
+ points: { show: false },
41
+ ...this.type === "area" ? { fill: withAlpha(color, .18) } : {}
42
+ };
43
+ }
44
+ /**
45
+ * Strips every remaining pixel of chrome, so the line fills the whole box.
46
+ *
47
+ * The axes are left alone on purpose: `this.axes = 'none'` already builds them with `show: false`, which
48
+ * is what makes uPlot skip both the axis element and its gutter. Handing it `axes: []` would do the
49
+ * opposite — uPlot fills a short array back up to two axes with its own defaults, which are *visible* —
50
+ * and a 120x32 sparkline would spend 52px of its width on a y axis it never asked for.
51
+ */
52
+ decorateOptions(options, _context) {
53
+ return {
54
+ ...options,
55
+ padding: [
56
+ 2,
57
+ 2,
58
+ 2,
59
+ 2
60
+ ]
61
+ };
62
+ }
63
+ resolveTone(series, index, context) {
64
+ if (this.tone === "neutral") return this.colorOf(series, index, context.theme);
65
+ if (this.tone === "positive") return context.theme.positive;
66
+ if (this.tone === "negative") return context.theme.negative;
67
+ const column = this.frame?.columns[index];
68
+ if (!column || !this.frame || this.frame.length < 2) return this.colorOf(series, index, context.theme);
69
+ const first = Number(column[0]);
70
+ const last = Number(column[this.frame.length - 1]);
71
+ if (!Number.isFinite(first) || !Number.isFinite(last) || first === last) return this.colorOf(series, index, context.theme);
72
+ return last > first ? context.theme.positive : context.theme.negative;
73
+ }
74
+ };
75
+ __decorate([property({ type: String })], Sparkline.prototype, "type", void 0);
76
+ __decorate([property({ type: String })], Sparkline.prototype, "tone", void 0);
77
+ Sparkline = __decorate([customElement("c2-sparkline")], Sparkline);
78
+ //#endregion
79
+ export { Sparkline };
@@ -0,0 +1,253 @@
1
+ import { t as ChartBase } from "./chart-base-C4-1TyKq.js";
2
+ import { i as __decorate } from "./chart-series-BnpHO3lm.js";
3
+ import { property } from "lit/decorators.js";
4
+ //#region src/engines/uplot-loader.ts
5
+ var pending;
6
+ var loaded;
7
+ /**
8
+ * Loads uPlot once per page. Ten sparklines mounting at the same time share one request and one module
9
+ * evaluation, because every caller awaits the same promise.
10
+ */
11
+ function loadUplot() {
12
+ if (!pending) pending = import("uplot").then((module) => {
13
+ loaded = module.default;
14
+ return loaded;
15
+ });
16
+ return pending;
17
+ }
18
+ /**
19
+ * The module, for callers that cannot await it — the path builders, which are read while an option object
20
+ * is being built. `undefined` until the load resolves; every chart builds its options from inside an
21
+ * adapter that already awaited {@link loadUplot}, so by then this is set.
22
+ */
23
+ function loadedUplot() {
24
+ return loaded;
25
+ }
26
+ //#endregion
27
+ //#region src/engines/uplot-adapter.ts
28
+ async function createUplotAdapter() {
29
+ const UPlot = await loadUplot();
30
+ let instance;
31
+ let container;
32
+ let events;
33
+ let data = [[]];
34
+ /** Set while we are rebuilding, so the scale hook does not report our own restore as a user zoom. */
35
+ let restoring = false;
36
+ /** Adds our hooks to whatever the element built, without the element knowing uPlot's hook shape. */
37
+ const withHooks = (options) => ({
38
+ ...options,
39
+ hooks: {
40
+ ...options.hooks,
41
+ setCursor: [(self) => {
42
+ const index = self.cursor.idx;
43
+ if (index === null || index === void 0) {
44
+ events?.hover(null);
45
+ return;
46
+ }
47
+ events?.hover({
48
+ index,
49
+ seriesIndex: Math.max(1, self.cursor.idxs?.findIndex((value) => value !== null && value !== void 0) ?? 1) - 1,
50
+ px: self.cursor.left ?? 0,
51
+ py: self.cursor.top ?? 0
52
+ });
53
+ }],
54
+ setSelect: [(self) => {
55
+ if (self.select.width <= 0) return;
56
+ const min = self.posToVal(self.select.left, "x");
57
+ const max = self.posToVal(self.select.left + self.select.width, "x");
58
+ events?.rangeChange({
59
+ min,
60
+ max
61
+ });
62
+ }],
63
+ setScale: [(self, key) => {
64
+ if (restoring || key !== "x") return;
65
+ const { min, max } = self.scales.x;
66
+ if (min !== void 0 && max !== void 0) events?.rangeChange({
67
+ min,
68
+ max
69
+ });
70
+ }]
71
+ }
72
+ });
73
+ const build = (options, next) => {
74
+ if (!container) return;
75
+ instance = new UPlot(withHooks(options), next, container);
76
+ };
77
+ return {
78
+ engine: "uplot",
79
+ async create(host, options, initial, handlers) {
80
+ container = host;
81
+ events = handlers;
82
+ data = initial;
83
+ build(options, initial);
84
+ },
85
+ /** The hot path, and the reason uPlot is here: a redraw and nothing else. */
86
+ setData(next) {
87
+ data = next;
88
+ instance?.setData(next, true);
89
+ },
90
+ /** Destroy and rebuild, preserving the x window. See the file header for why there is no alternative. */
91
+ setOptions(options, _mode) {
92
+ if (!instance || !container) return;
93
+ const { min, max } = instance.scales.x;
94
+ instance.destroy();
95
+ build(options, data);
96
+ if (min !== void 0 && max !== void 0 && instance) {
97
+ restoring = true;
98
+ instance.setScale("x", {
99
+ min,
100
+ max
101
+ });
102
+ restoring = false;
103
+ }
104
+ },
105
+ setSeriesVisibility(index, visible) {
106
+ instance?.setSeries(index + 1, { show: visible });
107
+ },
108
+ resize(width, height) {
109
+ if (width > 0 && height > 0) instance?.setSize({
110
+ width,
111
+ height
112
+ });
113
+ },
114
+ destroy() {
115
+ instance?.destroy();
116
+ instance = void 0;
117
+ container = void 0;
118
+ events = void 0;
119
+ }
120
+ };
121
+ }
122
+ //#endregion
123
+ //#region src/uplot-chart-base.ts
124
+ var DAY = 864e5;
125
+ var YEAR = 365 * DAY;
126
+ /** uPlot scale key for the secondary y axis, which `c2-chart-series[axis=right]` draws against. */
127
+ var RIGHT_SCALE = "y2";
128
+ /**
129
+ * The uPlot half of the hierarchy: the cartesian presentation shared by the line, area, bar and sparkline
130
+ * charts, and the option object built from it. A concrete chart supplies only {@link seriesStyle}, which
131
+ * is what makes a new uPlot chart type roughly ten lines.
132
+ *
133
+ * Defines no tag and is never registered.
134
+ *
135
+ * @cssproperty {color} [--c2-chart__axis-line--color=#e4e4e7] - Colour of the axis rules uPlot draws at the plot edges.
136
+ */
137
+ var UplotChartBase = class extends ChartBase {
138
+ constructor(..._args) {
139
+ super(..._args);
140
+ this.engineName = "uplot";
141
+ this.grid = "y";
142
+ this.axes = "both";
143
+ this.zoom = false;
144
+ this.cursor = "x";
145
+ }
146
+ /** Last chance to adjust the finished option object; the sparkline strips its chrome here. */
147
+ decorateOptions(options, _context) {
148
+ return options;
149
+ }
150
+ createAdapter() {
151
+ return createUplotAdapter();
152
+ }
153
+ projectData(frame) {
154
+ return this.frameBuilder.uplotView(frame);
155
+ }
156
+ buildOptions(context) {
157
+ const { theme, series, width, height } = context;
158
+ const showX = this.axes === "both" || this.axes === "x";
159
+ const showY = this.axes === "both" || this.axes === "y";
160
+ const hasRight = series.some((item) => item.axis === "right");
161
+ const axis = (show, isX, scale) => ({
162
+ ...scale ? {
163
+ scale,
164
+ side: 1
165
+ } : {},
166
+ show,
167
+ stroke: theme.axisColor,
168
+ font: `${theme.fontSize}px ${theme.fontFamily === "inherit" ? "system-ui, sans-serif" : theme.fontFamily}`,
169
+ ticks: {
170
+ show,
171
+ stroke: theme.gridColor,
172
+ width: 1
173
+ },
174
+ grid: scale === RIGHT_SCALE ? { show: false } : {
175
+ show: isX ? this.grid === "x" || this.grid === "both" : this.grid === "y" || this.grid === "both",
176
+ stroke: theme.gridColor,
177
+ width: 1
178
+ },
179
+ values: isX ? (_self, splits) => splits.map((value) => this.formatAxisX(value)) : (_self, splits) => splits.map((value) => this.formatValue(value))
180
+ });
181
+ const options = {
182
+ width: Math.max(1, Math.floor(width)),
183
+ height: Math.max(1, Math.floor(height)),
184
+ legend: { show: false },
185
+ cursor: this.cursor === "none" ? { show: false } : {
186
+ show: true,
187
+ x: true,
188
+ y: false,
189
+ drag: {
190
+ x: this.zoom,
191
+ y: false,
192
+ setScale: this.zoom
193
+ }
194
+ },
195
+ scales: {
196
+ x: { time: false },
197
+ y: { range: this.yRange() },
198
+ ...hasRight ? { [RIGHT_SCALE]: { range: this.yRange() } } : {}
199
+ },
200
+ axes: [
201
+ axis(showX, true),
202
+ axis(showY, false),
203
+ ...hasRight ? [axis(showY, false, RIGHT_SCALE)] : []
204
+ ],
205
+ series: [{}, ...series.map((item, index) => ({
206
+ label: item.label ?? item.field,
207
+ show: !context.hidden.has(index),
208
+ scale: item.axis === "right" ? RIGHT_SCALE : void 0,
209
+ ...this.seriesStyle(item, index, context)
210
+ }))]
211
+ };
212
+ return this.decorateOptions(options, context);
213
+ }
214
+ /** A fixed y range when either bound is set, otherwise uPlot's own auto-ranging. */
215
+ yRange() {
216
+ if (this.yMin === void 0 && this.yMax === void 0) return void 0;
217
+ return [this.yMin ?? null, this.yMax ?? null];
218
+ }
219
+ /**
220
+ * Axis tick labels are terser than the tooltip's. The unit comes from the span the chart covers, because a
221
+ * fixed date format repeats itself once the engine picks sub-day increments: an hour of samples would label
222
+ * every tick "Jan 1".
223
+ */
224
+ formatAxisX(value) {
225
+ if (this.xType !== "time") return this.formatValue(value);
226
+ const span = this.xSpan();
227
+ const options = span > 0 && span < DAY ? {
228
+ hour: "numeric",
229
+ minute: "2-digit"
230
+ } : span < YEAR ? {
231
+ month: "short",
232
+ day: "numeric"
233
+ } : {
234
+ month: "short",
235
+ year: "numeric"
236
+ };
237
+ return new Intl.DateTimeFormat(this.locale, options).format(new Date(value));
238
+ }
239
+ };
240
+ __decorate([property({ type: String })], UplotChartBase.prototype, "grid", void 0);
241
+ __decorate([property({ type: String })], UplotChartBase.prototype, "axes", void 0);
242
+ __decorate([property({
243
+ type: Number,
244
+ attribute: "y-min"
245
+ })], UplotChartBase.prototype, "yMin", void 0);
246
+ __decorate([property({
247
+ type: Number,
248
+ attribute: "y-max"
249
+ })], UplotChartBase.prototype, "yMax", void 0);
250
+ __decorate([property({ type: Boolean })], UplotChartBase.prototype, "zoom", void 0);
251
+ __decorate([property({ type: String })], UplotChartBase.prototype, "cursor", void 0);
252
+ //#endregion
253
+ export { loadedUplot as n, UplotChartBase as t };
@@ -0,0 +1,2 @@
1
+ import { t as UplotChartBase } from "./uplot-chart-base-BWr0zJE2.js";
2
+ export { UplotChartBase };