@siyahi/ui 0.1.9-next.1 → 0.1.9-next.10
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 +48 -8
- package/THIRD_PARTY_NOTICES.md +11 -10
- package/dist/components/registry/charts/area-chart-card.d.ts +4 -3
- package/dist/components/registry/charts/area-chart-card.js +2 -2
- package/dist/components/registry/charts/bar-chart-card.d.ts +7 -1
- package/dist/components/registry/charts/bar-chart-card.js +35 -14
- package/dist/components/registry/charts/line-chart-card.d.ts +5 -2
- package/dist/components/registry/charts/line-chart-card.js +2 -2
- package/dist/components/registry/dashboard-01/section-cards.d.ts +4 -0
- package/dist/components/registry/dashboard-01/section-cards.js +42 -34
- package/dist/components/registry/dashboardcn/bar-list.d.ts +3 -1
- package/dist/components/registry/dashboardcn/bar-list.js +3 -3
- package/dist/components/registry/dashboardcn/distribution-bar.d.ts +38 -0
- package/dist/components/registry/dashboardcn/distribution-bar.js +118 -0
- package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
- package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
- package/dist/components/registry/dashboardcn/sparkline.d.ts +18 -0
- package/dist/components/registry/dashboardcn/sparkline.js +95 -0
- package/dist/components/registry/minidev/copy-button.d.ts +11 -0
- package/dist/components/registry/minidev/copy-button.js +34 -0
- package/dist/components/registry/niko-table/ui/table.js +2 -2
- package/dist/components/registry/sidebar-07/nav-main.d.ts +1 -1
- package/dist/components/siyahi/data-bar.d.ts +19 -0
- package/dist/components/siyahi/data-bar.js +29 -0
- package/dist/components/siyahi/panel-grid.d.ts +22 -0
- package/dist/components/siyahi/panel-grid.js +34 -0
- package/dist/components/siyahi/siyahi-provider.d.ts +13 -2
- package/dist/components/siyahi/siyahi-provider.js +17 -4
- package/dist/components/ui/accordion.js +5 -5
- package/dist/components/ui/alert.js +2 -2
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +2 -2
- package/dist/components/ui/button.js +10 -10
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/card.js +4 -4
- package/dist/components/ui/chart.js +1 -1
- package/dist/components/ui/code-block.js +13 -12
- package/dist/components/ui/command.js +7 -6
- package/dist/components/ui/context-menu.js +7 -7
- package/dist/components/ui/dialog.js +5 -5
- package/dist/components/ui/dropdown-menu.js +8 -8
- package/dist/components/ui/input-group.js +11 -11
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/popover.js +3 -3
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/select.js +6 -6
- package/dist/components/ui/sheet.js +5 -5
- package/dist/components/ui/sidebar.js +17 -18
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +2 -2
- package/dist/components/ui/table.js +2 -2
- package/dist/components/ui/tabs.js +2 -2
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toggle-group.js +2 -2
- package/dist/components/ui/toggle.js +4 -4
- package/dist/components/ui/tooltip.js +2 -2
- package/dist/index.d.ts +12 -7
- package/dist/index.js +9 -4
- package/dist/lib/chart-frame.d.ts +18 -4
- package/dist/lib/chart-frame.js +183 -56
- package/dist/lib/chart-series.d.ts +58 -3
- package/package.json +1 -1
- package/registry.lock.json +32 -0
- package/report.css +11 -11
- package/styles/siyahi.css +53 -11
- package/dist/lib/recharts.d.ts +0 -2
- package/dist/lib/recharts.js +0 -1
package/dist/lib/chart-frame.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
|
-
import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card.js";
|
|
1
|
+
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/ui/card.js";
|
|
2
2
|
import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from "../components/ui/chart.js";
|
|
3
|
+
import { cn } from "./utils.js";
|
|
3
4
|
import { useLocale } from "../components/siyahi/siyahi-provider.js";
|
|
4
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { CartesianGrid, ReferenceLine, XAxis, YAxis } from "recharts";
|
|
6
7
|
//#region src/lib/chart-frame.tsx
|
|
8
|
+
const AXIS_TITLE = "fill-muted-foreground text-xs";
|
|
9
|
+
const TICK = { className: "fill-muted-foreground font-mono" };
|
|
10
|
+
const NO_LINES = [];
|
|
11
|
+
/**
|
|
12
|
+
* The colour a series' Bar takes, which its legend chip shows: the negative colour when every value drawn is below
|
|
13
|
+
* zero, since each bar's own Cell follows its sign but the chip follows the Bar.
|
|
14
|
+
*/
|
|
15
|
+
function seriesFill(item, data) {
|
|
16
|
+
const values = data.map((row) => row[item.key]).filter((value) => Number.isFinite(value)).map(Number);
|
|
17
|
+
return item.negativeColor && values.length > 0 && values.every((value) => value < 0) ? item.negativeColor : item.color;
|
|
18
|
+
}
|
|
7
19
|
/** A tooltip row: the series' colour and label, then its value as the page formats it, or — when the row has none. */
|
|
8
20
|
function seriesRow(series, formatValue) {
|
|
9
21
|
return (value, _name, item) => {
|
|
10
22
|
const entry = series.find(({ key }) => key === item.dataKey);
|
|
23
|
+
const color = entry?.negativeColor && Number(value) < 0 ? entry.negativeColor : entry?.color;
|
|
11
24
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12
25
|
/* @__PURE__ */ jsx("span", {
|
|
13
26
|
className: "size-2.5 shrink-0 rounded-xs",
|
|
14
|
-
style: { backgroundColor:
|
|
27
|
+
style: { backgroundColor: color }
|
|
15
28
|
}),
|
|
16
29
|
/* @__PURE__ */ jsx("span", {
|
|
17
30
|
className: "text-muted-foreground",
|
|
@@ -24,13 +37,63 @@ function seriesRow(series, formatValue) {
|
|
|
24
37
|
] });
|
|
25
38
|
};
|
|
26
39
|
}
|
|
40
|
+
const GEIST_WIDTH = 6.6;
|
|
41
|
+
const MONO_WIDTH = 7.2;
|
|
42
|
+
/**
|
|
43
|
+
* Room to keep right of the plot when every named tick is drawn: half the last label, which centres on the
|
|
44
|
+
* domain's right end, and at least 24px.
|
|
45
|
+
*/
|
|
46
|
+
function endRoom(xFormatter, xTicks) {
|
|
47
|
+
const last = xTicks.at(-1);
|
|
48
|
+
return Math.max(24, Math.ceil((last === void 0 ? 0 : xFormatter(last).length * MONO_WIDTH) / 2) + 4);
|
|
49
|
+
}
|
|
50
|
+
/** Squeezes a line into its column with SVG's own textLength when it would run into the next one. */
|
|
51
|
+
const fitTo = (text, room, charWidth) => room > 0 && text.length * charWidth > room ? {
|
|
52
|
+
textLength: room,
|
|
53
|
+
lengthAdjust: "spacingAndGlyphs"
|
|
54
|
+
} : {};
|
|
55
|
+
/**
|
|
56
|
+
* An x tick fitted to its column, drawn whenever a page names its ticks or gives each a second line: Recharts'
|
|
57
|
+
* own ticks would rather drop a label than let it run into the next. With a detail, the second line comes from the
|
|
58
|
+
* tick's row; under a column the lines hang below the axis, and beside a horizontal bar they straddle its middle.
|
|
59
|
+
* A two-line tick is set in Geist, not Mono: a name with a figure under it reads as a label, as in BarList, and
|
|
60
|
+
* sector names in Mono would take most of a phone's width.
|
|
61
|
+
*/
|
|
62
|
+
function fittedTick(data, xKey, xFormatter, detailOf, beside) {
|
|
63
|
+
const charWidth = detailOf ? GEIST_WIDTH : MONO_WIDTH;
|
|
64
|
+
return ({ x, y, width, visibleTicksCount, payload }) => {
|
|
65
|
+
const value = payload?.value;
|
|
66
|
+
const row = data.find((r) => r[xKey] === value);
|
|
67
|
+
const name = xFormatter(value);
|
|
68
|
+
const detail = row && detailOf ? detailOf(row) : null;
|
|
69
|
+
const room = beside || !visibleTicksCount ? 0 : Number(width) / visibleTicksCount - 6;
|
|
70
|
+
return /* @__PURE__ */ jsxs("text", {
|
|
71
|
+
x,
|
|
72
|
+
y,
|
|
73
|
+
textAnchor: beside ? "end" : "middle",
|
|
74
|
+
className: cn("recharts-cartesian-axis-tick-value fill-muted-foreground", !detailOf && "font-mono"),
|
|
75
|
+
children: [/* @__PURE__ */ jsx("tspan", {
|
|
76
|
+
x,
|
|
77
|
+
dy: beside ? -4 : 12,
|
|
78
|
+
...fitTo(name, room, charWidth),
|
|
79
|
+
children: name
|
|
80
|
+
}), detail !== null && /* @__PURE__ */ jsx("tspan", {
|
|
81
|
+
x,
|
|
82
|
+
dy: 15,
|
|
83
|
+
className: "tabular-nums",
|
|
84
|
+
...fitTo(detail, room, charWidth),
|
|
85
|
+
children: detail
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
}
|
|
27
90
|
/**
|
|
28
91
|
* The card, axes, grid, tooltip and legend the three chart cards share. Both
|
|
29
92
|
* axes keep Recharts' default ids: marks find their axes by id, and a page
|
|
30
93
|
* that gave its category axis its own id (dash#88) got a plot split in two
|
|
31
94
|
* and every tooltip headed with the series name instead of the category.
|
|
32
95
|
*/
|
|
33
|
-
function ChartFrame({ chart: Chart, children, title, description, action, data, xKey, series, xFormatter = String, valueFormatter, yTickFormatter, height }) {
|
|
96
|
+
function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, title, description, action, data, xKey, series, xFormatter = String, xTooltipFormatter = xFormatter, valueFormatter, yTickFormatter, yDomain, yTicks, height, xTickDetail, xLabel, yLabel, referenceLines = NO_LINES, placeholder, footer, xDomain, xTicks }) {
|
|
34
97
|
const { numberLocale } = useLocale();
|
|
35
98
|
const formatValue = valueFormatter ?? new Intl.NumberFormat(numberLocale).format;
|
|
36
99
|
const config = Object.fromEntries(series.map(({ key, label, color }) => [key, {
|
|
@@ -38,59 +101,123 @@ function ChartFrame({ chart: Chart, children, title, description, action, data,
|
|
|
38
101
|
color
|
|
39
102
|
}]));
|
|
40
103
|
const crossesZero = data.some((row) => series.some(({ key }) => Number(row[key]) < 0));
|
|
41
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
42
|
-
/* @__PURE__ */
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
105
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
106
|
+
/* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
107
|
+
description && /* @__PURE__ */ jsx(CardDescription, { children: description }),
|
|
108
|
+
action && /* @__PURE__ */ jsx(CardAction, { children: action })
|
|
109
|
+
] }),
|
|
110
|
+
/* @__PURE__ */ jsx(CardContent, { children: placeholder ? /* @__PURE__ */ jsx("div", {
|
|
111
|
+
"data-slot": "chart-placeholder",
|
|
112
|
+
className: "flex items-center justify-center",
|
|
113
|
+
style: { height },
|
|
114
|
+
children: placeholder
|
|
115
|
+
}) : /* @__PURE__ */ jsx(ChartContainer, {
|
|
116
|
+
config,
|
|
117
|
+
className: "aspect-auto w-full",
|
|
118
|
+
style: { height },
|
|
119
|
+
children: /* @__PURE__ */ jsxs(Chart, {
|
|
120
|
+
data,
|
|
121
|
+
layout: horizontal ? "vertical" : "horizontal",
|
|
122
|
+
stackOffset,
|
|
123
|
+
margin: {
|
|
124
|
+
left: 0,
|
|
125
|
+
right: xTicks ? endRoom(xFormatter, xTicks) : 8
|
|
126
|
+
},
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx(CartesianGrid, {
|
|
129
|
+
vertical: horizontal,
|
|
130
|
+
horizontal: !horizontal,
|
|
131
|
+
strokeDasharray: "3 3"
|
|
132
|
+
}),
|
|
133
|
+
horizontal ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(XAxis, {
|
|
134
|
+
type: "number",
|
|
135
|
+
hide: true,
|
|
136
|
+
domain: yDomain,
|
|
137
|
+
ticks: yTicks
|
|
138
|
+
}), /* @__PURE__ */ jsx(YAxis, {
|
|
139
|
+
dataKey: xKey,
|
|
140
|
+
type: "category",
|
|
141
|
+
width: "auto",
|
|
142
|
+
tickLine: false,
|
|
143
|
+
axisLine: false,
|
|
144
|
+
tickMargin: 8,
|
|
145
|
+
tickFormatter: (value) => xFormatter(value),
|
|
146
|
+
tick: xTickDetail ? fittedTick(data, xKey, xFormatter, xTickDetail, horizontal) : TICK,
|
|
147
|
+
interval: 0
|
|
148
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(XAxis, {
|
|
149
|
+
dataKey: xKey,
|
|
150
|
+
type: xDomain ? "number" : "category",
|
|
151
|
+
domain: xDomain,
|
|
152
|
+
ticks: xTicks,
|
|
153
|
+
height: (xTickDetail ? 40 : 30) + (xLabel ? 18 : 0),
|
|
154
|
+
label: xLabel ? {
|
|
155
|
+
value: xLabel,
|
|
156
|
+
position: "insideBottom",
|
|
157
|
+
className: AXIS_TITLE
|
|
158
|
+
} : void 0,
|
|
159
|
+
tickLine: false,
|
|
160
|
+
axisLine: false,
|
|
161
|
+
tickMargin: 8,
|
|
162
|
+
tickFormatter: (value) => xFormatter(value),
|
|
163
|
+
tick: xTickDetail || xTicks ? fittedTick(data, xKey, xFormatter, xTickDetail, false) : TICK,
|
|
164
|
+
interval: xTickDetail || xTicks ? 0 : void 0
|
|
165
|
+
}), /* @__PURE__ */ jsx(YAxis, {
|
|
166
|
+
tickLine: false,
|
|
167
|
+
axisLine: false,
|
|
168
|
+
width: "auto",
|
|
169
|
+
domain: yDomain,
|
|
170
|
+
ticks: yTicks,
|
|
171
|
+
label: yLabel ? {
|
|
172
|
+
value: yLabel,
|
|
173
|
+
angle: -90,
|
|
174
|
+
position: "insideLeft",
|
|
175
|
+
style: { textAnchor: "middle" },
|
|
176
|
+
className: AXIS_TITLE
|
|
177
|
+
} : void 0,
|
|
178
|
+
tickFormatter: (value) => (yTickFormatter ?? formatValue)(value),
|
|
179
|
+
tick: TICK
|
|
180
|
+
})] }),
|
|
181
|
+
crossesZero && (horizontal ? /* @__PURE__ */ jsx(ReferenceLine, {
|
|
182
|
+
x: 0,
|
|
183
|
+
stroke: "var(--border)"
|
|
184
|
+
}) : /* @__PURE__ */ jsx(ReferenceLine, {
|
|
185
|
+
y: 0,
|
|
186
|
+
stroke: "var(--border)"
|
|
187
|
+
})),
|
|
188
|
+
referenceLines.map(({ label, emphasis = "muted", labelPosition = "insideTopLeft", ...at }) => /* @__PURE__ */ jsx(ReferenceLine, {
|
|
189
|
+
...horizontal ? {
|
|
190
|
+
x: at.y,
|
|
191
|
+
y: at.x
|
|
192
|
+
} : at,
|
|
193
|
+
stroke: emphasis === "strong" ? "var(--foreground)" : "var(--muted-foreground)",
|
|
194
|
+
strokeDasharray: at.y === void 0 ? void 0 : "4 4",
|
|
195
|
+
label: label === void 0 ? void 0 : {
|
|
196
|
+
value: label,
|
|
197
|
+
position: labelPosition,
|
|
198
|
+
className: "fill-muted-foreground text-xs"
|
|
199
|
+
}
|
|
200
|
+
}, `${at.x ?? ""}:${at.y ?? ""}:${label ?? ""}`)),
|
|
201
|
+
/* @__PURE__ */ jsx(ChartTooltip, { content: /* @__PURE__ */ jsx(ChartTooltipContent, {
|
|
202
|
+
labelFormatter: (_, payload) => {
|
|
203
|
+
const row = payload[0]?.payload;
|
|
204
|
+
return row ? xTooltipFormatter(row[xKey]) : null;
|
|
205
|
+
},
|
|
206
|
+
formatter: seriesRow(series, formatValue)
|
|
207
|
+
}) }),
|
|
208
|
+
children,
|
|
209
|
+
/* @__PURE__ */ jsx(ChartLegend, {
|
|
210
|
+
content: /* @__PURE__ */ jsx(ChartLegendContent, {}),
|
|
211
|
+
itemSorter: null
|
|
212
|
+
})
|
|
213
|
+
]
|
|
214
|
+
})
|
|
215
|
+
}) }),
|
|
216
|
+
footer && /* @__PURE__ */ jsx(CardFooter, {
|
|
217
|
+
className: "flex-col items-start gap-2 text-sm",
|
|
218
|
+
children: footer
|
|
92
219
|
})
|
|
93
|
-
|
|
220
|
+
] });
|
|
94
221
|
}
|
|
95
222
|
//#endregion
|
|
96
|
-
export { ChartFrame, seriesRow };
|
|
223
|
+
export { ChartFrame, seriesFill, seriesRow };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
//#region src/lib/chart-series.d.ts
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The colours a series may take: the five chart slots, muted for an "Other" past five, and the two meaning
|
|
5
|
+
* colours for a gain and a loss.
|
|
6
|
+
*/
|
|
7
|
+
export type ChartColor = "var(--chart-1)" | "var(--chart-2)" | "var(--chart-3)" | "var(--chart-4)" | "var(--chart-5)" | "var(--muted-foreground)" | "var(--positive)" | "var(--negative)";
|
|
5
8
|
/** The fields of a row that hold numbers: the ones a series can plot. */
|
|
6
9
|
type NumericKey<T> = { [K in keyof T]-?: T[K] extends number | null | undefined ? K : never; }[keyof T] & string;
|
|
7
10
|
/** One series: the field it plots, its name in the legend and tooltip, and its colour. */
|
|
@@ -9,6 +12,8 @@ export interface ChartSeriesItem<T> {
|
|
|
9
12
|
key: NumericKey<T>;
|
|
10
13
|
label: string;
|
|
11
14
|
color: ChartColor;
|
|
15
|
+
/** A bar below zero takes this colour instead, such as var(--negative) for a loss beside var(--positive). */
|
|
16
|
+
negativeColor?: ChartColor;
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* The series in draw, stack and legend order; give the slots in order from
|
|
@@ -16,6 +21,23 @@ export interface ChartSeriesItem<T> {
|
|
|
16
21
|
* number-like keys such as "2024" first whatever order the page wrote them in.
|
|
17
22
|
*/
|
|
18
23
|
export type ChartSeries<T> = readonly ChartSeriesItem<T>[];
|
|
24
|
+
/**
|
|
25
|
+
* A labelled line across the plot: a level on the value axis (y), such as a limit, or a point on the x axis, such
|
|
26
|
+
* as an event. A level is dashed, an event solid.
|
|
27
|
+
*/
|
|
28
|
+
export type ChartReferenceLine = ({
|
|
29
|
+
y: number;
|
|
30
|
+
x?: never;
|
|
31
|
+
} | {
|
|
32
|
+
x: number | string;
|
|
33
|
+
y?: never;
|
|
34
|
+
}) & {
|
|
35
|
+
label?: string;
|
|
36
|
+
/** "strong" draws it in the text colour, for the line that matters most; "muted" by default. */
|
|
37
|
+
emphasis?: "muted" | "strong";
|
|
38
|
+
/** Where the label sits against the line. Defaults to insideTopLeft. */
|
|
39
|
+
labelPosition?: "insideTopLeft" | "insideTopRight" | "insideBottomLeft" | "insideBottomRight";
|
|
40
|
+
};
|
|
19
41
|
/** What BarChartCard, AreaChartCard and LineChartCard all take. */
|
|
20
42
|
export interface SeriesChartProps<T extends object, K extends keyof T> {
|
|
21
43
|
title: ReactNode;
|
|
@@ -27,14 +49,47 @@ export interface SeriesChartProps<T extends object, K extends keyof T> {
|
|
|
27
49
|
/** The field the x axis reads: a month, an hour of day, a price bucket. One row per value; a repeated value is hidden behind the first. */
|
|
28
50
|
xKey: K;
|
|
29
51
|
series: ChartSeries<NoInfer<T>>;
|
|
30
|
-
/** The x axis ticks and the tooltip's heading. Defaults to the value as text. */
|
|
52
|
+
/** The x axis ticks, and the tooltip's heading unless xTooltipFormatter is set. Defaults to the value as text. */
|
|
31
53
|
xFormatter?: (value: T[K]) => string;
|
|
54
|
+
/** The tooltip's heading, when it should say more than a tick: "19:34:13 IST, 10 s average" against "19:34". */
|
|
55
|
+
xTooltipFormatter?: (value: T[K]) => string;
|
|
32
56
|
/** A series' value in the tooltip, and the y axis unless yTickFormatter is set. Defaults to the locale's numbers. */
|
|
33
57
|
valueFormatter?: (value: number) => string;
|
|
34
58
|
/** The y axis, when its ticks should be shorter than the tooltip's figures: moneyCompact against money. */
|
|
35
59
|
yTickFormatter?: (value: number) => string;
|
|
60
|
+
/**
|
|
61
|
+
* A fixed range for the value axis, such as [0, 100] for a percentage. By default it fits the data; a bar
|
|
62
|
+
* chart's always reaches zero.
|
|
63
|
+
*/
|
|
64
|
+
yDomain?: [number, number];
|
|
65
|
+
/** Where the value axis puts its ticks, such as [0, 25, 50, 75, 100]. */
|
|
66
|
+
yTicks?: readonly number[];
|
|
36
67
|
/** Height of the plot and legend, in pixels. */
|
|
37
68
|
height: number;
|
|
69
|
+
/** A second line under each x tick, so a row's figure reads without a hover: "FY24" then "▲₹1.2L". */
|
|
70
|
+
xTickDetail?: (row: T) => string;
|
|
71
|
+
/** A title under the x axis, such as "Hour of day (IST)". Not drawn on sideways bars. */
|
|
72
|
+
xLabel?: string;
|
|
73
|
+
/** A title beside the value axis, read bottom to top, such as "Orders". Not drawn on sideways bars. */
|
|
74
|
+
yLabel?: string;
|
|
75
|
+
/** Limits and events to mark on the plot. A zero line draws by itself when a value goes below zero. */
|
|
76
|
+
referenceLines?: readonly ChartReferenceLine[];
|
|
77
|
+
/** Shown in the plot's place, at its height, while the data loads or after it failed to. */
|
|
78
|
+
placeholder?: ReactNode;
|
|
79
|
+
/** Lines under the chart, such as a caption or a takeaway, in the card's footer. */
|
|
80
|
+
footer?: ReactNode;
|
|
38
81
|
}
|
|
82
|
+
/** A numeric x axis, for samples in time or any measure where a mark can sit between two rows. */
|
|
83
|
+
export interface NumericXProps {
|
|
84
|
+
/** The x axis runs over this range of the xKey field, which must hold numbers; without it the axis is one slot per row. */
|
|
85
|
+
xDomain?: [number, number];
|
|
86
|
+
/** Where the x axis puts its ticks, in the xKey field's units; give xDomain with it, so the axis is numeric. */
|
|
87
|
+
xTicks?: readonly number[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* How a line or an area's edge joins its points: "linear" draws straight segments, as measured samples should
|
|
91
|
+
* be drawn; "monotone", the default, smooths between them without overshooting a point.
|
|
92
|
+
*/
|
|
93
|
+
export type ChartCurve = "monotone" | "linear";
|
|
39
94
|
//#endregion
|
|
40
95
|
export {};
|
package/package.json
CHANGED
package/registry.lock.json
CHANGED
|
@@ -41,6 +41,30 @@
|
|
|
41
41
|
"copied": "2026-10-20",
|
|
42
42
|
"sha256": "bc19cf1f5e486fa11273e7d7ed620eb7b82ba360f72e5a15e6bf488f992d16ce"
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
"file": "src/components/registry/dashboardcn/distribution-bar.tsx",
|
|
46
|
+
"registry": "@dashboardcn/distribution-bar",
|
|
47
|
+
"origin": "https://dashboardcn.com/r/distribution-bar.json",
|
|
48
|
+
"licence": "MIT, Copyright (c) 2026 dashboardcn contributors, https://github.com/NoahGdev/dashboardcn/blob/main/LICENSE",
|
|
49
|
+
"copied": "2026-10-22",
|
|
50
|
+
"sha256": "9028368f1363732cef765dabad2eca3ba98b608f1e237123b09df701c41c8b5a"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"file": "src/components/registry/dashboardcn/kpi-row-card.tsx",
|
|
54
|
+
"registry": "@dashboardcn/kpi-row-card",
|
|
55
|
+
"origin": "https://dashboardcn.com/r/kpi-row-card.json",
|
|
56
|
+
"licence": "MIT, Copyright (c) 2026 dashboardcn contributors, https://github.com/NoahGdev/dashboardcn/blob/main/LICENSE",
|
|
57
|
+
"copied": "2026-10-26",
|
|
58
|
+
"sha256": "b49fa95b3efa19086b3df2e3a18f6a0d5a95204951448c5d93fc41c2bdb6326f"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"file": "src/components/registry/dashboardcn/sparkline.tsx",
|
|
62
|
+
"registry": "@dashboardcn/sparkline",
|
|
63
|
+
"origin": "https://dashboardcn.com/r/sparkline.json",
|
|
64
|
+
"licence": "MIT, Copyright (c) 2026 dashboardcn contributors, https://github.com/NoahGdev/dashboardcn/blob/main/LICENSE",
|
|
65
|
+
"copied": "2026-10-26",
|
|
66
|
+
"sha256": "54b43e63d866bcdf8071744df08e87f29385ba60d480ab9ee8aa1fac3eb33d5c"
|
|
67
|
+
},
|
|
44
68
|
{
|
|
45
69
|
"file": "src/components/registry/heatmap/calendar-heatmap.tsx",
|
|
46
70
|
"registry": "@heatmap/calendar-heatmap",
|
|
@@ -65,6 +89,14 @@
|
|
|
65
89
|
"copied": "2026-10-20",
|
|
66
90
|
"sha256": "b7af6139e3764e1479880fb232988e758edb27ce4e4280d9e0349cbdf9b3d30c"
|
|
67
91
|
},
|
|
92
|
+
{
|
|
93
|
+
"file": "src/components/registry/minidev/copy-button.tsx",
|
|
94
|
+
"registry": "@minidev/copy-button",
|
|
95
|
+
"origin": "https://ui.minidev.pro/r/copy-button.json",
|
|
96
|
+
"licence": "MIT, Copyright (c) 2026 MiniDev, https://github.com/amankaushik481/minidev-ui/blob/main/LICENSE",
|
|
97
|
+
"copied": "2026-10-22",
|
|
98
|
+
"sha256": "67f491ea6c947ebf3bf058423a373347badd49ad07861e022599ebdbb11cab44"
|
|
99
|
+
},
|
|
68
100
|
{
|
|
69
101
|
"file": "src/components/registry/niko-table/components/data-table-column-actions.tsx",
|
|
70
102
|
"registry": "@niko-table/data-table",
|
package/report.css
CHANGED
|
@@ -48,20 +48,20 @@
|
|
|
48
48
|
|
|
49
49
|
@media (prefers-color-scheme: dark) {
|
|
50
50
|
:root {
|
|
51
|
-
--background: oklch(0.
|
|
52
|
-
--foreground: oklch(0.
|
|
53
|
-
--card: oklch(0.
|
|
54
|
-
--card-foreground: oklch(0.
|
|
55
|
-
--popover: oklch(0.
|
|
56
|
-
--popover-foreground: oklch(0.
|
|
51
|
+
--background: oklch(0.18 0 0);
|
|
52
|
+
--foreground: oklch(0.922 0 0);
|
|
53
|
+
--card: oklch(0.18 0 0);
|
|
54
|
+
--card-foreground: oklch(0.922 0 0);
|
|
55
|
+
--popover: oklch(0.18 0 0);
|
|
56
|
+
--popover-foreground: oklch(0.922 0 0);
|
|
57
57
|
--primary: oklch(0.922 0 0);
|
|
58
58
|
--primary-foreground: oklch(0.205 0 0);
|
|
59
59
|
--secondary: oklch(0.269 0 0);
|
|
60
|
-
--secondary-foreground: oklch(0.
|
|
60
|
+
--secondary-foreground: oklch(0.922 0 0);
|
|
61
61
|
--muted: oklch(0.269 0 0);
|
|
62
62
|
--muted-foreground: oklch(0.708 0 0);
|
|
63
63
|
--accent: oklch(0.269 0 0);
|
|
64
|
-
--accent-foreground: oklch(0.
|
|
64
|
+
--accent-foreground: oklch(0.922 0 0);
|
|
65
65
|
--destructive: oklch(0.704 0.191 22.216);
|
|
66
66
|
--border: oklch(1 0 0 / 10%);
|
|
67
67
|
--input: oklch(1 0 0 / 15%);
|
|
@@ -78,11 +78,11 @@
|
|
|
78
78
|
--chart-3: oklch(0.86 0.13 80);
|
|
79
79
|
--chart-4: oklch(0.55 0.25 293);
|
|
80
80
|
--chart-5: oklch(0.84 0.085 12);
|
|
81
|
-
--sidebar: oklch(0.
|
|
82
|
-
--sidebar-foreground: oklch(0.
|
|
81
|
+
--sidebar: oklch(0.145 0 0);
|
|
82
|
+
--sidebar-foreground: oklch(0.922 0 0);
|
|
83
83
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
84
84
|
--sidebar-accent: oklch(0.269 0 0);
|
|
85
|
-
--sidebar-accent-foreground: oklch(0.
|
|
85
|
+
--sidebar-accent-foreground: oklch(0.922 0 0);
|
|
86
86
|
--sidebar-border: oklch(1 0 0 / 10%);
|
|
87
87
|
--sidebar-ring: oklch(0.556 0 0);
|
|
88
88
|
}
|
package/styles/siyahi.css
CHANGED
|
@@ -130,20 +130,30 @@
|
|
|
130
130
|
--sidebar-ring: oklch(0.708 0 0);
|
|
131
131
|
|
|
132
132
|
@variant dark {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
/*
|
|
134
|
+
* The canvas lifts just off black and text sits a step below white:
|
|
135
|
+
* near-white on near-black (19:1) blurs for many readers, and with the
|
|
136
|
+
* cards' grey gone on a ruled page the canvas is what text sits on.
|
|
137
|
+
* Claude Code (#181818, about #e8e8e8 text) and T3 Code (#0a0a0a, about
|
|
138
|
+
* #bebebe) both narrow that gap; this sits between them, at 14.9:1.
|
|
139
|
+
* The card matches the canvas, so the contrast check scores the colour
|
|
140
|
+
* a ruled chart is drawn on, and the sidebar is a shade darker, as in
|
|
141
|
+
* the light scheme.
|
|
142
|
+
*/
|
|
143
|
+
--background: oklch(0.18 0 0);
|
|
144
|
+
--foreground: oklch(0.922 0 0);
|
|
145
|
+
--card: oklch(0.18 0 0);
|
|
146
|
+
--card-foreground: oklch(0.922 0 0);
|
|
147
|
+
--popover: oklch(0.18 0 0);
|
|
148
|
+
--popover-foreground: oklch(0.922 0 0);
|
|
139
149
|
--primary: oklch(0.922 0 0);
|
|
140
150
|
--primary-foreground: oklch(0.205 0 0);
|
|
141
151
|
--secondary: oklch(0.269 0 0);
|
|
142
|
-
--secondary-foreground: oklch(0.
|
|
152
|
+
--secondary-foreground: oklch(0.922 0 0);
|
|
143
153
|
--muted: oklch(0.269 0 0);
|
|
144
154
|
--muted-foreground: oklch(0.708 0 0);
|
|
145
155
|
--accent: oklch(0.269 0 0);
|
|
146
|
-
--accent-foreground: oklch(0.
|
|
156
|
+
--accent-foreground: oklch(0.922 0 0);
|
|
147
157
|
--destructive: oklch(0.704 0.191 22.216);
|
|
148
158
|
--border: oklch(1 0 0 / 10%);
|
|
149
159
|
--input: oklch(1 0 0 / 15%);
|
|
@@ -161,12 +171,12 @@
|
|
|
161
171
|
--chart-3: oklch(0.86 0.13 80);
|
|
162
172
|
--chart-4: oklch(0.55 0.25 293);
|
|
163
173
|
--chart-5: oklch(0.84 0.085 12);
|
|
164
|
-
--sidebar: oklch(0.
|
|
165
|
-
--sidebar-foreground: oklch(0.
|
|
174
|
+
--sidebar: oklch(0.145 0 0);
|
|
175
|
+
--sidebar-foreground: oklch(0.922 0 0);
|
|
166
176
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
167
177
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
168
178
|
--sidebar-accent: oklch(0.269 0 0);
|
|
169
|
-
--sidebar-accent-foreground: oklch(0.
|
|
179
|
+
--sidebar-accent-foreground: oklch(0.922 0 0);
|
|
170
180
|
--sidebar-border: oklch(1 0 0 / 10%);
|
|
171
181
|
--sidebar-ring: oklch(0.556 0 0);
|
|
172
182
|
}
|
|
@@ -215,3 +225,35 @@
|
|
|
215
225
|
}
|
|
216
226
|
}
|
|
217
227
|
}
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
* Surfaces, from SiyahiProvider's surface prop. Ruled, the default, and open
|
|
231
|
+
* take the box off every core Card: no fill, no corner, no ring, and no
|
|
232
|
+
* tinted footer band; PanelGrid draws the hairlines between ruled blocks.
|
|
233
|
+
* Open also drops the card's padding, so a block's content sits level with
|
|
234
|
+
* the page's text. A card provider gives shadcn's own card back. Each scope
|
|
235
|
+
* starts at the root, so a Card outside any provider is ruled too, and stops
|
|
236
|
+
* at a provider that says otherwise. Unlayered, like the rule above, to
|
|
237
|
+
* outrank the core components' utility classes; a picked SectionCards tile
|
|
238
|
+
* keeps its ring, which is important.
|
|
239
|
+
*/
|
|
240
|
+
@scope (:root, [data-surface="ruled"], [data-surface="open"]) to ([data-surface="card"]) {
|
|
241
|
+
[data-slot="card"] {
|
|
242
|
+
background: none;
|
|
243
|
+
border-radius: 0;
|
|
244
|
+
--tw-ring-color: transparent;
|
|
245
|
+
}
|
|
246
|
+
[data-slot="card-footer"] {
|
|
247
|
+
background: none;
|
|
248
|
+
border-top-width: 0;
|
|
249
|
+
/* The band's own top padding stacked on the card's gap, and with no band it read as a hole under the figure. */
|
|
250
|
+
padding-top: 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@scope ([data-surface="open"]) to ([data-surface="ruled"], [data-surface="card"]) {
|
|
255
|
+
[data-slot="card"] {
|
|
256
|
+
--card-spacing: 0px;
|
|
257
|
+
gap: calc(var(--spacing) * 4);
|
|
258
|
+
}
|
|
259
|
+
}
|
package/dist/lib/recharts.d.ts
DELETED
package/dist/lib/recharts.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Area, AreaChart, Bar, BarChart, CartesianGrid, Line, LineChart, ReferenceLine, XAxis, YAxis } from "recharts";
|