@quantumwake/terminal-ux-dashboard-components 0.1.21 → 0.1.23

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
@@ -323,9 +323,14 @@ declare function PieView({ records, groupColumn, data: presetData, style }: PieV
323
323
 
324
324
  interface LineSerie {
325
325
  id: string;
326
+ /** lo/hi (optional, per point) draw a soft envelope band behind the
327
+ * line — the reading for "this line summarizes several": the band is
328
+ * the min–max spread of what it aggregates. */
326
329
  data: {
327
330
  x: string;
328
331
  y: number;
332
+ lo?: number;
333
+ hi?: number;
329
334
  }[];
330
335
  }
331
336
  interface LineViewProps {
@@ -334,12 +339,9 @@ interface LineViewProps {
334
339
  yColumn: string;
335
340
  /** Pre-shaped Nivo line series bypasses client-side processing. */
336
341
  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
342
  style?: Partial<ChartStyle>;
341
343
  }
342
- declare function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }: LineViewProps): react.JSX.Element;
344
+ declare function LineView({ records, xColumn, yColumn, data: presetData, style }: LineViewProps): react.JSX.Element;
343
345
 
344
346
  interface SparklineViewProps {
345
347
  /** The series, oldest first. */
@@ -348,8 +350,13 @@ interface SparklineViewProps {
348
350
  height?: number;
349
351
  /** Line + area hue. */
350
352
  color?: string;
353
+ /** Show the CURRENT (last) value as a readout over the mark — a trend
354
+ * shape without its number answers "which way", never "how much". */
355
+ showValue?: boolean;
356
+ /** Formats the readout (e.g. v => `${v.toFixed(1)} ms`). Default: locale. */
357
+ format?: (v: number) => string;
351
358
  }
352
- declare function SparklineView({ data, height, color }: SparklineViewProps): react.JSX.Element;
359
+ declare function SparklineView({ data, height, color, showValue, format }: SparklineViewProps): react.JSX.Element;
353
360
 
354
361
  interface ScatterSerie {
355
362
  id: string;
package/dist/index.d.ts CHANGED
@@ -323,9 +323,14 @@ declare function PieView({ records, groupColumn, data: presetData, style }: PieV
323
323
 
324
324
  interface LineSerie {
325
325
  id: string;
326
+ /** lo/hi (optional, per point) draw a soft envelope band behind the
327
+ * line — the reading for "this line summarizes several": the band is
328
+ * the min–max spread of what it aggregates. */
326
329
  data: {
327
330
  x: string;
328
331
  y: number;
332
+ lo?: number;
333
+ hi?: number;
329
334
  }[];
330
335
  }
331
336
  interface LineViewProps {
@@ -334,12 +339,9 @@ interface LineViewProps {
334
339
  yColumn: string;
335
340
  /** Pre-shaped Nivo line series bypasses client-side processing. */
336
341
  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
342
  style?: Partial<ChartStyle>;
341
343
  }
342
- declare function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }: LineViewProps): react.JSX.Element;
344
+ declare function LineView({ records, xColumn, yColumn, data: presetData, style }: LineViewProps): react.JSX.Element;
343
345
 
344
346
  interface SparklineViewProps {
345
347
  /** The series, oldest first. */
@@ -348,8 +350,13 @@ interface SparklineViewProps {
348
350
  height?: number;
349
351
  /** Line + area hue. */
350
352
  color?: string;
353
+ /** Show the CURRENT (last) value as a readout over the mark — a trend
354
+ * shape without its number answers "which way", never "how much". */
355
+ showValue?: boolean;
356
+ /** Formats the readout (e.g. v => `${v.toFixed(1)} ms`). Default: locale. */
357
+ format?: (v: number) => string;
351
358
  }
352
- declare function SparklineView({ data, height, color }: SparklineViewProps): react.JSX.Element;
359
+ declare function SparklineView({ data, height, color, showValue, format }: SparklineViewProps): react.JSX.Element;
353
360
 
354
361
  interface ScatterSerie {
355
362
  id: string;
package/dist/index.js CHANGED
@@ -644,7 +644,7 @@ function PieView({ records, groupColumn, data: presetData, style }) {
644
644
  }
645
645
  ) });
646
646
  }
