@quantumwake/terminal-ux-dashboard-components 0.1.22 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -146,6 +146,7 @@ interface ChartStyle {
146
146
  maxXTicks: number;
147
147
  maxYTicks: number;
148
148
  areaOpacity: number;
149
+ yFromZero: boolean;
149
150
  barLabels: boolean;
150
151
  seriesColors: string[];
151
152
  }
@@ -323,9 +324,14 @@ declare function PieView({ records, groupColumn, data: presetData, style }: PieV
323
324
 
324
325
  interface LineSerie {
325
326
  id: string;
327
+ /** lo/hi (optional, per point) draw a soft envelope band behind the
328
+ * line — the reading for "this line summarizes several": the band is
329
+ * the min–max spread of what it aggregates. */
326
330
  data: {
327
331
  x: string;
328
332
  y: number;
333
+ lo?: number;
334
+ hi?: number;
329
335
  }[];
330
336
  }
331
337
  interface LineViewProps {
@@ -334,12 +340,9 @@ interface LineViewProps {
334
340
  yColumn: string;
335
341
  /** Pre-shaped Nivo line series bypasses client-side processing. */
336
342
  data?: LineSerie[];
337
- /** Serie ids to draw dotted — the aggregate-vs-individual distinction
338
- * (an average line reads as derived, a member line as observed). */
339
- dashedIds?: string[];
340
343
  style?: Partial<ChartStyle>;
341
344
  }
342
- declare function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }: LineViewProps): react.JSX.Element;
345
+ declare function LineView({ records, xColumn, yColumn, data: presetData, style }: LineViewProps): react.JSX.Element;
343
346
 
344
347
  interface SparklineViewProps {
345
348
  /** The series, oldest first. */
package/dist/index.d.ts CHANGED
@@ -146,6 +146,7 @@ interface ChartStyle {
146
146
  maxXTicks: number;
147
147
  maxYTicks: number;
148
148
  areaOpacity: number;
149
+ yFromZero: boolean;
149
150
  barLabels: boolean;
150
151
  seriesColors: string[];
151
152
  }
@@ -323,9 +324,14 @@ declare function PieView({ records, groupColumn, data: presetData, style }: PieV
323
324
 
324
325
  interface LineSerie {
325
326
  id: string;
327
+ /** lo/hi (optional, per point) draw a soft envelope band behind the
328
+ * line — the reading for "this line summarizes several": the band is
329
+ * the min–max spread of what it aggregates. */
326
330
  data: {
327
331
  x: string;
328
332
  y: number;
333
+ lo?: number;
334
+ hi?: number;
329
335
  }[];
330
336
  }
331
337
  interface LineViewProps {
@@ -334,12 +340,9 @@ interface LineViewProps {
334
340
  yColumn: string;
335
341
  /** Pre-shaped Nivo line series bypasses client-side processing. */
336
342
  data?: LineSerie[];
337
- /** Serie ids to draw dotted — the aggregate-vs-individual distinction
338
- * (an average line reads as derived, a member line as observed). */
339
- dashedIds?: string[];
340
343
  style?: Partial<ChartStyle>;
341
344
  }
342
- declare function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }: LineViewProps): react.JSX.Element;
345
+ declare function LineView({ records, xColumn, yColumn, data: presetData, style }: LineViewProps): react.JSX.Element;
343
346
 
344
347
  interface SparklineViewProps {
345
348
  /** The series, oldest first. */
package/dist/index.js CHANGED
@@ -275,6 +275,7 @@ var DEFAULT_CHART_STYLE = {
275
275
  maxXTicks: 0,
276
276
  maxYTicks: 0,
277
277
  areaOpacity: 0.15,
278
+ yFromZero: false,
278
279
  barLabels: true,
279
280
  seriesColors: []
280
281
  };
@@ -644,7 +645,7 @@ function PieView({ records, groupColumn, data: presetData, style }) {
644
645
  }
645
646
  ) });
646
647
  }
