@cascivo/charts 0.4.0 → 0.5.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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <div align="center">
4
4
  <a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="72" height="72" alt="cascivo logo"></a>
5
5
  <h1>@cascivo/charts</h1>
6
- <p><strong>Chart components built from scratch — scales, shapes, and signal-driven rendering, zero dependencies</strong></p>
6
+ <p><strong>Chart components built from scratch — scales, shapes, and signal-driven rendering, zero dependencies. Colors come from @cascivo/themes; components from @cascivo/react. Docs offline: npx @cascivo/docs</strong></p>
7
7
 
8
8
  [![npm](https://img.shields.io/npm/v/%40cascivo%2Fcharts?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/charts)
9
9
  [![downloads](https://img.shields.io/npm/dm/%40cascivo%2Fcharts?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/charts)
@@ -18,6 +18,8 @@
18
18
 
19
19
  Accessible, signal-driven chart library for cascivo — AreaChart, BarChart, LineChart, Sparkline, Heatmap, and more. All charts are keyboard-navigable with `aria-live` tooltips. CVD-safe palettes (Okabe-Ito, oklch) verified in CI across all 12 themes.
20
20
 
21
+ > **Docs offline?** The full cascivo reference ships as an npm package — `npx -y @cascivo/docs`, no website needed.
22
+
21
23
  ## Install
22
24
 
23
25
  ```sh
@@ -49,6 +51,24 @@ export function Traffic() {
49
51
  Charts are CSS-token-themed: drop them inside any element carrying a `data-theme` (or import a
50
52
  theme stylesheet) and they pick up the same palette, radii, and typography as the rest of cascivo.
51
53
 
54
+ ### Sizing — responsive by default
55
+
56
+ **Omit `width`** and the chart fills and tracks its container (a `ResizeObserver`
57
+ watches the slot), so a chart drops cleanly into a responsive `Card` or grid cell with
58
+ no measuring on your part. `height` defaults to `300` (px); set it to change the aspect.
59
+
60
+ Pass an explicit `width` only for a fixed-size export — and even then it is **clamped to
61
+ the container** (`max-inline-size: 100%`), so an over-wide `width` scales down instead of
62
+ overflowing and clipping data. To size another element to match a chart, or to build a
63
+ custom chart, use the exported `useChartSize()` hook.
64
+
65
+ ```tsx
66
+ <Card>
67
+ <LineChart data={data} /> {/* fills the card, resizes with it */}
68
+ </Card>
69
+ <LineChart data={data} height={160} /> {/* shorter, still full-width */}
70
+ ```
71
+
52
72
  > **Vite SSR (TanStack Start, Remix, vite-ssr, workerd)?** Like the rest of cascivo, the
53
73
  > chart CSS ships as side-effect imports a bare server loader can't resolve — mark
54
74
  > `ssr: { noExternal: [/^@cascivo\//] }` (the pattern already covers `@cascivo/charts`) and
package/dist/charts.css CHANGED
@@ -1,2 +1,2 @@
1
- @layer cascivo.component{._frame_1doa7_2{inline-size:100%;position:relative}@media (prefers-reduced-motion:no-preference){._frame_1doa7_2>svg{animation:_cascivo-chart-in_1doa7_1 var(--cascivo-chart-anim-dur,.32s) var(--cascivo-chart-anim-ease,ease-out) both}@keyframes _cascivo-chart-in_1doa7_1{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}._frame_1doa7_2 svg :is(path,rect,circle,line)[data-series],._frame_1doa7_2 svg path[data-link],._frame_1doa7_2 svg path[data-depth],._frame_1doa7_2 svg rect[data-day]{transition-property:var(--cascivo-chart-anim-props,opacity, fill, fill-opacity);transition-duration:var(--cascivo-chart-anim-dur,.24s);transition-timing-function:var(--cascivo-chart-anim-ease,ease)}._frame_1doa7_2[data-no-anim]>svg{animation:none}._frame_1doa7_2[data-no-anim] svg :is(path,rect,circle,line)[data-series],._frame_1doa7_2[data-no-anim] svg path[data-link],._frame_1doa7_2[data-no-anim] svg path[data-depth],._frame_1doa7_2[data-no-anim] svg rect[data-day]{transition:none}}._fallback_1doa7_53{clip-path:inset(50%);white-space:nowrap;block-size:1px;inline-size:1px;position:absolute;inset-inline-start:-9999px;overflow:hidden}._legend_zczeh_2{gap:var(--cascivo-space-2);padding-block:var(--cascivo-space-2);flex-wrap:wrap;display:flex}._item_zczeh_9{align-items:center;gap:var(--cascivo-space-1);padding:var(--cascivo-space-1) var(--cascivo-space-2);border:1px solid var(--cascivo-color-border);border-radius:var(--cascivo-radius-sm);cursor:pointer;font-size:var(--cascivo-font-size-sm);color:var(--cascivo-color-text);transition:opacity var(--cascivo-duration-150,.15s) ease;background:0 0;display:flex}._item_zczeh_9[data-state=off]{opacity:.4}._swatch_zczeh_27{border-radius:2px;flex-shrink:0;block-size:12px;inline-size:12px;display:inline-block}}
1
+ @layer cascivo.component{._frame_1xxqo_2{inline-size:100%;position:relative}._frame_1xxqo_2>svg{block-size:auto;max-inline-size:100%}@media (prefers-reduced-motion:no-preference){._frame_1xxqo_2>svg{animation:_cascivo-chart-in_1xxqo_1 var(--cascivo-chart-anim-dur,.32s) var(--cascivo-chart-anim-ease,ease-out) both}@keyframes _cascivo-chart-in_1xxqo_1{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}._frame_1xxqo_2 svg :is(path,rect,circle,line)[data-series],._frame_1xxqo_2 svg path[data-link],._frame_1xxqo_2 svg path[data-depth],._frame_1xxqo_2 svg rect[data-day]{transition-property:var(--cascivo-chart-anim-props,opacity, fill, fill-opacity);transition-duration:var(--cascivo-chart-anim-dur,.24s);transition-timing-function:var(--cascivo-chart-anim-ease,ease)}._frame_1xxqo_2[data-no-anim]>svg{animation:none}._frame_1xxqo_2[data-no-anim] svg :is(path,rect,circle,line)[data-series],._frame_1xxqo_2[data-no-anim] svg path[data-link],._frame_1xxqo_2[data-no-anim] svg path[data-depth],._frame_1xxqo_2[data-no-anim] svg rect[data-day]{transition:none}}._fallback_1xxqo_62{clip-path:inset(50%);white-space:nowrap;block-size:1px;inline-size:1px;position:absolute;inset-inline-start:-9999px;overflow:hidden}._legend_zczeh_2{gap:var(--cascivo-space-2);padding-block:var(--cascivo-space-2);flex-wrap:wrap;display:flex}._item_zczeh_9{align-items:center;gap:var(--cascivo-space-1);padding:var(--cascivo-space-1) var(--cascivo-space-2);border:1px solid var(--cascivo-color-border);border-radius:var(--cascivo-radius-sm);cursor:pointer;font-size:var(--cascivo-font-size-sm);color:var(--cascivo-color-text);transition:opacity var(--cascivo-duration-150,.15s) ease;background:0 0;display:flex}._item_zczeh_9[data-state=off]{opacity:.4}._swatch_zczeh_27{border-radius:2px;flex-shrink:0;block-size:12px;inline-size:12px;display:inline-block}}
2
2
  /*$vite$:1*/
package/dist/index.d.ts CHANGED
@@ -765,7 +765,15 @@ interface ZoomConfig {
765
765
  interface ChartFrameProps {
766
766
  title: string;
767
767
  description?: string | undefined;
768
+ /**
769
+ * Fixed SVG width in px. **Omit it (the default) for a responsive chart** — the
770
+ * frame fills and tracks its container's width via `ResizeObserver`. Set a fixed
771
+ * width only for a fixed-size export or thumbnail; even then it is clamped to the
772
+ * container (`max-inline-size: 100%`) so it can never overflow its card.
773
+ */
768
774
  width?: number | undefined;
775
+ /** SVG height in px. Defaults to 300 (48 in `plain` mode). Unlike `width`, height
776
+ * does not track the container — set it to change the chart's aspect. */
769
777
  height?: number | undefined;
770
778
  fallback?: ReactNode;
771
779
  children: (size: {
@@ -847,6 +855,20 @@ interface ChartSize {
847
855
  width: number;
848
856
  height: number;
849
857
  }
858
+ /**
859
+ * Measure a container and track its size in signals. **Every cascivo chart already
860
+ * uses this internally** — charts are responsive by default and fill their
861
+ * container, so you do NOT need this to make a chart responsive (just omit the
862
+ * chart's `width`). Reach for it only to size *another* element to match a chart,
863
+ * or to build a custom chart on the same measurement primitive.
864
+ *
865
+ * Returns `{ ref, width, height }`: spread `ref` onto the element to measure; read
866
+ * `width.value` / `height.value` (they update on resize via a `ResizeObserver`,
867
+ * deferred one frame to avoid the "ResizeObserver loop" warning). Under SSR (no
868
+ * `ResizeObserver`) it falls back to a single `getBoundingClientRect()` read, so
869
+ * the first paint has a sensible size. `defaultWidth` seeds the signal only until
870
+ * the first real measurement lands.
871
+ */
850
872
  declare function useChartSize(defaultWidth?: number, defaultHeight?: number): {
851
873
  ref: React.RefObject<HTMLDivElement | null>;
852
874
  width: import('@preact/signals-react').Signal<number>;
@@ -1272,7 +1294,12 @@ interface AreaChartProps<Datum = {
1272
1294
  y: number;
1273
1295
  }> {
1274
1296
  series: readonly AreaChartSeries<Datum>[];
1275
- x: (d: Datum) => number;
1297
+ /**
1298
+ * X-value accessor. Return a `number` for a numeric axis, or a `Date` for a
1299
+ * time axis — when the values are Dates the chart uses a time scale and formats
1300
+ * ticks as dates (parity with `LineChart`). One x-domain per chart.
1301
+ */
1302
+ x: (d: Datum) => number | Date;
1276
1303
  /**
1277
1304
  * Y-value accessor, applied to **every** series' data unless a series provides
1278
1305
  * its own `y`. There is one x-domain per chart, so `x` is chart-level only; to
package/dist/index.js CHANGED
@@ -337,7 +337,7 @@ function R(e, t, n) {
337
337
  }
338
338
  return r;
339
339
  }
340
- function ee(e, t, n, r, i) {
340
+ function z(e, t, n, r, i) {
341
341
  if (e.length === 0) return e;
342
342
  let a = [], o = (e) => (e[0] - r) * t + (e[1] - i) * n;
343
343
  for (let t = 0; t < e.length; t++) {
@@ -349,7 +349,7 @@ function ee(e, t, n, r, i) {
349
349
  }
350
350
  return a;
351
351
  }
352
- function te(e, t) {
352
+ function ee(e, t) {
353
353
  let n = [
354
354
  [t.x0, t.y0],
355
355
  [t.x1, t.y0],
@@ -361,21 +361,21 @@ function te(e, t) {
361
361
  for (let n = 0; n < e.length && i.length > 0; n++) {
362
362
  if (n === r) continue;
363
363
  let a = e[n];
364
- i = ee(i, a[0] - t[0], a[1] - t[1], (t[0] + a[0]) / 2, (t[1] + a[1]) / 2);
364
+ i = z(i, a[0] - t[0], a[1] - t[1], (t[0] + a[0]) / 2, (t[1] + a[1]) / 2);
365
365
  }
366
366
  return i;
367
367
  });
368
368
  }
369
- function z(e) {
369
+ function B(e) {
370
370
  return e.length === 0 ? "" : `M${e.map((e) => `${e[0]},${e[1]}`).join("L")}Z`;
371
371
  }
372
372
  //#endregion
373
373
  //#region src/engine/stats.ts
374
- function B(e) {
374
+ function V(e) {
375
375
  let t = e.length, n = e[Math.floor(t * .25)] ?? 0;
376
376
  return (e[Math.floor(t * .75)] ?? 0) - n;
377
377
  }
378
- function V(e, t) {
378
+ function te(e, t) {
379
379
  if (e.length === 0) return [];
380
380
  let n = [...e].sort((e, t) => e - t), r = n.length, i = n[0] ?? 0, a = n[r - 1] ?? 0;
381
381
  if (i === a) return [{
@@ -386,7 +386,7 @@ function V(e, t) {
386
386
  let o;
387
387
  if (t !== void 0 && t > 0) o = t;
388
388
  else {
389
- let e = 2 * B(n) * r ** (-1 / 3);
389
+ let e = 2 * V(n) * r ** (-1 / 3);
390
390
  o = Math.ceil(e > 0 ? (a - i) / e : Math.sqrt(r)), o = Math.max(1, Math.min(o, 200));
391
391
  }
392
392
  let s = (a - i) / o, c = Array.from({ length: o }, (e, t) => ({
@@ -915,9 +915,9 @@ var Ve = {
915
915
  bottom: 2,
916
916
  left: 2
917
917
  }, Ue = {
918
- frame: "_frame_1doa7_2",
919
- "cascivo-chart-in": "_cascivo-chart-in_1doa7_1",
920
- fallback: "_fallback_1doa7_53"
918
+ frame: "_frame_1xxqo_2",
919
+ "cascivo-chart-in": "_cascivo-chart-in_1xxqo_1",
920
+ fallback: "_fallback_1xxqo_62"
921
921
  };
922
922
  //#endregion
923
923
  //#region src/core/data-point.ts
@@ -1141,9 +1141,9 @@ var at = {
1141
1141
  };
1142
1142
  function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, children: h, className: g, "data-state": _, emptyLabel: v, plain: y, tooltip: b, onSelect: x, hover: S = "rect", renderer: C = "svg", paint: w, zoom: T, toolbox: E, onRestore: D, transition: O, onBeforeDraw: k, onAfterDraw: A }) {
1143
1143
  o();
1144
- let j = s(), M = `${j}-desc`, N = `${j}-live`, { ref: P, width: F, height: I } = Be(n ?? 400, r), L = i(null), ee = i(!1), te = c(null), z = c(null), B = c(null), V = c(null);
1144
+ let j = s(), M = `${j}-desc`, N = `${j}-live`, { ref: P, width: F, height: I } = Be(n ?? 400, r), L = i(null), z = i(!1), ee = c(null), B = c(null), V = c(null), te = c(null);
1145
1145
  a(() => {
1146
- let e = V.current;
1146
+ let e = te.current;
1147
1147
  if (!e || !T) return;
1148
1148
  let t = (t) => {
1149
1149
  t.preventDefault();
@@ -1154,7 +1154,7 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1154
1154
  });
1155
1155
  let H = () => {
1156
1156
  T && (T.window.value = [0, Math.max(0, T.count - 1)]);
1157
- }, U = n ?? F.value, W = r ?? I.value, G = E === !0 ? {} : E || null, K = () => z.current ? nt(z.current) : null, q = () => {
1157
+ }, U = n ?? F.value, W = r ?? I.value, G = E === !0 ? {} : E || null, K = () => B.current ? nt(B.current) : null, q = () => {
1158
1158
  let t = K();
1159
1159
  t && it(t, `${e || "chart"}.svg`);
1160
1160
  }, ne = () => {
@@ -1174,9 +1174,9 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1174
1174
  }) : b;
1175
1175
  a(() => {
1176
1176
  let e = L.value;
1177
- if (!Y || !te.current) return;
1177
+ if (!Y || !ee.current) return;
1178
1178
  let t = e === null ? void 0 : Y.points[e];
1179
- te.current.textContent = t ? (Y.format ?? We)(t) : "";
1179
+ ee.current.textContent = t ? (Y.format ?? We)(t) : "";
1180
1180
  });
1181
1181
  let re = {
1182
1182
  position: "absolute",
@@ -1213,10 +1213,10 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1213
1213
  onPng: ne,
1214
1214
  onSvg: q,
1215
1215
  onToggleData: () => {
1216
- ee.value = !ee.value;
1216
+ z.value = !z.value;
1217
1217
  },
1218
1218
  onRestore: J,
1219
- showData: ee.value
1219
+ showData: z.value
1220
1220
  })
1221
1221
  }),
1222
1222
  X && /* @__PURE__ */ f(qe, {
@@ -1227,7 +1227,7 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1227
1227
  paint: w
1228
1228
  }),
1229
1229
  /* @__PURE__ */ p("svg", {
1230
- ref: z,
1230
+ ref: B,
1231
1231
  role: "img",
1232
1232
  "aria-label": e,
1233
1233
  "aria-describedby": t ? M : void 0,
@@ -1268,7 +1268,7 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1268
1268
  style: at,
1269
1269
  children: m
1270
1270
  }),
1271
- G && ee.value && m && /* @__PURE__ */ f("div", {
1271
+ G && z.value && m && /* @__PURE__ */ f("div", {
1272
1272
  "data-data-view": "",
1273
1273
  style: { overflowX: "auto" },
1274
1274
  children: m
@@ -1277,7 +1277,7 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1277
1277
  Y !== void 0 && /* @__PURE__ */ p(d, { children: [
1278
1278
  /* @__PURE__ */ f("span", {
1279
1279
  id: N,
1280
- ref: te,
1280
+ ref: ee,
1281
1281
  "aria-live": "polite",
1282
1282
  style: {
1283
1283
  position: "absolute",
@@ -1347,21 +1347,21 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1347
1347
  children: u(l.charts.resetZoom)
1348
1348
  }),
1349
1349
  /* @__PURE__ */ f("div", {
1350
- ref: V,
1350
+ ref: te,
1351
1351
  role: "application",
1352
1352
  "aria-label": T ? "Chart — arrow keys navigate points; + and - zoom, 0 resets, drag to pan" : "Chart data — use arrow keys to navigate points",
1353
1353
  tabIndex: 0,
1354
1354
  style: re,
1355
1355
  onPointerDown: (e) => {
1356
- T && (B.current = {
1356
+ T && (V.current = {
1357
1357
  x: e.clientX,
1358
1358
  win: [...T.window.value]
1359
1359
  }, e.currentTarget.setPointerCapture(e.pointerId));
1360
1360
  },
1361
1361
  onPointerMove: (e) => {
1362
- if (T && B.current && e.buttons === 1) {
1363
- let t = e.currentTarget.getBoundingClientRect(), n = B.current.win[1] - B.current.win[0] + 1, r = e.clientX - B.current.x, i = t.width ? -(r / t.width) * n : 0;
1364
- T.window.value = Ze(B.current.win, T.count, i);
1362
+ if (T && V.current && e.buttons === 1) {
1363
+ let t = e.currentTarget.getBoundingClientRect(), n = V.current.win[1] - V.current.win[0] + 1, r = e.clientX - V.current.x, i = t.width ? -(r / t.width) * n : 0;
1364
+ T.window.value = Ze(V.current.win, T.count, i);
1365
1365
  return;
1366
1366
  }
1367
1367
  if (!Y || !Y.points.length) return;
@@ -1369,10 +1369,10 @@ function Q({ title: e, description: t, width: n, height: r = 300, fallback: m, c
1369
1369
  L.value = Y.mode === "axis" ? Ke(Y.points, n, r, "x") : S === "voronoi" ? R(Y.points.map((e) => [e.cx, e.cy]), n, r) : Ke(Y.points, n, r, "xy");
1370
1370
  },
1371
1371
  onPointerUp: () => {
1372
- B.current = null;
1372
+ V.current = null;
1373
1373
  },
1374
1374
  onPointerLeave: () => {
1375
- B.current = null, Y && (L.value = null);
1375
+ V.current = null, Y && (L.value = null);
1376
1376
  },
1377
1377
  onKeyDown: (e) => {
1378
1378
  if (T) {
@@ -2222,9 +2222,9 @@ var Xt = Array.from({ length: 8 }, (e, t) => `var(--cascivo-chart-${t + 1})`);
2222
2222
  function Zt(e) {
2223
2223
  return [Math.min(0, ...e), Math.max(...e)];
2224
2224
  }
2225
- function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monotone", width: u, height: h, xTicks: g = 5, yTicks: _ = 5, legend: v, tooltip: y, formatTooltip: b, className: x, plain: C, annotations: E, labels: D, connectNulls: O, onSelect: k, brush: A, dataZoom: j, zoom: M, syncId: N, tooltipMode: P, secondAxis: F, decimate: I, toolbox: L, transition: R, onBeforeDraw: ee, onAfterDraw: te }) {
2225
+ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monotone", width: u, height: h, xTicks: g = 5, yTicks: _ = 5, legend: v, tooltip: y, formatTooltip: b, className: x, plain: C, annotations: E, labels: D, connectNulls: O, onSelect: k, brush: A, dataZoom: j, zoom: M, syncId: N, tooltipMode: P, secondAxis: F, decimate: I, toolbox: L, transition: R, onBeforeDraw: z, onAfterDraw: ee }) {
2226
2226
  o();
2227
- let z = i(/* @__PURE__ */ new Set()), B = C ? null : xt(D), V = I === !0 ? {
2227
+ let B = i(/* @__PURE__ */ new Set()), V = C ? null : xt(D), te = I === !0 ? {
2228
2228
  method: "lttb",
2229
2229
  threshold: 1e3
2230
2230
  } : I ? {
@@ -2281,7 +2281,7 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2281
2281
  for (let r = 0; r < e; r++) {
2282
2282
  let e = [], i = 0, a = 0, o = Infinity, s = "";
2283
2283
  K.forEach((n, c) => {
2284
- if (z.value.has(n.id)) return;
2284
+ if (B.value.has(n.id)) return;
2285
2285
  let l = n.data[r];
2286
2286
  if (l === void 0) return;
2287
2287
  let f = X(n)(l);
@@ -2307,7 +2307,7 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2307
2307
  format: (e) => `${e.label}: ${(e.segments ?? []).map((e) => `${e.label} ${e.value}`).join(", ")}`
2308
2308
  };
2309
2309
  }
2310
- let f = K.flatMap((e) => z.value.has(e.id) ? [] : e.data.flatMap((n, r) => {
2310
+ let f = K.flatMap((e) => B.value.has(e.id) ? [] : e.data.flatMap((n, r) => {
2311
2311
  let i = X(e)(n);
2312
2312
  if (!Number.isFinite(i)) return [];
2313
2313
  let a = t(n), o = s.map(a), c = u(e).map(i), l = a instanceof Date ? a.toLocaleDateString() : String(a);
@@ -2338,8 +2338,8 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2338
2338
  W.value = [0, Math.max(0, H - 1)];
2339
2339
  } : void 0,
2340
2340
  transition: R,
2341
- onBeforeDraw: ee,
2342
- onAfterDraw: te,
2341
+ onBeforeDraw: z,
2342
+ onAfterDraw: ee,
2343
2343
  children: ({ width: e, height: n }) => {
2344
2344
  let r = e - J.left - J.right, i = n - J.top - J.bottom, a = Math.min(...ce ? Z.map((e) => e.getTime()) : Z), o = Math.max(...ce ? Z.map((e) => e.getTime()) : Z), s = ce ? S([new Date(a), new Date(o)], [0, r]) : m([a, o], [0, r]), c = m(Zt(ae), [i, 0]), u = q ? m(Zt(oe), [i, 0]) : c;
2345
2345
  return /* @__PURE__ */ f("g", { children: /* @__PURE__ */ p("g", {
@@ -2358,16 +2358,16 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2358
2358
  innerH: i
2359
2359
  }),
2360
2360
  K.map((e, n) => {
2361
- if (z.value.has(e.id)) return null;
2361
+ if (B.value.has(e.id)) return null;
2362
2362
  let r = e.color ?? Xt[n % Xt.length], i = e.axis === "right" ? u : c, a = (e) => s.map(e);
2363
- if (V && e.data.length > V.threshold) {
2363
+ if (te && e.data.length > te.threshold) {
2364
2364
  let n = [];
2365
2365
  for (let r of e.data) {
2366
2366
  let o = X(e)(r);
2367
2367
  Number.isFinite(o) && n.push([a(t(r)), i.map(o)]);
2368
2368
  }
2369
2369
  return /* @__PURE__ */ f("path", {
2370
- d: T(Ie(n, V.threshold, V.method).map((e) => [e[0], e[1]]), l),
2370
+ d: T(Ie(n, te.threshold, te.method).map((e) => [e[0], e[1]]), l),
2371
2371
  fill: "none",
2372
2372
  stroke: r,
2373
2373
  strokeWidth: 2,
@@ -2388,12 +2388,12 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2388
2388
  strokeLinecap: "round",
2389
2389
  strokeLinejoin: "round",
2390
2390
  "data-series": e.id
2391
- }, n)), B && e.data.map((t, n) => {
2391
+ }, n)), V && e.data.map((t, n) => {
2392
2392
  let r = o[n];
2393
2393
  return r ? /* @__PURE__ */ f(St, {
2394
2394
  x: r[0],
2395
2395
  y: r[1] - 8,
2396
- text: B.format(X(e)(t))
2396
+ text: V.format(X(e)(t))
2397
2397
  }, n) : null;
2398
2398
  })] }, e.id);
2399
2399
  }),
@@ -2440,7 +2440,7 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2440
2440
  label: e.label,
2441
2441
  color: e.color ?? Xt[t % Xt.length]
2442
2442
  })),
2443
- hidden: z
2443
+ hidden: B
2444
2444
  })
2445
2445
  ]
2446
2446
  });
@@ -2448,37 +2448,40 @@ function Qt({ series: e, x: t, y: n, title: r, description: s, curve: l = "monot
2448
2448
  //#endregion
2449
2449
  //#region src/charts/area-chart/area-chart.tsx
2450
2450
  var $t = { fillOpacity: "var(--cascivo-chart-fill-opacity, 0.25)" }, en = Array.from({ length: 8 }, (e, t) => `var(--cascivo-chart-${t + 1})`);
2451
- function tn({ series: e, x: t, y: n, title: r, description: l, stacked: u = !1, curve: h = "monotone", fill: g = "solid", patternKind: _, width: v, height: y, xTicks: b = 5, yTicks: x = 5, legend: S, tooltip: C, className: w, plain: E, annotations: D, labels: O, onSelect: k, brush: A, dataZoom: j, zoom: M, syncId: P, tooltipMode: I, secondAxis: L, decimate: R, toolbox: ee }) {
2451
+ function tn({ series: e, x: t, y: n, title: r, description: l, stacked: u = !1, curve: h = "monotone", fill: g = "solid", patternKind: _, width: v, height: y, xTicks: b = 5, yTicks: x = 5, legend: C, tooltip: w, className: E, plain: D, annotations: O, labels: k, onSelect: A, brush: j, dataZoom: M, zoom: P, syncId: I, tooltipMode: L, secondAxis: R, decimate: z, toolbox: ee }) {
2452
2452
  o();
2453
- let te = s(), z = i(/* @__PURE__ */ new Set()), B = E ? null : xt(O), V = R === !0 ? {
2453
+ let B = s(), V = i(/* @__PURE__ */ new Set()), te = D ? null : xt(k), H = z === !0 ? {
2454
2454
  method: "lttb",
2455
2455
  threshold: 1e3
2456
- } : R ? {
2457
- method: R.method ?? "lttb",
2458
- threshold: R.threshold ?? 1e3
2459
- } : null, H = e.reduce((e, t) => Math.max(e, t.data.length), 0), U = (A || j || M || P !== void 0) && H > 0, W = i([0, Math.max(0, H - 1)]), G = c(null);
2460
- P && !G.current && (G.current = st(P)), a(() => () => {
2461
- P && ct(P);
2456
+ } : z ? {
2457
+ method: z.method ?? "lttb",
2458
+ threshold: z.threshold ?? 1e3
2459
+ } : null, U = e.reduce((e, t) => Math.max(e, t.data.length), 0), W = (j || M || P || I !== void 0) && U > 0, G = i([0, Math.max(0, U - 1)]), K = c(null);
2460
+ I && !K.current && (K.current = st(I)), a(() => () => {
2461
+ I && ct(I);
2462
2462
  }), a(() => {
2463
- let e = G.current;
2463
+ let e = K.current;
2464
2464
  if (!e) return;
2465
- let t = e.window.value, n = W.peek();
2466
- t && (t[0] !== n[0] || t[1] !== n[1]) && (W.value = t);
2465
+ let t = e.window.value, n = G.peek();
2466
+ t && (t[0] !== n[0] || t[1] !== n[1]) && (G.value = t);
2467
2467
  }), a(() => {
2468
- let e = G.current;
2468
+ let e = K.current;
2469
2469
  if (!e) return;
2470
- let t = W.value, n = e.window.peek();
2470
+ let t = G.value, n = e.window.peek();
2471
2471
  (!n || n[0] !== t[0] || n[1] !== t[1]) && (e.window.value = t);
2472
2472
  });
2473
- let K = U ? e.map((e) => ({
2473
+ let q = W ? e.map((e) => ({
2474
2474
  ...e,
2475
- data: e.data.slice(W.value[0], W.value[1] + 1)
2476
- })) : e, q = !E && !u && K.some((e) => e.axis === "right"), ne = E ? He : Ve, J = q ? {
2477
- ...ne,
2475
+ data: e.data.slice(G.value[0], G.value[1] + 1)
2476
+ })) : e, ne = !D && !u && q.some((e) => e.axis === "right"), J = D ? He : Ve, Y = ne ? {
2477
+ ...J,
2478
2478
  right: 60
2479
- } : ne, Y = y ?? (E ? 48 : 300), re = E ? !1 : S ?? K.length > 1, X = (e) => e.y ?? n, Z = (K[0]?.data ?? []).map((e) => t(e)), ie = (q ? K.filter((e) => e.axis !== "right") : K).flatMap((e) => e.data.map((t) => X(e)(t))), ae = q ? K.filter((e) => e.axis === "right").flatMap((e) => e.data.map((t) => X(e)(t))) : [];
2480
- Yt("AreaChart", () => [...ie, ...ae]);
2481
- let oe = Z.length > 0, se = oe ? Math.min(...Z) : 0, ce = oe ? Math.max(...Z) : 1, le = u ? 0 : Math.min(0, ...ie), ue = Math.max(...u ? (K[0]?.data ?? []).map((e, t) => K.reduce((e, n) => e + X(n)(n.data[t]), 0)) : ie), de = q ? Math.min(0, ...ae) : le, fe = q ? Math.max(...ae) : ue;
2479
+ } : J, re = y ?? (D ? 48 : 300), X = D ? !1 : C ?? q.length > 1, Z = (e) => e.y ?? n, ie = (q[0]?.data ?? []).map((e) => t(e)), ae = (ne ? q.filter((e) => e.axis !== "right") : q).flatMap((e) => e.data.map((t) => Z(e)(t))), oe = ne ? q.filter((e) => e.axis === "right").flatMap((e) => e.data.map((t) => Z(e)(t))) : [];
2480
+ Yt("AreaChart", () => [...ae, ...oe]);
2481
+ let se = ie.length > 0, ce = se && ie[0] instanceof Date, le = ie.map((e) => e instanceof Date ? e.getTime() : e), ue = se ? Math.min(...le) : 0, de = se ? Math.max(...le) : 1, fe = (e) => ce ? S([new Date(ue), new Date(de)], [0, e]) : m([ue, de], [0, e]), pe = (e, n) => e.map(t(n)), me = (e) => {
2482
+ let n = t(e);
2483
+ return n instanceof Date ? n.toLocaleDateString() : String(n);
2484
+ }, he = u ? 0 : Math.min(0, ...ae), ge = Math.max(...u ? (q[0]?.data ?? []).map((e, t) => q.reduce((e, n) => e + Z(n)(n.data[t]), 0)) : ae), _e = ne ? Math.min(0, ...oe) : he, ve = ne ? Math.max(...oe) : ge;
2482
2485
  return /* @__PURE__ */ p("div", {
2483
2486
  style: {
2484
2487
  display: "flex",
@@ -2490,136 +2493,136 @@ function tn({ series: e, x: t, y: n, title: r, description: l, stacked: u = !1,
2490
2493
  title: r,
2491
2494
  description: l,
2492
2495
  width: v,
2493
- height: Y,
2496
+ height: re,
2494
2497
  fallback: /* @__PURE__ */ p("table", { children: [
2495
2498
  /* @__PURE__ */ f("caption", { children: r }),
2496
- /* @__PURE__ */ f("thead", { children: /* @__PURE__ */ p("tr", { children: [/* @__PURE__ */ f("th", { children: "X" }), K.map((e) => /* @__PURE__ */ f("th", { children: e.label }, e.id))] }) }),
2497
- /* @__PURE__ */ f("tbody", { children: (K[0]?.data ?? []).map((e, n) => /* @__PURE__ */ p("tr", { children: [/* @__PURE__ */ f("td", { children: K[0] ? String(t(K[0].data[n])) : "" }), K.map((e) => /* @__PURE__ */ f("td", { children: e.data[n] == null ? "" : X(e)(e.data[n]) }, e.id))] }, n)) })
2499
+ /* @__PURE__ */ f("thead", { children: /* @__PURE__ */ p("tr", { children: [/* @__PURE__ */ f("th", { children: "X" }), q.map((e) => /* @__PURE__ */ f("th", { children: e.label }, e.id))] }) }),
2500
+ /* @__PURE__ */ f("tbody", { children: (q[0]?.data ?? []).map((e, t) => /* @__PURE__ */ p("tr", { children: [/* @__PURE__ */ f("td", { children: q[0] ? me(q[0].data[t]) : "" }), q.map((e) => /* @__PURE__ */ f("td", { children: e.data[t] == null ? "" : Z(e)(e.data[t]) }, e.id))] }, t)) })
2498
2501
  ] }),
2499
- className: w,
2500
- "data-state": oe ? void 0 : "empty",
2501
- plain: E,
2502
- tooltip: C !== !1 && oe ? ({ width: e, height: n }) => {
2503
- if (C === !1 || !oe) return;
2504
- let r = e - J.left - J.right, i = n - J.top - J.bottom, a = m([se, ce], [0, r]), o = m([le, ue], [i, 0]), s = q ? m([de, fe], [i, 0]) : o, c = (e) => e.axis === "right" ? s : o;
2505
- if (I === "axis") {
2506
- let e = K.reduce((e, t) => Math.max(e, t.data.length), 0), n = [];
2507
- for (let r = 0; r < e; r++) {
2508
- let e = [], i = Infinity, o = "", s = J.left;
2509
- K.forEach((n, l) => {
2510
- if (z.value.has(n.id)) return;
2511
- let u = n.data[r];
2512
- if (u === void 0) return;
2513
- let d = X(n)(u);
2514
- Number.isFinite(d) && (s = J.left + a.map(t(u)), i = Math.min(i, c(n).map(d)), o = String(t(u)), e.push({
2515
- label: n.label,
2516
- value: d,
2517
- color: n.color ?? en[l % en.length]
2502
+ className: E,
2503
+ "data-state": se ? void 0 : "empty",
2504
+ plain: D,
2505
+ tooltip: w !== !1 && se ? ({ width: e, height: t }) => {
2506
+ if (w === !1 || !se) return;
2507
+ let n = e - Y.left - Y.right, r = t - Y.top - Y.bottom, i = fe(n), a = m([he, ge], [r, 0]), o = ne ? m([_e, ve], [r, 0]) : a, s = (e) => e.axis === "right" ? o : a;
2508
+ if (L === "axis") {
2509
+ let e = q.reduce((e, t) => Math.max(e, t.data.length), 0), t = [];
2510
+ for (let n = 0; n < e; n++) {
2511
+ let e = [], r = Infinity, a = "", o = Y.left;
2512
+ q.forEach((t, c) => {
2513
+ if (V.value.has(t.id)) return;
2514
+ let l = t.data[n];
2515
+ if (l === void 0) return;
2516
+ let u = Z(t)(l);
2517
+ Number.isFinite(u) && (o = Y.left + pe(i, l), r = Math.min(r, s(t).map(u)), a = me(l), e.push({
2518
+ label: t.label,
2519
+ value: u,
2520
+ color: t.color ?? en[c % en.length]
2518
2521
  }));
2519
- }), e.length !== 0 && n.push({
2520
- id: `x-${r}`,
2521
- cx: s,
2522
- cy: J.top + (i === Infinity ? 0 : i),
2523
- label: o,
2524
- value: o,
2522
+ }), e.length !== 0 && t.push({
2523
+ id: `x-${n}`,
2524
+ cx: o,
2525
+ cy: Y.top + (r === Infinity ? 0 : r),
2526
+ label: a,
2527
+ value: a,
2525
2528
  segments: e
2526
2529
  });
2527
2530
  }
2528
2531
  return {
2529
- points: n,
2532
+ points: t,
2530
2533
  mode: "axis",
2531
2534
  format: (e) => `${e.label}: ${(e.segments ?? []).map((e) => `${e.label} ${e.value}`).join(", ")}`
2532
2535
  };
2533
2536
  }
2534
- return { points: K.flatMap((e) => z.value.has(e.id) ? [] : e.data.map((n, r) => ({
2535
- id: `${e.id}-${r}`,
2536
- cx: J.left + a.map(t(n)),
2537
- cy: J.top + c(e).map(X(e)(n)),
2538
- label: String(t(n)),
2539
- value: X(e)(n),
2537
+ return { points: q.flatMap((e) => V.value.has(e.id) ? [] : e.data.map((t, n) => ({
2538
+ id: `${e.id}-${n}`,
2539
+ cx: Y.left + pe(i, t),
2540
+ cy: Y.top + s(e).map(Z(e)(t)),
2541
+ label: me(t),
2542
+ value: Z(e)(t),
2540
2543
  seriesId: e.id
2541
2544
  }))) };
2542
2545
  } : void 0,
2543
- onSelect: k,
2544
- zoom: M && H > 1 ? {
2545
- window: W,
2546
- count: H
2546
+ onSelect: A,
2547
+ zoom: P && U > 1 ? {
2548
+ window: G,
2549
+ count: U
2547
2550
  } : void 0,
2548
2551
  toolbox: ee,
2549
- onRestore: U ? () => {
2550
- W.value = [0, Math.max(0, H - 1)];
2552
+ onRestore: W ? () => {
2553
+ G.value = [0, Math.max(0, U - 1)];
2551
2554
  } : void 0,
2552
- children: ({ width: e, height: n }) => {
2553
- let r = e - J.left - J.right, i = n - J.top - J.bottom, a = m([se, ce], [0, r]), o = m([le, ue], [i, 0]), s = q ? m([de, fe], [i, 0]) : o, c = [];
2554
- return u && (c = F(K.map((e) => e.data.map((t) => X(e)(t))))), /* @__PURE__ */ p("g", { children: [g !== "solid" && /* @__PURE__ */ f(Dt, {
2555
- prefix: te,
2555
+ children: ({ width: e, height: t }) => {
2556
+ let n = e - Y.left - Y.right, r = t - Y.top - Y.bottom, i = fe(n), a = m([he, ge], [r, 0]), o = ne ? m([_e, ve], [r, 0]) : a, s = [];
2557
+ return u && (s = F(q.map((e) => e.data.map((t) => Z(e)(t))))), /* @__PURE__ */ p("g", { children: [g !== "solid" && /* @__PURE__ */ f(Dt, {
2558
+ prefix: B,
2556
2559
  fill: g,
2557
2560
  patternKind: _,
2558
- series: K.map((e, t) => ({
2561
+ series: q.map((e, t) => ({
2559
2562
  id: e.id,
2560
2563
  color: e.color ?? en[t % en.length]
2561
2564
  }))
2562
2565
  }), /* @__PURE__ */ p("g", {
2563
- transform: `translate(${J.left},${J.top})`,
2566
+ transform: `translate(${Y.left},${Y.top})`,
2564
2567
  children: [
2565
- !E && /* @__PURE__ */ f(pt, {
2566
- scale: o,
2568
+ !D && /* @__PURE__ */ f(pt, {
2569
+ scale: a,
2567
2570
  orientation: "y",
2568
- length: r,
2571
+ length: n,
2569
2572
  tickCount: x
2570
2573
  }),
2571
- !E && vt(D, {
2572
- xScale: a,
2573
- yScale: o,
2574
- innerW: r,
2575
- innerH: i
2574
+ !D && vt(O, {
2575
+ xScale: i,
2576
+ yScale: a,
2577
+ innerW: n,
2578
+ innerH: r
2576
2579
  }),
2577
- K.map((e, n) => {
2578
- if (z.value.has(e.id)) return null;
2579
- let r = e.color ?? en[n % en.length], i, l;
2580
- if (u && c[n]) {
2581
- let s = c[n];
2582
- i = e.data.map((e, n) => [a.map(t(e)), o.map(s[n][1])]);
2583
- let u = e.data.map((e, n) => [a.map(t(e)), o.map(s[n][0])]);
2584
- l = o.map(0);
2585
- let d = T(i, h), m = u[u.length - 1], _ = u[0], v = [...u].reverse().map(([e, t]) => `L${e},${t}`).join(""), y = `${d}L${m[0]},${m[1]}${v}L${_[0]},${_[1]}Z`;
2580
+ q.map((e, t) => {
2581
+ if (V.value.has(e.id)) return null;
2582
+ let n = e.color ?? en[t % en.length], r, c;
2583
+ if (u && s[t]) {
2584
+ let o = s[t];
2585
+ r = e.data.map((e, t) => [pe(i, e), a.map(o[t][1])]);
2586
+ let l = e.data.map((e, t) => [pe(i, e), a.map(o[t][0])]);
2587
+ c = a.map(0);
2588
+ let u = T(r, h), d = l[l.length - 1], m = l[0], _ = [...l].reverse().map(([e, t]) => `L${e},${t}`).join(""), v = `${u}L${d[0]},${d[1]}${_}L${m[0]},${m[1]}Z`;
2586
2589
  return /* @__PURE__ */ p("g", {
2587
2590
  "data-series": e.id,
2588
2591
  children: [
2589
2592
  /* @__PURE__ */ f("path", {
2590
- d: y,
2591
- fill: Et(te, e.id, g, r),
2593
+ d: v,
2594
+ fill: Et(B, e.id, g, n),
2592
2595
  style: g === "solid" ? $t : void 0,
2593
2596
  stroke: "none"
2594
2597
  }),
2595
2598
  /* @__PURE__ */ f("path", {
2596
- d: T(i, h),
2599
+ d: T(r, h),
2597
2600
  fill: "none",
2598
- stroke: r,
2601
+ stroke: n,
2599
2602
  strokeWidth: 2
2600
2603
  }),
2601
- B && i.map((t, n) => /* @__PURE__ */ f(St, {
2604
+ te && r.map((t, n) => /* @__PURE__ */ f(St, {
2602
2605
  x: t[0],
2603
2606
  y: t[1] - 8,
2604
- text: B.format(X(e)(e.data[n]))
2607
+ text: te.format(Z(e)(e.data[n]))
2605
2608
  }, n))
2606
2609
  ]
2607
2610
  }, e.id);
2608
2611
  } else {
2609
- let n = e.axis === "right" ? s : o;
2610
- if (i = e.data.map((r) => [a.map(t(r)), n.map(X(e)(r))]), l = n.map(0), V && i.length > V.threshold) {
2611
- let t = Ie(i, V.threshold, V.method).map((e) => [e[0], e[1]]);
2612
+ let t = e.axis === "right" ? o : a;
2613
+ if (r = e.data.map((n) => [pe(i, n), t.map(Z(e)(n))]), c = t.map(0), H && r.length > H.threshold) {
2614
+ let t = Ie(r, H.threshold, H.method).map((e) => [e[0], e[1]]);
2612
2615
  return /* @__PURE__ */ p("g", {
2613
2616
  "data-series": e.id,
2614
2617
  children: [/* @__PURE__ */ f("path", {
2615
- d: N(t, l, h),
2616
- fill: Et(te, e.id, g, r),
2618
+ d: N(t, c, h),
2619
+ fill: Et(B, e.id, g, n),
2617
2620
  style: g === "solid" ? $t : void 0,
2618
2621
  stroke: "none"
2619
2622
  }), /* @__PURE__ */ f("path", {
2620
2623
  d: T(t, h),
2621
2624
  fill: "none",
2622
- stroke: r,
2625
+ stroke: n,
2623
2626
  strokeWidth: 2
2624
2627
  })]
2625
2628
  }, e.id);
@@ -2628,70 +2631,70 @@ function tn({ series: e, x: t, y: n, title: r, description: l, stacked: u = !1,
2628
2631
  "data-series": e.id,
2629
2632
  children: [
2630
2633
  /* @__PURE__ */ f("path", {
2631
- d: N(i, l, h),
2632
- fill: Et(te, e.id, g, r),
2634
+ d: N(r, c, h),
2635
+ fill: Et(B, e.id, g, n),
2633
2636
  style: g === "solid" ? $t : void 0,
2634
2637
  stroke: "none"
2635
2638
  }),
2636
2639
  /* @__PURE__ */ f("path", {
2637
- d: T(i, h),
2640
+ d: T(r, h),
2638
2641
  fill: "none",
2639
- stroke: r,
2642
+ stroke: n,
2640
2643
  strokeWidth: 2
2641
2644
  }),
2642
- B && i.map((t, n) => /* @__PURE__ */ f(St, {
2645
+ te && r.map((t, n) => /* @__PURE__ */ f(St, {
2643
2646
  x: t[0],
2644
2647
  y: t[1] - 8,
2645
- text: B.format(X(e)(e.data[n]))
2648
+ text: te.format(Z(e)(e.data[n]))
2646
2649
  }, n))
2647
2650
  ]
2648
2651
  }, e.id);
2649
2652
  }
2650
2653
  }),
2651
- !E && /* @__PURE__ */ p(d, { children: [
2654
+ !D && /* @__PURE__ */ p(d, { children: [
2652
2655
  /* @__PURE__ */ f($, {
2653
- scale: a,
2656
+ scale: i,
2654
2657
  orientation: "x",
2655
- length: r,
2658
+ length: n,
2656
2659
  tickCount: b,
2657
- transform: `translate(0,${i})`
2660
+ transform: `translate(0,${r})`
2658
2661
  }),
2659
2662
  /* @__PURE__ */ f($, {
2660
- scale: o,
2663
+ scale: a,
2661
2664
  orientation: "y",
2662
- length: i,
2665
+ length: r,
2663
2666
  tickCount: x
2664
2667
  }),
2665
- q && /* @__PURE__ */ f($, {
2666
- scale: s,
2668
+ ne && /* @__PURE__ */ f($, {
2669
+ scale: o,
2667
2670
  orientation: "y",
2668
- length: i,
2671
+ length: r,
2669
2672
  tickCount: x,
2670
- transform: `translate(${r},0)`,
2671
- ...L?.format ? { format: (e) => L.format(Number(e)) } : {}
2673
+ transform: `translate(${n},0)`,
2674
+ ...R?.format ? { format: (e) => R.format(Number(e)) } : {}
2672
2675
  })
2673
2676
  ] })
2674
2677
  ]
2675
2678
  })] });
2676
2679
  }
2677
2680
  }),
2678
- A && !j && H > 1 && /* @__PURE__ */ f(Pt, {
2679
- count: H,
2680
- window: W,
2681
+ j && !M && U > 1 && /* @__PURE__ */ f(Pt, {
2682
+ count: U,
2683
+ window: G,
2681
2684
  label: "Range"
2682
2685
  }),
2683
- j && H > 1 && /* @__PURE__ */ f(Ft, {
2684
- count: H,
2685
- window: W,
2686
+ M && U > 1 && /* @__PURE__ */ f(Ft, {
2687
+ count: U,
2688
+ window: G,
2686
2689
  label: "Range"
2687
2690
  }),
2688
- re && /* @__PURE__ */ f(Kt, {
2689
- series: K.map((e, t) => ({
2691
+ X && /* @__PURE__ */ f(Kt, {
2692
+ series: q.map((e, t) => ({
2690
2693
  id: e.id,
2691
2694
  label: e.label,
2692
2695
  color: e.color ?? en[t % en.length]
2693
2696
  })),
2694
- hidden: z
2697
+ hidden: V
2695
2698
  })
2696
2699
  ]
2697
2700
  });
@@ -2705,13 +2708,13 @@ function rn(e) {
2705
2708
  }
2706
2709
  function an({ series: e, x: t, y: n, title: r, description: a, orientation: c = "vertical", mode: l = "grouped", width: u, height: h, xTicks: _ = 5, yTicks: v = 5, xLabelEvery: y, legend: b, tooltip: x, tooltipFormat: S, className: C, plain: w, annotations: T, labels: E, onSelect: D, fill: O = "solid", patternKind: k }) {
2707
2710
  o();
2708
- let A = s(), j = w ? null : xt(E), M = i(/* @__PURE__ */ new Set()), N = w ? He : Ve, P = h ?? (w ? 48 : 300), I = w ? !1 : b ?? e.length > 1, L = (e) => e.y ?? n, R = (e[0]?.data ?? []).map((e) => t(e)), ee = e.flatMap((e) => e.data.map((t) => L(e)(t))), te = R.length > 0, z = l === "stacked" || l === "percent", B = R.map((t, n) => e.reduce((e, t) => e + L(t)(t.data[n]), 0)), V = () => {
2711
+ let A = s(), j = w ? null : xt(E), M = i(/* @__PURE__ */ new Set()), N = w ? He : Ve, P = h ?? (w ? 48 : 300), I = w ? !1 : b ?? e.length > 1, L = (e) => e.y ?? n, R = (e[0]?.data ?? []).map((e) => t(e)), z = e.flatMap((e) => e.data.map((t) => L(e)(t))), ee = R.length > 0, B = l === "stacked" || l === "percent", V = R.map((t, n) => e.reduce((e, t) => e + L(t)(t.data[n]), 0)), te = () => {
2709
2712
  let t = F(e.map((e) => e.data.map((t) => L(e)(t))));
2710
2713
  return l === "percent" ? t.map((e) => e.map(([e, t], n) => {
2711
- let r = B[n] || 1;
2714
+ let r = V[n] || 1;
2712
2715
  return [e / r, t / r];
2713
2716
  })) : t;
2714
- }, H = z ? 0 : Math.min(0, ...ee), U = te ? Math.max(...B) : 1, W = l === "percent" ? 1 : l === "stacked" ? U : Math.max(1, ...ee), G = l === "percent" ? (e) => `${Math.round(Number(e) * 100)}%` : void 0;
2717
+ }, H = B ? 0 : Math.min(0, ...z), U = ee ? Math.max(...V) : 1, W = l === "percent" ? 1 : l === "stacked" ? U : Math.max(1, ...z), G = l === "percent" ? (e) => `${Math.round(Number(e) * 100)}%` : void 0;
2715
2718
  return /* @__PURE__ */ p("div", {
2716
2719
  style: {
2717
2720
  display: "flex",
@@ -2729,13 +2732,13 @@ function an({ series: e, x: t, y: n, title: r, description: a, orientation: c =
2729
2732
  /* @__PURE__ */ f("tbody", { children: R.map((t, n) => /* @__PURE__ */ p("tr", { children: [/* @__PURE__ */ f("td", { children: t }), e.map((e) => /* @__PURE__ */ f("td", { children: e.data[n] == null ? "" : L(e)(e.data[n]) }, e.id))] }, t)) })
2730
2733
  ] }),
2731
2734
  className: C,
2732
- "data-state": te ? void 0 : "empty",
2735
+ "data-state": ee ? void 0 : "empty",
2733
2736
  plain: w,
2734
- tooltip: x && te ? ({ width: n, height: r }) => {
2735
- if (!x || !te) return;
2737
+ tooltip: x && ee ? ({ width: n, height: r }) => {
2738
+ if (!x || !ee) return;
2736
2739
  let i = n - N.left - N.right, a = r - N.top - N.bottom, o = c === "vertical", s = g(R, o ? [0, i] : [0, a], .2), u = m([H, W], o ? [a, 0] : [0, i]), d = e.filter((e) => !M.value.has(e.id)), f = [];
2737
- z && (f = V());
2738
- let p = z && !S, h = R.map((t, n) => {
2740
+ B && (f = te());
2741
+ let p = B && !S, h = R.map((t, n) => {
2739
2742
  let r = d.map((t) => ({
2740
2743
  label: t.label,
2741
2744
  value: L(t)(t.data[n]),
@@ -2749,7 +2752,7 @@ function an({ series: e, x: t, y: n, title: r, description: a, orientation: c =
2749
2752
  let r = e.indexOf(n), i = l === "grouped" ? s.bandwidth / d.length : s.bandwidth;
2750
2753
  return n.data.map((e, a) => {
2751
2754
  let c = s.map(t(e)) ?? 0, m, g;
2752
- if (z && f[r]) {
2755
+ if (B && f[r]) {
2753
2756
  let e = f[r][a];
2754
2757
  m = e[1], g = e[0];
2755
2758
  } else m = L(n)(e), g = H;
@@ -2773,7 +2776,7 @@ function an({ series: e, x: t, y: n, title: r, description: a, orientation: c =
2773
2776
  onSelect: D,
2774
2777
  children: ({ width: n, height: r }) => {
2775
2778
  let i = n - N.left - N.right, a = r - N.top - N.bottom, o = c === "vertical", s = g(R, o ? [0, i] : [0, a], .2), u = m([H, W], o ? [a, 0] : [0, i]), h = e.filter((e) => !M.value.has(e.id)), b = [];
2776
- return z && (b = V()), /* @__PURE__ */ p("g", { children: [O !== "solid" && /* @__PURE__ */ f(Dt, {
2779
+ return B && (b = te()), /* @__PURE__ */ p("g", { children: [O !== "solid" && /* @__PURE__ */ f(Dt, {
2777
2780
  prefix: A,
2778
2781
  fill: O,
2779
2782
  patternKind: k,
@@ -2806,13 +2809,13 @@ function an({ series: e, x: t, y: n, title: r, description: a, orientation: c =
2806
2809
  let i = n.color ?? nn[e.indexOf(n) % nn.length], a = e.indexOf(n), c = l === "grouped" ? s.bandwidth / h.length : s.bandwidth;
2807
2810
  return n.data.map((e, d) => {
2808
2811
  let m = s.map(t(e)) ?? 0, h, g;
2809
- if (z && b[a]) {
2812
+ if (B && b[a]) {
2810
2813
  let e = b[a][d];
2811
2814
  h = e[1], g = e[0];
2812
2815
  } else h = L(n)(e), g = H;
2813
2816
  let _ = m + (l === "grouped" ? r * c : 0), v = Math.min(u.map(h), u.map(g)), y = Math.abs(u.map(h) - u.map(g)), x = null;
2814
2817
  if (j) {
2815
- let t = j.format(L(n)(e)), r = _ + c / 2, i = z || y < 18 || v < 14;
2818
+ let t = j.format(L(n)(e)), r = _ + c / 2, i = B || y < 18 || v < 14;
2816
2819
  if (o) x = /* @__PURE__ */ f(St, {
2817
2820
  x: r,
2818
2821
  y: i ? v + 13 : v - 4,
@@ -2829,7 +2832,7 @@ function an({ series: e, x: t, y: n, title: r, description: a, orientation: c =
2829
2832
  tone: i ? "muted" : "default"
2830
2833
  });
2831
2834
  }
2832
- z && y < 14 && (x = null);
2835
+ B && y < 14 && (x = null);
2833
2836
  }
2834
2837
  return /* @__PURE__ */ p("g", { children: [o ? /* @__PURE__ */ f("rect", {
2835
2838
  x: _,
@@ -3030,7 +3033,7 @@ function un({ series: e, title: t, description: n, r = 4, width: a, height: s, x
3030
3033
  let w = i(/* @__PURE__ */ new Set()), T = _ ? He : Ve, E = s ?? (_ ? 48 : 300), D = _ ? !1 : u ?? e.length > 1, O = e.reduce((e, t) => e + t.data.length, 0), k = !S && (x === "canvas" || x === "auto" && O > 2e3), A = i([S?.min ?? 0, S?.max ?? 1]), j = i(/* @__PURE__ */ new Set()), M = (t, { width: n, height: i }) => {
3031
3034
  let a = n - T.left - T.right, o = i - T.top - T.bottom;
3032
3035
  if (a <= 0 || o <= 0) return;
3033
- let s = m([I, L], [0, a]), c = m([R, ee], [o, 0]);
3036
+ let s = m([I, L], [0, a]), c = m([R, z], [o, 0]);
3034
3037
  e.forEach((e, n) => {
3035
3038
  if (!w.value.has(e.id)) {
3036
3039
  t.fillStyle = Je(t, e.color ?? ln[n % ln.length]), t.globalAlpha = .7;
@@ -3040,7 +3043,7 @@ function un({ series: e, title: t, description: n, r = 4, width: a, height: s, x
3040
3043
  }
3041
3044
  }
3042
3045
  }), t.globalAlpha = 1;
3043
- }, N = e.flatMap((e) => e.data.map((e) => e.x)), P = e.flatMap((e) => e.data.map((e) => e.y)), F = N.length > 0, I = F ? Math.min(...N) : 0, L = F ? Math.max(...N) : 1, R = F ? Math.min(0, ...P) : 0, ee = F ? Math.max(...P) : 1;
3046
+ }, N = e.flatMap((e) => e.data.map((e) => e.x)), P = e.flatMap((e) => e.data.map((e) => e.y)), F = N.length > 0, I = F ? Math.min(...N) : 0, L = F ? Math.max(...N) : 1, R = F ? Math.min(0, ...P) : 0, z = F ? Math.max(...P) : 1;
3044
3047
  return /* @__PURE__ */ p("div", {
3045
3048
  style: {
3046
3049
  display: "flex",
@@ -3071,7 +3074,7 @@ function un({ series: e, title: t, description: n, r = 4, width: a, height: s, x
3071
3074
  plain: _,
3072
3075
  tooltip: h !== !1 && F ? ({ width: t, height: n }) => {
3073
3076
  if (h === !1 || !F) return;
3074
- let r = t - T.left - T.right, i = n - T.top - T.bottom, a = m([I, L], [0, r]), o = m([R, ee], [i, 0]);
3077
+ let r = t - T.left - T.right, i = n - T.top - T.bottom, a = m([I, L], [0, r]), o = m([R, z], [i, 0]);
3075
3078
  return { points: e.flatMap((e) => w.value.has(e.id) ? [] : e.data.map((t, n) => ({
3076
3079
  id: `${e.id}-${n}`,
3077
3080
  cx: T.left + a.map(t.x),
@@ -3090,7 +3093,7 @@ function un({ series: e, title: t, description: n, r = 4, width: a, height: s, x
3090
3093
  A.value = [S.min, S.max], j.value = /* @__PURE__ */ new Set();
3091
3094
  } : void 0,
3092
3095
  children: ({ width: t, height: n }) => {
3093
- let i = t - T.left - T.right, a = n - T.top - T.bottom, o = m([I, L], [0, i]), s = m([R, ee], [a, 0]);
3096
+ let i = t - T.left - T.right, a = n - T.top - T.bottom, o = m([I, L], [0, i]), s = m([R, z], [a, 0]);
3094
3097
  return /* @__PURE__ */ f("g", { children: /* @__PURE__ */ p("g", {
3095
3098
  transform: `translate(${T.left},${T.top})`,
3096
3099
  children: [
@@ -3368,7 +3371,7 @@ function hn({ value: e, label: t, delta: n, deltaLabel: r, icon: i, sparkline: a
3368
3371
  //#region src/charts/histogram/histogram.tsx
3369
3372
  function gn({ data: e, bins: t, title: n, label: r, description: i, width: a, height: s, className: c, plain: l }) {
3370
3373
  o();
3371
- let u = l ? He : Ve, h = s ?? (l ? 48 : 300), g = V(e, t), _ = g.reduce((e, t) => Math.max(e, t.count), 0);
3374
+ let u = l ? He : Ve, h = s ?? (l ? 48 : 300), g = te(e, t), _ = g.reduce((e, t) => Math.max(e, t.count), 0);
3372
3375
  return /* @__PURE__ */ f(Q, {
3373
3376
  title: n,
3374
3377
  description: i,
@@ -4988,4 +4991,4 @@ function Qn({ value: e, min: t = 0, max: n = 100, thresholds: r, unit: i = "", s
4988
4991
  });
4989
4992
  }
4990
4993
  //#endregion
4991
- export { tn as AreaChart, $ as Axis, an as BarChart, vn as Boxplot, Pt as Brush, Sn as BubbleChart, Mn as Bullet, qn as Calendar, Jn as Candlestick, qe as CanvasLayer, Dt as ChartDefs, Q as ChartFrame, Cn as ComboChart, Ve as DEFAULT_MARGINS, St as DataLabel, Ft as DataZoom, In as Funnel, Qn as Gauge, kt as Glyph, pt as GridLines, wn as Heatmap, gn as Histogram, hn as Kpi, Kt as Legend, Qt as LineChart, pn as Meter, He as PLAIN_MARGINS, cn as PieChart, Xn as Polar, An as Radar, Pn as RadialBar, Hn as Sankey, un as ScatterChart, dn as Sparkline, Rn as Stream, Bn as Sunburst, Nt as Text, et as Toolbox, En as Treemap, Wt as VisualMap, lt as _syncGroupCount, Ee as aggregate, be as angleBand, yt as annotationSummary, P as arcPath, N as areaPath, g as bandScale, De as bin, V as binValues, ze as bindStream, H as boxStats, z as cellPath, Ie as decimate, he as divergingRamp, it as download, Me as encode, Ne as encodeCategory, U as extent, Et as fillFor, Se as filter, st as getSyncGroup, Ot as glyphPath, wt as gradientId, Qe as isZoomed, T as linePath, m as linearScale, ie as linkPath, v as logScale, Pe as lttb, Ht as mapVisual, X as maxDepth, Fe as minmax, L as nearestIndex, h as niceTicks, Ze as panWindow, re as partition, Tt as patternId, Vt as pieceIndex, ye as polarPoint, C as quantize, xe as radiusScale, ve as rampLightness, ge as rampOf, _e as rampStops, Ae as regression, ct as releaseSyncGroup, _t as renderAnnotation, vt as renderAnnotations, Je as resolveColor, xt as resolveLabels, Z as sankeyLayout, me as sequentialRamp, nt as serializeSvg, we as sort, w as splitDefined, _ as sqrtScale, q as squarify, F as stackSeries, J as streamExtent, ne as streamLayout, Y as sumValue, rt as svgToPngBlob, S as timeScale, I as toStackedSeries, Be as useChartSize, Re as useStreamSeries, Ut as visualVisible, te as voronoiCells, R as voronoiFind, Mt as wrapText, Xe as zoomWindow };
4994
+ export { tn as AreaChart, $ as Axis, an as BarChart, vn as Boxplot, Pt as Brush, Sn as BubbleChart, Mn as Bullet, qn as Calendar, Jn as Candlestick, qe as CanvasLayer, Dt as ChartDefs, Q as ChartFrame, Cn as ComboChart, Ve as DEFAULT_MARGINS, St as DataLabel, Ft as DataZoom, In as Funnel, Qn as Gauge, kt as Glyph, pt as GridLines, wn as Heatmap, gn as Histogram, hn as Kpi, Kt as Legend, Qt as LineChart, pn as Meter, He as PLAIN_MARGINS, cn as PieChart, Xn as Polar, An as Radar, Pn as RadialBar, Hn as Sankey, un as ScatterChart, dn as Sparkline, Rn as Stream, Bn as Sunburst, Nt as Text, et as Toolbox, En as Treemap, Wt as VisualMap, lt as _syncGroupCount, Ee as aggregate, be as angleBand, yt as annotationSummary, P as arcPath, N as areaPath, g as bandScale, De as bin, te as binValues, ze as bindStream, H as boxStats, B as cellPath, Ie as decimate, he as divergingRamp, it as download, Me as encode, Ne as encodeCategory, U as extent, Et as fillFor, Se as filter, st as getSyncGroup, Ot as glyphPath, wt as gradientId, Qe as isZoomed, T as linePath, m as linearScale, ie as linkPath, v as logScale, Pe as lttb, Ht as mapVisual, X as maxDepth, Fe as minmax, L as nearestIndex, h as niceTicks, Ze as panWindow, re as partition, Tt as patternId, Vt as pieceIndex, ye as polarPoint, C as quantize, xe as radiusScale, ve as rampLightness, ge as rampOf, _e as rampStops, Ae as regression, ct as releaseSyncGroup, _t as renderAnnotation, vt as renderAnnotations, Je as resolveColor, xt as resolveLabels, Z as sankeyLayout, me as sequentialRamp, nt as serializeSvg, we as sort, w as splitDefined, _ as sqrtScale, q as squarify, F as stackSeries, J as streamExtent, ne as streamLayout, Y as sumValue, rt as svgToPngBlob, S as timeScale, I as toStackedSeries, Be as useChartSize, Re as useStreamSeries, Ut as visualVisible, ee as voronoiCells, R as voronoiFind, Mt as wrapText, Xe as zoomWindow };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cascivo/charts",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
- "description": "Chart components built from scratch — scales, shapes, and signal-driven rendering, zero dependencies",
5
+ "description": "Chart components built from scratch — scales, shapes, and signal-driven rendering, zero dependencies. Colors come from @cascivo/themes; components from @cascivo/react. Docs offline: npx @cascivo/docs",
6
6
  "keywords": [
7
7
  "cascivo",
8
8
  "charts",
@@ -44,8 +44,8 @@
44
44
  "provenance": true
45
45
  },
46
46
  "dependencies": {
47
- "@cascivo/core": "^0.5.1",
48
- "@cascivo/i18n": "^0.2.9"
47
+ "@cascivo/core": "^0.5.2",
48
+ "@cascivo/i18n": "^0.2.10"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@preact/signals": "^2",
package/readme.body.md CHANGED
@@ -1,5 +1,7 @@
1
1
  Accessible, signal-driven chart library for cascivo — AreaChart, BarChart, LineChart, Sparkline, Heatmap, and more. All charts are keyboard-navigable with `aria-live` tooltips. CVD-safe palettes (Okabe-Ito, oklch) verified in CI across all {{count.themes}} themes.
2
2
 
3
+ > **Docs offline?** The full cascivo reference ships as an npm package — `npx -y @cascivo/docs`, no website needed.
4
+
3
5
  ## Install
4
6
 
5
7
  ```sh
@@ -31,6 +33,24 @@ export function Traffic() {
31
33
  Charts are CSS-token-themed: drop them inside any element carrying a `data-theme` (or import a
32
34
  theme stylesheet) and they pick up the same palette, radii, and typography as the rest of cascivo.
33
35
 
36
+ ### Sizing — responsive by default
37
+
38
+ **Omit `width`** and the chart fills and tracks its container (a `ResizeObserver`
39
+ watches the slot), so a chart drops cleanly into a responsive `Card` or grid cell with
40
+ no measuring on your part. `height` defaults to `300` (px); set it to change the aspect.
41
+
42
+ Pass an explicit `width` only for a fixed-size export — and even then it is **clamped to
43
+ the container** (`max-inline-size: 100%`), so an over-wide `width` scales down instead of
44
+ overflowing and clipping data. To size another element to match a chart, or to build a
45
+ custom chart, use the exported `useChartSize()` hook.
46
+
47
+ ```tsx
48
+ <Card>
49
+ <LineChart data={data} /> {/* fills the card, resizes with it */}
50
+ </Card>
51
+ <LineChart data={data} height={160} /> {/* shorter, still full-width */}
52
+ ```
53
+
34
54
  > **Vite SSR (TanStack Start, Remix, vite-ssr, workerd)?** Like the rest of cascivo, the
35
55
  > chart CSS ships as side-effect imports a bare server loader can't resolve — mark
36
56
  > `ssr: { noExternal: [/^@cascivo\//] }` (the pattern already covers `@cascivo/charts`) and