@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,2 @@
1
+ import { t as ChartBase } from "./chart-base-C4-1TyKq.js";
2
+ export { ChartBase };
@@ -0,0 +1,286 @@
1
+ import { isChartFrame } from "./chart-types.js";
2
+ import { getFieldValue } from "@c2n/core/data-helper.js";
3
+ //#region src/chart-data.ts
4
+ /**
5
+ * Normalisation and projection: everything between "what the consumer handed us" and "what the engine
6
+ * wants", and nothing else. No colour, no axis, no label formatting — those are presentation and live in
7
+ * the elements.
8
+ *
9
+ * Two rules make the realtime path cheap:
10
+ *
11
+ * 1. Normalisation is keyed on the **identity** of the input, so re-assigning the same array never redoes
12
+ * it, and a 100 000-point dataset is never deep-compared.
13
+ * 2. Appending writes into spare capacity and bumps `frame.revision`, so every projection cache below
14
+ * invalidates together without anything being rebuilt eagerly.
15
+ */
16
+ /** Growth factor for the spare capacity an append writes into. */
17
+ var GROWTH = 1.5;
18
+ /** Smallest buffer we bother allocating. */
19
+ var MIN_CAPACITY = 16;
20
+ function toNumber(value) {
21
+ if (value === null || value === void 0 || value === "") return null;
22
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
23
+ if (value instanceof Date) return value.getTime();
24
+ const parsed = typeof value === "string" ? Date.parse(value) : NaN;
25
+ if (!Number.isNaN(parsed) && typeof value === "string" && /[-:TZ]/.test(value)) return parsed;
26
+ const coerced = Number(value);
27
+ return Number.isFinite(coerced) ? coerced : null;
28
+ }
29
+ /** True when every entry is a real number, which is what lets the column be a `Float64Array`. */
30
+ function isDense(values) {
31
+ for (let index = 0; index < values.length; index += 1) if (values[index] === null) return false;
32
+ return true;
33
+ }
34
+ /**
35
+ * Packs one column. Dense data becomes a `Float64Array` with spare capacity; anything with a hole stays a
36
+ * plain array, because both engines detect a gap with `== null` and `NaN` in a typed array would be read
37
+ * as a real value and wreck the scale range.
38
+ */
39
+ function packColumn(values, capacity) {
40
+ if (!isDense(values)) {
41
+ const column = values.slice();
42
+ column.length = capacity;
43
+ return column;
44
+ }
45
+ const column = new Float64Array(capacity);
46
+ for (let index = 0; index < values.length; index += 1) column[index] = values[index];
47
+ return column;
48
+ }
49
+ function capacityFor(length) {
50
+ return Math.max(MIN_CAPACITY, Math.ceil(length * GROWTH));
51
+ }
52
+ function readLength(column) {
53
+ return column.length;
54
+ }
55
+ /** Reads one value out of a column, normalising the two representations to `number | null`. */
56
+ function columnValue(column, index) {
57
+ const value = column[index];
58
+ return value === null || value === void 0 || Number.isNaN(value) ? null : value;
59
+ }
60
+ function growColumn(column, capacity) {
61
+ if (column instanceof Float64Array) {
62
+ const next = new Float64Array(capacity);
63
+ next.set(column);
64
+ return next;
65
+ }
66
+ const next = column.slice();
67
+ next.length = capacity;
68
+ return next;
69
+ }
70
+ /** A column that must now hold a `null` but is currently typed: widen it to a plain array. */
71
+ function widenColumn(column, length) {
72
+ if (!(column instanceof Float64Array)) return column;
73
+ const next = new Array(column.length);
74
+ for (let index = 0; index < length; index += 1) next[index] = column[index];
75
+ return next;
76
+ }
77
+ /**
78
+ * Builds and caches the normalised form of whatever a consumer assigned, and owns the projections each
79
+ * engine consumes. One instance per chart element.
80
+ */
81
+ var ChartFrameBuilder = class {
82
+ /** Keyed on the input reference: assigning the same array twice never re-reads it. */
83
+ #frames = /* @__PURE__ */ new WeakMap();
84
+ /** uPlot views, invalidated by `frame.revision`. */
85
+ #uplot = /* @__PURE__ */ new WeakMap();
86
+ /** ECharts views, invalidated by `frame.revision` and the requested shape. */
87
+ #echarts = /* @__PURE__ */ new WeakMap();
88
+ /**
89
+ * Normalises `input` into a {@link ChartFrame}. Returns the *same* frame for the same input reference
90
+ * and signature, so this is safe to call on every update.
91
+ */
92
+ build(input, context) {
93
+ if (input === void 0 || input === null) return void 0;
94
+ if (isChartFrame(input)) return input;
95
+ if (!Array.isArray(input) || input.length === 0) return {
96
+ x: new Float64Array(MIN_CAPACITY),
97
+ columns: [],
98
+ length: 0,
99
+ capacity: MIN_CAPACITY,
100
+ revision: 0
101
+ };
102
+ const cached = this.#frames.get(input);
103
+ if (cached && cached.signature === context.signature) return cached.frame;
104
+ const frame = this.#normalize(input, context);
105
+ this.#frames.set(input, {
106
+ frame,
107
+ signature: context.signature
108
+ });
109
+ return frame;
110
+ }
111
+ #normalize(input, context) {
112
+ const rows = input;
113
+ const first = rows[0];
114
+ if (typeof first === "number") {
115
+ const values = rows;
116
+ const capacity = capacityFor(values.length);
117
+ const x = new Float64Array(capacity);
118
+ for (let index = 0; index < values.length; index += 1) x[index] = index;
119
+ return {
120
+ x,
121
+ columns: [packColumn(values.map(toNumber), capacity)],
122
+ length: values.length,
123
+ capacity,
124
+ revision: 0
125
+ };
126
+ }
127
+ if (Array.isArray(first) || ArrayBuffer.isView(first)) {
128
+ const columns = rows;
129
+ const length = columns.length > 0 ? readLength(columns[0]) : 0;
130
+ const capacity = capacityFor(length);
131
+ const read = (source) => {
132
+ const values = new Array(length);
133
+ for (let index = 0; index < length; index += 1) values[index] = toNumber(source[index]);
134
+ return packColumn(values, capacity);
135
+ };
136
+ return {
137
+ x: read(columns[0]),
138
+ columns: columns.slice(1).map(read),
139
+ length,
140
+ capacity,
141
+ revision: 0
142
+ };
143
+ }
144
+ return this.#fromRows(rows, context);
145
+ }
146
+ #fromRows(rows, context) {
147
+ const length = rows.length;
148
+ const capacity = capacityFor(length);
149
+ const xValues = new Array(length);
150
+ const labels = [];
151
+ let hasLabels = false;
152
+ for (let index = 0; index < length; index += 1) {
153
+ const row = rows[index];
154
+ xValues[index] = context.xField ? toNumber(getFieldValue(row, context.xField)) : index;
155
+ if (context.labelField) {
156
+ const label = getFieldValue(row, context.labelField);
157
+ if (label !== void 0 && label !== null) {
158
+ labels[index] = String(label);
159
+ hasLabels = true;
160
+ }
161
+ }
162
+ }
163
+ for (let index = 0; index < length; index += 1) if (xValues[index] === null) xValues[index] = index;
164
+ const columns = (context.series.length > 0 ? context.series.map((series) => series.field) : inferFields(rows, context)).map((field) => {
165
+ const values = new Array(length);
166
+ for (let index = 0; index < length; index += 1) values[index] = toNumber(getFieldValue(rows[index], field));
167
+ return packColumn(values, capacity);
168
+ });
169
+ const frame = {
170
+ x: packColumn(xValues, capacity),
171
+ columns,
172
+ length,
173
+ capacity,
174
+ revision: 0
175
+ };
176
+ if (hasLabels) frame.labels = labels;
177
+ return frame;
178
+ }
179
+ /**
180
+ * Appends one x and one value per series in place. Grows geometrically, and drops the oldest points once
181
+ * `maxPoints` is reached, so a streaming chart holds a bounded ring rather than an unbounded array.
182
+ */
183
+ push(frame, x, values, maxPoints) {
184
+ if (frame.columns.length === 0 && values.length > 0) frame.columns = values.map(() => new Float64Array(frame.capacity));
185
+ if (frame.length >= frame.capacity) {
186
+ const capacity = capacityFor(frame.length + 1);
187
+ frame.x = growColumn(frame.x, capacity);
188
+ frame.columns = frame.columns.map((column) => growColumn(column, capacity));
189
+ frame.capacity = capacity;
190
+ }
191
+ const at = frame.length;
192
+ writeAt(frame, "x", at, x);
193
+ for (let index = 0; index < frame.columns.length; index += 1) {
194
+ const value = values[index] ?? null;
195
+ if (value === null) frame.columns[index] = widenColumn(frame.columns[index], at);
196
+ frame.columns[index][at] = value;
197
+ }
198
+ frame.length += 1;
199
+ if (maxPoints > 0 && frame.length > maxPoints) this.#trim(frame, frame.length - maxPoints);
200
+ frame.revision += 1;
201
+ }
202
+ /** Drops `count` points off the front, keeping the buffers and their capacity. */
203
+ #trim(frame, count) {
204
+ const remaining = frame.length - count;
205
+ shiftLeft(frame.x, count, remaining);
206
+ for (const column of frame.columns) shiftLeft(column, count, remaining);
207
+ if (frame.labels) frame.labels.splice(0, count);
208
+ frame.length = remaining;
209
+ }
210
+ /**
211
+ * uPlot's view: `[xs, ys…]` sliced to `length`. A typed column becomes a `subarray`, which is a view
212
+ * over the same buffer and costs nothing.
213
+ */
214
+ uplotView(frame) {
215
+ const hit = this.#uplot.get(frame);
216
+ if (hit && hit.revision === frame.revision && hit.length === frame.length) return hit.view;
217
+ const view = [sliceColumn(frame.x, frame.length), ...frame.columns.map((column) => sliceColumn(column, frame.length))];
218
+ this.#uplot.set(frame, {
219
+ revision: frame.revision,
220
+ length: frame.length,
221
+ view
222
+ });
223
+ return view;
224
+ }
225
+ /**
226
+ * ECharts' view, one array per series. `pairs` is `[[x, y], …]` for the cartesian charts, `named` is
227
+ * `[{ name, value }, …]` for the ones whose marks are labelled rather than positioned (pie, gauge), and
228
+ * `values` is a bare value list.
229
+ */
230
+ echartsView(frame, shape) {
231
+ let perShape = this.#echarts.get(frame);
232
+ if (!perShape) {
233
+ perShape = /* @__PURE__ */ new Map();
234
+ this.#echarts.set(frame, perShape);
235
+ }
236
+ const hit = perShape.get(shape);
237
+ if (hit && hit.revision === frame.revision && hit.length === frame.length) return hit.view;
238
+ const view = frame.columns.map((column) => {
239
+ const out = new Array(frame.length);
240
+ for (let index = 0; index < frame.length; index += 1) {
241
+ const value = columnValue(column, index);
242
+ if (shape === "pairs") out[index] = [columnValue(frame.x, index), value];
243
+ else if (shape === "named") out[index] = {
244
+ name: frame.labels?.[index] ?? String(index),
245
+ value
246
+ };
247
+ else out[index] = value;
248
+ }
249
+ return out;
250
+ });
251
+ perShape.set(shape, {
252
+ revision: frame.revision,
253
+ length: frame.length,
254
+ view
255
+ });
256
+ return view;
257
+ }
258
+ };
259
+ /** Writes into `x` through the same widening rule the y columns use. */
260
+ function writeAt(frame, key, index, value) {
261
+ if (value === null) frame[key] = widenColumn(frame[key], index);
262
+ frame[key][index] = value;
263
+ }
264
+ function shiftLeft(column, count, remaining) {
265
+ if (column instanceof Float64Array) {
266
+ column.copyWithin(0, count, count + remaining);
267
+ return;
268
+ }
269
+ for (let index = 0; index < remaining; index += 1) column[index] = column[index + count];
270
+ }
271
+ function sliceColumn(column, length) {
272
+ if (column instanceof Float64Array) return column.subarray(0, length);
273
+ return column.slice(0, length);
274
+ }
275
+ /**
276
+ * Every numeric key of the first row except the ones already spoken for by the x and label fields.
277
+ *
278
+ * Only a fallback: the element normally resolves the series first and passes them in. Plotting the x field
279
+ * as a series is the bug this guards against.
280
+ */
281
+ function inferFields(rows, context) {
282
+ const row = rows[0] ?? {};
283
+ return Object.keys(row).filter((key) => typeof row[key] === "number" && key !== context.xField && key !== context.labelField);
284
+ }
285
+ //#endregion
286
+ export { ChartFrameBuilder, columnValue };
@@ -0,0 +1,83 @@
1
+ import { property } from "lit/decorators.js";
2
+ import { customElement } from "@c2n/core/element-helper.js";
3
+ import { LitElement, css } from "lit";
4
+ //#region \0@oxc-project+runtime@0.148.0/helpers/esm/decorate.js
5
+ function __decorate(decorators, target, key, desc) {
6
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
8
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
9
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
10
+ }
11
+ //#endregion
12
+ //#region src/chart-series.ts
13
+ /** Fired at the parent chart whenever a series definition changes. */
14
+ var SERIES_CHANGE_EVENT = "c2-chart-series-change";
15
+ /** The tag, so a chart can match a definition by name rather than by class identity. */
16
+ var SERIES_TAG = "c2-chart-series";
17
+ var ChartSeries = class ChartSeries extends LitElement {
18
+ constructor(..._args) {
19
+ super(..._args);
20
+ this.field = "";
21
+ this.axis = "left";
22
+ this.spanGaps = false;
23
+ this.hidden = false;
24
+ }
25
+ static {
26
+ this.styles = css`
27
+ :host {
28
+ display: none;
29
+ }
30
+ `;
31
+ }
32
+ /** A plain snapshot of this definition, so the chart never holds a reference to the element. */
33
+ toConfig() {
34
+ return {
35
+ field: this.field,
36
+ label: this.label,
37
+ color: this.color,
38
+ lineWidth: this.lineWidth,
39
+ axis: this.axis,
40
+ spanGaps: this.spanGaps,
41
+ hidden: this.hidden,
42
+ format: this.format
43
+ };
44
+ }
45
+ connectedCallback() {
46
+ super.connectedCallback();
47
+ this.#notify();
48
+ }
49
+ disconnectedCallback() {
50
+ super.disconnectedCallback();
51
+ this.#notify();
52
+ }
53
+ updated(_changed) {
54
+ this.#notify();
55
+ }
56
+ /** Composed so it crosses the shadow boundary of a chart that wraps its slot; the chart stops it there. */
57
+ #notify() {
58
+ this.dispatchEvent(new CustomEvent(SERIES_CHANGE_EVENT, {
59
+ bubbles: true,
60
+ composed: true
61
+ }));
62
+ }
63
+ };
64
+ __decorate([property({ type: String })], ChartSeries.prototype, "field", void 0);
65
+ __decorate([property({ type: String })], ChartSeries.prototype, "label", void 0);
66
+ __decorate([property({ type: String })], ChartSeries.prototype, "color", void 0);
67
+ __decorate([property({
68
+ type: Number,
69
+ attribute: "line-width"
70
+ })], ChartSeries.prototype, "lineWidth", void 0);
71
+ __decorate([property({ type: String })], ChartSeries.prototype, "axis", void 0);
72
+ __decorate([property({
73
+ type: Boolean,
74
+ attribute: "span-gaps"
75
+ })], ChartSeries.prototype, "spanGaps", void 0);
76
+ __decorate([property({
77
+ type: Boolean,
78
+ reflect: true
79
+ })], ChartSeries.prototype, "hidden", void 0);
80
+ __decorate([property({ attribute: false })], ChartSeries.prototype, "format", void 0);
81
+ ChartSeries = __decorate([customElement("c2-chart-series")], ChartSeries);
82
+ //#endregion
83
+ export { __decorate as i, SERIES_CHANGE_EVENT as n, SERIES_TAG as r, ChartSeries as t };
@@ -0,0 +1,2 @@
1
+ import { n as SERIES_CHANGE_EVENT, r as SERIES_TAG, t as ChartSeries } from "./chart-series-BnpHO3lm.js";
2
+ export { ChartSeries, SERIES_CHANGE_EVENT, SERIES_TAG };
@@ -0,0 +1,151 @@
1
+ import { isServer } from "lit";
2
+ //#region src/chart-theme.ts
3
+ /**
4
+ * Turns the element's own CSS custom properties into plain values a canvas engine can use.
5
+ *
6
+ * This is the one place the package has to work around the fact that a chart is not DOM: `::part()` and
7
+ * `var()` never reach a canvas, so the theme has to be *read* and handed over as strings and numbers.
8
+ *
9
+ * Colours are read through hidden probe elements rather than `getPropertyValue`, because a custom
10
+ * property whose value is a `var()` chain or a `color-mix()` comes back from `getPropertyValue` as the
11
+ * author's literal text — which no engine can parse. The computed `color` of a probe is always a resolved
12
+ * `rgb(…)`. The probes live in the shadow root under `display: none`, so they cost no layout.
13
+ */
14
+ /** Number of series colours in the palette; matches `--c2-chart__series-1…8--color`. */
15
+ var PALETTE_SIZE = 8;
16
+ /**
17
+ * The colours the probe block exposes, in DOM order. `chart.scss` emits one `i:nth-child(n)` rule per
18
+ * entry, so this list and that loop must stay in step.
19
+ */
20
+ var PROBE_COLORS = [
21
+ "series-1",
22
+ "series-2",
23
+ "series-3",
24
+ "series-4",
25
+ "series-5",
26
+ "series-6",
27
+ "series-7",
28
+ "series-8",
29
+ "axis",
30
+ "grid",
31
+ "text",
32
+ "muted",
33
+ "tooltip-background",
34
+ "tooltip-text",
35
+ "crosshair",
36
+ "positive",
37
+ "negative",
38
+ "surface"
39
+ ];
40
+ var FALLBACK = {
41
+ palette: [
42
+ "#0265dc",
43
+ "#ea580c",
44
+ "#0f766e",
45
+ "#db2777",
46
+ "#a16207",
47
+ "#7c3aed",
48
+ "#0891b2",
49
+ "#52525b"
50
+ ],
51
+ color: "#18181b",
52
+ mutedColor: "#71717a",
53
+ axisColor: "#71717a",
54
+ gridColor: "#e4e4e7",
55
+ surface: "#ffffff",
56
+ tooltipBackground: "#18181b",
57
+ tooltipColor: "#fafafa",
58
+ crosshairColor: "#a1a1aa",
59
+ positive: "#16a34a",
60
+ negative: "#dc2626",
61
+ fontFamily: "inherit",
62
+ fontSize: 12,
63
+ lineWidth: 2,
64
+ pointRadius: 2.5
65
+ };
66
+ /**
67
+ * Resolves and caches the host's chart theme, and invalidates it whenever the page's colour scheme moves.
68
+ *
69
+ * Three independent triggers, because an app may use any of them: the `data-theme` / `class` attribute on
70
+ * `<html>` (what a site toggle sets), the OS preference, and the `c2n-theme-change` event the docs site
71
+ * happens to fire. None of them is required for the component to work.
72
+ */
73
+ var ChartThemeController = class {
74
+ #host;
75
+ #onChange;
76
+ #theme;
77
+ #observer;
78
+ #media;
79
+ constructor(host, onChange) {
80
+ this.#host = host;
81
+ this.#onChange = onChange;
82
+ host.addController(this);
83
+ }
84
+ /** The resolved theme, computed on first read after each invalidation. */
85
+ get theme() {
86
+ if (!this.#theme) this.#theme = this.#resolve();
87
+ return this.#theme;
88
+ }
89
+ /** Drops the cached theme and tells the host to rebuild its engine options. */
90
+ invalidate() {
91
+ this.#theme = void 0;
92
+ this.#onChange();
93
+ }
94
+ hostConnected() {
95
+ if (isServer) return;
96
+ window.addEventListener("c2n-theme-change", this.#handle);
97
+ if (typeof MutationObserver !== "undefined") {
98
+ if (!this.#observer) this.#observer = new MutationObserver(this.#handle);
99
+ this.#observer.observe(document.documentElement, {
100
+ attributes: true,
101
+ attributeFilter: ["data-theme", "class"]
102
+ });
103
+ }
104
+ if (typeof matchMedia !== "undefined") {
105
+ if (!this.#media) this.#media = matchMedia("(prefers-color-scheme: dark)");
106
+ this.#media.addEventListener("change", this.#handle);
107
+ }
108
+ }
109
+ hostDisconnected() {
110
+ if (isServer) return;
111
+ window.removeEventListener("c2n-theme-change", this.#handle);
112
+ this.#observer?.disconnect();
113
+ this.#media?.removeEventListener("change", this.#handle);
114
+ this.#theme = void 0;
115
+ }
116
+ #handle = () => this.invalidate();
117
+ #resolve() {
118
+ if (isServer || typeof getComputedStyle !== "function") return FALLBACK;
119
+ const style = getComputedStyle(this.#host);
120
+ const probes = this.#host.renderRoot?.querySelectorAll(".theme-probe > i");
121
+ if (!probes || probes.length < PROBE_COLORS.length) return FALLBACK;
122
+ const at = (name, fallback) => {
123
+ const index = PROBE_COLORS.indexOf(name);
124
+ const probe = probes[index];
125
+ return (probe ? getComputedStyle(probe).color : "") || fallback;
126
+ };
127
+ const scalar = (name, fallback) => {
128
+ const value = parseFloat(style.getPropertyValue(name));
129
+ return Number.isFinite(value) ? value : fallback;
130
+ };
131
+ return {
132
+ palette: PROBE_COLORS.slice(0, 8).map((name, index) => at(name, FALLBACK.palette[index])),
133
+ color: at("text", FALLBACK.color),
134
+ mutedColor: at("muted", FALLBACK.mutedColor),
135
+ axisColor: at("axis", FALLBACK.axisColor),
136
+ gridColor: at("grid", FALLBACK.gridColor),
137
+ surface: at("surface", FALLBACK.surface),
138
+ tooltipBackground: at("tooltip-background", FALLBACK.tooltipBackground),
139
+ tooltipColor: at("tooltip-text", FALLBACK.tooltipColor),
140
+ crosshairColor: at("crosshair", FALLBACK.crosshairColor),
141
+ positive: at("positive", FALLBACK.positive),
142
+ negative: at("negative", FALLBACK.negative),
143
+ fontFamily: style.getPropertyValue("--c2-chart--font-family").trim() || FALLBACK.fontFamily,
144
+ fontSize: scalar("--c2-chart--font-size", FALLBACK.fontSize),
145
+ lineWidth: scalar("--c2-chart__line--width", FALLBACK.lineWidth),
146
+ pointRadius: scalar("--c2-chart__point--radius", FALLBACK.pointRadius)
147
+ };
148
+ }
149
+ };
150
+ //#endregion
151
+ export { ChartThemeController, PALETTE_SIZE, PROBE_COLORS };
@@ -0,0 +1,8 @@
1
+ import { getFieldValue } from "@c2n/core/data-helper.js";
2
+ //#region src/chart-types.ts
3
+ /** Marks a value as a `ChartFrame` without an `instanceof` check surviving a bundler boundary. */
4
+ function isChartFrame(value) {
5
+ return typeof value === "object" && value !== null && "columns" in value && "length" in value && "revision" in value;
6
+ }
7
+ //#endregion
8
+ export { getFieldValue, isChartFrame };
package/dist/chart.js ADDED
@@ -0,0 +1,13 @@
1
+ import { t as ChartBase } from "./chart-base-C4-1TyKq.js";
2
+ import { isChartFrame } from "./chart-types.js";
3
+ import { ChartFrameBuilder, columnValue } from "./chart-data.js";
4
+ import { ChartThemeController, PALETTE_SIZE, PROBE_COLORS } from "./chart-theme.js";
5
+ import { n as SERIES_CHANGE_EVENT, t as ChartSeries } from "./chart-series-BnpHO3lm.js";
6
+ import { t as UplotChartBase } from "./uplot-chart-base-BWr0zJE2.js";
7
+ import { LineChart } from "./line-chart.js";
8
+ import { AreaChart } from "./area-chart.js";
9
+ import { BarChart } from "./bar-chart.js";
10
+ import { Sparkline } from "./sparkline.js";
11
+ import { t as EchartsChartBase } from "./echarts-chart-base-LogCQN10.js";
12
+ import { PieChart } from "./pie-chart.js";
13
+ export { AreaChart, BarChart, ChartBase, ChartFrameBuilder, ChartSeries, ChartThemeController, EchartsChartBase, LineChart, PALETTE_SIZE, PROBE_COLORS, PieChart, SERIES_CHANGE_EVENT, Sparkline, UplotChartBase, columnValue, isChartFrame };