647
- function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }) {
648
+ function LineView({ records, xColumn, yColumn, data: presetData, style }) {
648
649
  const computed = useMemo(() => {
649
650
  if (presetData || !records) return [];
650
651
  const sorted = [...records].filter((r) => r[xColumn] != null && r[yColumn] != null).sort((a, b) => {
@@ -666,16 +667,28 @@ function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, styl
666
667
  ]));
667
668
  const longest = data.reduce((a, b) => b.data.length > a.data.length ? b : a, { id: "", data: [] });
668
669
  const tickValues = thinTicks(longest.data.map((d) => d.x), s.maxXTicks);
669
- const dashed = new Set(dashedIds || []);
670
+ let yScale = { type: "linear", min: "auto", max: "auto" };
671
+ if (s.yFromZero) {
672
+ const dataMax = Math.max(0, ...data.flatMap((serie) => serie.data.map((d) => Math.max(d.y, d.hi ?? d.y))));
673
+ yScale = { type: "linear", min: 0, max: niceCeil(dataMax) };
674
+ }
675
+ const bandedIds = new Set(data.filter((serie) => serie.data.some((d) => d.lo != null)).map((serie) => serie.id));
676
+ const bandsLayer = ({ series, yScale: yScale2, lineGenerator }) => /* @__PURE__ */ jsx(Fragment, { children: series.map((serie) => {
677
+ const pts = serie.data.filter((d) => d.data.lo != null && d.data.hi != null && d.position.x != null);
678
+ if (pts.length < 2) return null;
679
+ const upper = lineGenerator(pts.map((d) => ({ x: d.position.x, y: yScale2(d.data.hi) })));
680
+ const lower = lineGenerator([...pts].reverse().map((d) => ({ x: d.position.x, y: yScale2(d.data.lo) })));
681
+ if (!upper || !lower) return null;
682
+ return /* @__PURE__ */ jsx("path", { d: `${upper} L ${lower.slice(1)} Z`, fill: serie.color, opacity: 0.12 }, `band-${serie.id}`);
683
+ }) });
670
684
  const linesLayer = ({ series, lineGenerator }) => /* @__PURE__ */ jsx(Fragment, { children: series.map((serie) => /* @__PURE__ */ jsx(
671
685
  "path",
672
686
  {
673
687
  d: lineGenerator(serie.data.map((d) => d.position)),
674
688
  fill: "none",
675
689
  stroke: serie.color,
676
- strokeWidth: 2,
677
- strokeLinecap: "round",
678
- strokeDasharray: dashed.has(String(serie.id)) ? "1 5" : void 0
690
+ strokeWidth: bandedIds.has(String(serie.id)) ? 2.5 : 1.5,
691
+ strokeLinecap: "round"
679
692
  },
680
693
  serie.id
681
694
  )) });
@@ -685,7 +698,7 @@ function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, styl
685
698
  data,
686
699
  margin,
687
700
  xScale: { type: "point" },
688
- yScale: { type: "linear", min: "auto", max: "auto" },
701
+ yScale,
689
702
  curve: "monotoneX",
690
703
  enableArea: s.areaOpacity > 0,
691
704
  areaOpacity: s.areaOpacity,
@@ -698,11 +711,20 @@ function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, styl
698
711
  axisBottom: { ...makeAxis(style, "x", xColumn), ...tickValues ? { tickValues } : {} },
699
712
  axisLeft: makeAxis(style, "y", yColumn, { numeric: true }),
700
713
  useMesh: true,
701
- layers: ["grid", "markers", "axes", "areas", linesLayer, "crosshair", "slices", "mesh", "legends"],
714
+ layers: ["grid", "markers", "axes", "areas", bandsLayer, linesLayer, "crosshair", "slices", "mesh", "legends"],
702
715
  theme: buildNivoTheme(style)
703
716
  }
704
717
  ) });
705
718
  }
719
+ function niceCeil(v) {
720
+ if (v <= 0) return 1;
721
+ const padded = v * 1.05;
722
+ const mag = Math.pow(10, Math.floor(Math.log10(padded)));
723
+ for (const step of [1, 2, 5, 10]) {
724
+ if (padded <= step * mag) return step * mag;
725
+ }
726
+ return 10 * mag;
727
+ }
706
728
  function SparklineView({ data, height = 56, color = "#3987e5", showValue = false, format }) {
707
729
  const gradientId = useId();
708
730
  const width = 260;