@cascivo/charts 0.18.0 → 1.0.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.
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { i as e, l as t, t as n } from "./chart-frame.module-CkOcXGSL.js";
3
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ //#region src/core/mini-frame.tsx
5
+ var o = {
6
+ position: "absolute",
7
+ insetInlineStart: "-9999px",
8
+ inlineSize: "1px",
9
+ blockSize: "1px",
10
+ overflow: "hidden",
11
+ clipPath: "inset(50%)",
12
+ whiteSpace: "nowrap"
13
+ };
14
+ function s({ title: e, width: t, height: r, className: s, fallback: c, children: l }) {
15
+ return /* @__PURE__ */ a("div", {
16
+ className: [n.frame, s].filter(Boolean).join(" "),
17
+ "data-plain": "",
18
+ children: [/* @__PURE__ */ i("svg", {
19
+ role: "img",
20
+ "aria-label": e,
21
+ width: t,
22
+ height: r,
23
+ viewBox: `0 0 ${t} ${r}`,
24
+ children: l
25
+ }), c && /* @__PURE__ */ i("div", {
26
+ className: n.fallback,
27
+ style: o,
28
+ children: c
29
+ })]
30
+ });
31
+ }
32
+ //#endregion
33
+ //#region src/charts/sparkline/sparkline-lite.tsx
34
+ function c({ data: n, width: o = 120, height: c = 32, label: l, ariaLabel: u, color: d = "var(--cascivo-chart-1)", endDot: f = !0, className: p }) {
35
+ let m = (() => {
36
+ if (n.length === 0) return [];
37
+ let e = t([0, n.length - 1], [2, o - 2]), r = Math.min(...n), i = Math.max(...n), a = t([r === i ? r - 1 : r, i], [c - 2, 2]);
38
+ return n.map((t, n) => [e.map(n), a.map(t)]);
39
+ })(), h = m[m.length - 1];
40
+ return /* @__PURE__ */ i(s, {
41
+ title: l ?? u,
42
+ width: o,
43
+ height: c,
44
+ ...p === void 0 ? {} : { className: p },
45
+ children: m.length > 0 && /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i("path", {
46
+ d: e(m, "monotone"),
47
+ fill: "none",
48
+ stroke: d,
49
+ strokeWidth: 1.5,
50
+ strokeLinecap: "round",
51
+ strokeLinejoin: "round"
52
+ }), f && h && /* @__PURE__ */ i("circle", {
53
+ cx: h[0],
54
+ cy: h[1],
55
+ r: 2.5,
56
+ fill: d
57
+ })] })
58
+ });
59
+ }
60
+ //#endregion
61
+ export { c as Sparkline };
@@ -0,0 +1,43 @@
1
+ interface SparklineLiteBaseProps {
2
+ data: readonly number[];
3
+ /**
4
+ * SVG width in px. **This chart is fixed-width by default** — it is a compact, inline
5
+ * chart meant to sit in a table cell or beside a label, so omitting `width` gives you
6
+ * 120px rather than a container-filling chart.
7
+ *
8
+ * @defaultValue `120`
9
+ */
10
+ width?: number;
11
+ height?: number;
12
+ color?: string;
13
+ /**
14
+ * Show dot at last data point
15
+ *
16
+ * @defaultValue `true`
17
+ */
18
+ endDot?: boolean;
19
+ className?: string;
20
+ }
21
+ /**
22
+ * Exactly one of `label` / `ariaLabel` is required — a chart with no accessible name is a
23
+ * bug, so this stays enforced by the type. `ariaLabel` is the catalog's convention for an
24
+ * invisible accessible name; `Sparkline` predates it and shipped `label`, so both work.
25
+ */
26
+ type SparklineLiteProps = SparklineLiteBaseProps & ({
27
+ label: string;
28
+ ariaLabel?: never;
29
+ } | {
30
+ ariaLabel: string;
31
+ label?: never;
32
+ });
33
+ declare function Sparkline({
34
+ data,
35
+ width,
36
+ height,
37
+ label,
38
+ ariaLabel,
39
+ color,
40
+ endDot,
41
+ className
42
+ }: SparklineLiteProps): import("react").JSX.Element;
43
+ export { Sparkline, type SparklineLiteProps as SparklineProps };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import './charts.css';
3
+ import { i as e, l as t, t as n } from "./chart-frame.module-CkOcXGSL.js";
4
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/core/mini-frame.tsx
6
+ var o = {
7
+ position: "absolute",
8
+ insetInlineStart: "-9999px",
9
+ inlineSize: "1px",
10
+ blockSize: "1px",
11
+ overflow: "hidden",
12
+ clipPath: "inset(50%)",
13
+ whiteSpace: "nowrap"
14
+ };
15
+ function s({ title: e, width: t, height: r, className: s, fallback: c, children: l }) {
16
+ return /* @__PURE__ */ a("div", {
17
+ className: [n.frame, s].filter(Boolean).join(" "),
18
+ "data-plain": "",
19
+ children: [/* @__PURE__ */ i("svg", {
20
+ role: "img",
21
+ "aria-label": e,
22
+ width: t,
23
+ height: r,
24
+ viewBox: `0 0 ${t} ${r}`,
25
+ children: l
26
+ }), c && /* @__PURE__ */ i("div", {
27
+ className: n.fallback,
28
+ style: o,
29
+ children: c
30
+ })]
31
+ });
32
+ }
33
+ //#endregion
34
+ //#region src/charts/sparkline/sparkline-lite.tsx
35
+ function c({ data: n, width: o = 120, height: c = 32, label: l, ariaLabel: u, color: d = "var(--cascivo-chart-1)", endDot: f = !0, className: p }) {
36
+ let m = (() => {
37
+ if (n.length === 0) return [];
38
+ let e = t([0, n.length - 1], [2, o - 2]), r = Math.min(...n), i = Math.max(...n), a = t([r === i ? r - 1 : r, i], [c - 2, 2]);
39
+ return n.map((t, n) => [e.map(n), a.map(t)]);
40
+ })(), h = m[m.length - 1];
41
+ return /* @__PURE__ */ i(s, {
42
+ title: l ?? u,
43
+ width: o,
44
+ height: c,
45
+ ...p === void 0 ? {} : { className: p },
46
+ children: m.length > 0 && /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i("path", {
47
+ d: e(m, "monotone"),
48
+ fill: "none",
49
+ stroke: d,
50
+ strokeWidth: 1.5,
51
+ strokeLinecap: "round",
52
+ strokeLinejoin: "round"
53
+ }), f && h && /* @__PURE__ */ i("circle", {
54
+ cx: h[0],
55
+ cy: h[1],
56
+ r: 2.5,
57
+ fill: d
58
+ })] })
59
+ });
60
+ }
61
+ //#endregion
62
+ export { c as Sparkline };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascivo/charts",
3
- "version": "0.18.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
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": [
@@ -38,6 +38,12 @@
38
38
  "import": "./dist/index.js",