647
- function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }) {
647
+ function LineView({ records, xColumn, yColumn, data: presetData, style }) {
648
648
  const computed = useMemo(() => {
649
649
  if (presetData || !records) return [];
650
650
  const sorted = [...records].filter((r) => r[xColumn] != null && r[yColumn] != null).sort((a, b) => {
@@ -666,16 +666,23 @@ function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, styl
666
666
  ]));
667
667
  const longest = data.reduce((a, b) => b.data.length > a.data.length ? b : a, { id: "", data: [] });
668
668
  const tickValues = thinTicks(longest.data.map((d) => d.x), s.maxXTicks);
669
- const dashed = new Set(dashedIds || []);
669
+ const bandedIds = new Set(data.filter((serie) => serie.data.some((d) => d.lo != null)).map((serie) => serie.id));
670
+ const bandsLayer = ({ series, yScale, lineGenerator }) => /* @__PURE__ */ jsx(Fragment, { children: series.map((serie) => {
671
+ const pts = serie.data.filter((d) => d.data.lo != null && d.data.hi != null && d.position.x != null);
672
+ if (pts.length < 2) return null;
673
+ const upper = lineGenerator(pts.map((d) => ({ x: d.position.x, y: yScale(d.data.hi) })));
674
+ const lower = lineGenerator([...pts].reverse().map((d) => ({ x: d.position.x, y: yScale(d.data.lo) })));
675
+ if (!upper || !lower) return null;
676
+ return /* @__PURE__ */ jsx("path", { d: `${upper} L ${lower.slice(1)} Z`, fill: serie.color, opacity: 0.12 }, `band-${serie.id}`);
677
+ }) });
670
678
  const linesLayer = ({ series, lineGenerator }) => /* @__PURE__ */ jsx(Fragment, { children: series.map((serie) => /* @__PURE__ */ jsx(
671
679
  "path",
672
680
  {
673
681
  d: lineGenerator(serie.data.map((d) => d.position)),
674
682
  fill: "none",
675
683
  stroke: serie.color,
676
- strokeWidth: 2,
677
- strokeLinecap: "round",
678
- strokeDasharray: dashed.has(String(serie.id)) ? "1 5" : void 0
684
+ strokeWidth: bandedIds.has(String(serie.id)) ? 2.5 : 1.5,
685
+ strokeLinecap: "round"
679
686
  },
680
687
  serie.id
681
688
  )) });
@@ -698,12 +705,12 @@ function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, styl
698
705
  axisBottom: { ...makeAxis(style, "x", xColumn), ...tickValues ? { tickValues } : {} },
699
706
  axisLeft: makeAxis(style, "y", yColumn, { numeric: true }),
700
707
  useMesh: true,
701
- layers: ["grid", "markers", "axes", "areas", linesLayer, "crosshair", "slices", "mesh", "legends"],
708
+ layers: ["grid", "markers", "axes", "areas", bandsLayer, linesLayer, "crosshair", "slices", "mesh", "legends"],
702
709
  theme: buildNivoTheme(style)
703
710
  }
704
711
  ) });
705
712
  }
706
- function SparklineView({ data, height = 56, color = "#3987e5" }) {
713
+ function SparklineView({ data, height = 56, color = "#3987e5", showValue = false, format }) {
707
714
  const gradientId = useId();
708
715
  const width = 260;
709
716
  const pts = data && data.length ? data : [0];
@@ -712,13 +719,18 @@ function SparklineView({ data, height = 56, color = "#3987e5" }) {
712
719
  const xy = (v, i) => [i * dx, height - v / max * (height - 4) - 2];
713
720
  const line = pts.map((v, i) => `${i === 0 ? "M" : "L"} ${xy(v, i)[0].toFixed(1)} ${xy(v, i)[1].toFixed(1)}`).join(" ");
714
721
  const area = `${line} L ${width} ${height} L 0 ${height} Z`;
715
- return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${width} ${height}`, height, className: "w-full", preserveAspectRatio: "none", children: [
716
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
717
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.25" }),
718
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
719
- ] }) }),
720
- /* @__PURE__ */ jsx("path", { d: area, fill: `url(#${gradientId})` }),
721
- /* @__PURE__ */ jsx("path", { d: line, fill: "none", stroke: color, strokeWidth: "2", vectorEffect: "non-scaling-stroke" })
722
+ const current = pts[pts.length - 1];
723
+ const readout = format ? format(current) : current.toLocaleString(void 0, { maximumFractionDigits: 1 });
724
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
725
+ /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${width} ${height}`, height, className: "w-full", preserveAspectRatio: "none", children: [
726
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
727
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.25" }),
728
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
729
+ ] }) }),
730
+ /* @__PURE__ */ jsx("path", { d: area, fill: `url(#${gradientId})` }),
731
+ /* @__PURE__ */ jsx("path", { d: line, fill: "none", stroke: color, strokeWidth: "2", vectorEffect: "non-scaling-stroke" })
732
+ ] }),
733
+ showValue && /* @__PURE__ */ jsx("span", { className: "absolute right-1 top-0 font-mono text-lg text-midnight-text-primary", children: readout })
722
734
  ] });
723
735
  }
724
736
  function ScatterView({ records, xColumn, yColumn, data: presetData, style }) {