39
39
  "default": "./dist/index.js"
40
40
  },
41
+ "./sparkline": {
42
+ "types": "./dist/sparkline.d.ts",
43
+ "node": "./dist/node/sparkline.js",
44
+ "import": "./dist/sparkline.js",
45
+ "default": "./dist/sparkline.js"
46
+ },
41
47
  "./styles.css": "./dist/charts.css"
42
48
  },
43
49
  "publishConfig": {
@@ -45,8 +51,8 @@
45
51
  "provenance": true
46
52
  },
47
53
  "dependencies": {
48
- "@cascivo/core": "^0.18.0",
49
- "@cascivo/i18n": "^0.18.0"
54
+ "@cascivo/core": "^1.0.0",
55
+ "@cascivo/i18n": "^1.0.0"
50
56
  },
51
57
  "devDependencies": {
52
58
  "@preact/signals": "^2",
package/readme.body.md CHANGED
@@ -63,6 +63,20 @@ The charts are signal-driven. In a plain React app (no Babel signals transform),
63
63
  from `@cascivo/core` as the first statement of any component that reads a signal during render. The
64
64
  docs app (Preact) does not need this.
65
65
 
66
+ ## One sparkline, without the engine
67
+
68
+ `import { Sparkline } from '@cascivo/charts'` pulls in the whole charting engine — tooltips, voronoi hit-testing, a canvas layer, zoom/pan, a toolbox, PNG/SVG export — because `Sparkline` is built on the same frame as every other chart. An adopter measured 44.87 kB / 14.84 kB gzip for a single trend line on a landing page.
69
+
70
+ For a page that wants a sparkline and draws no other charts, there is a subpath that does not:
71
+
72
+ ```tsx
73
+ import { Sparkline } from '@cascivo/charts/sparkline' // ~3.5 kB gzip, no engine
74
+ ```
75
+
76
+ Identical props, identical markup, identical styling — asserted by a DOM-parity test, and the size is held by a budget in CI. **One difference: no hover tooltip**, because the tooltip is what requires the engine.
77
+
78
+ Use the main entry when the page draws other charts anyway: the engine is already paid for and the subpath saves nothing.
79
+
66
80
  ## Coloring
67
81
 
68
82
  By default every slice/series/layer is colored from the positional palette