@siyahi/ui 0.1.9-next.6 → 0.1.9-next.8
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 +38 -6
- package/THIRD_PARTY_NOTICES.md +11 -11
- package/dist/components/registry/dashboard-01/section-cards.d.ts +2 -0
- package/dist/components/registry/dashboard-01/section-cards.js +3 -2
- 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/niko-table/ui/table.js +2 -2
- 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 +7 -3
- package/dist/index.js +7 -3
- package/package.json +1 -1
- package/registry.lock.json +16 -0
- package/report.css +11 -11
- package/styles/siyahi.css +51 -11
package/README.md
CHANGED
|
@@ -67,12 +67,13 @@ Every merge to `main` also attaches both tarballs to a GitHub release
|
|
|
67
67
|
|
|
68
68
|
## What is in it
|
|
69
69
|
|
|
70
|
-
- **shadcn/ui components** in the `base-
|
|
71
|
-
CLI and never edited.
|
|
70
|
+
- **shadcn/ui components** in the `base-nova` style, shadcn's flat and compact
|
|
71
|
+
one, installed with the shadcn CLI and never edited.
|
|
72
72
|
- **Registry add-ons**, copied once with their origin and licence recorded:
|
|
73
73
|
bar, area and line chart cards from shadcn's chart blocks, a data table on
|
|
74
74
|
TanStack Table, calendar, weekday and status heatmaps, a ranked
|
|
75
|
-
bar list, the `
|
|
75
|
+
bar list, a `Sparkline`, the `MetricStrip` row of figures, the
|
|
76
|
+
`SectionCards` stat tile and the `sidebar-07` app shell.
|
|
76
77
|
- **Siyahi components**: `Delta` (a signed figure with ▲ ▼), `PriceChart`
|
|
77
78
|
(TradingView Lightweight Charts in theme colours), `Treemap` (holdings heat
|
|
78
79
|
map; hover or tap a tile for its figures) with `TreemapLegend` (its colour
|
|
@@ -80,9 +81,13 @@ Every merge to `main` also attaches both tarballs to a GitHub release
|
|
|
80
81
|
in a tooltip), `ToneProgress` (Progress in a meaning colour), the page parts
|
|
81
82
|
`PageSection`, `PageSubheading`, `DataList` and `InlineCode`, the data table
|
|
82
83
|
parts `DataTableSortHeader` (sorts on one click) and `DataTableRowCount`
|
|
83
|
-
("12 of 48"),
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
("12 of 48"), `DataBar` (a figure in a table cell with a bar giving its size
|
|
85
|
+
against the column's largest), `PanelGrid` (data blocks side by side, with
|
|
86
|
+
hairlines between them on a ruled page), and `SiyahiProvider`.
|
|
87
|
+
- **Surfaces**: by default a data block has no box. Every `Card` on a ruled
|
|
88
|
+
page, chart cards and stat tiles included, loses its fill, corner and ring,
|
|
89
|
+
and a `PanelGrid` draws hairlines between blocks; see Surfaces below. A
|
|
90
|
+
category (a sector, a
|
|
86
91
|
broker, a unit's kind) is an outline `Badge`: categories stay neutral, and
|
|
87
92
|
colour is left to the four meaning colours and the charts. On a narrow card
|
|
88
93
|
(header under 24rem, so any phone) a header action such as a toggle drops
|
|
@@ -110,6 +115,9 @@ Every merge to `main` also attaches both tarballs to a GitHub release
|
|
|
110
115
|
| Ranked counts or amounts by category (a name, a bar and a figure) | `BarList`; give two lists one `max` to share a scale |
|
|
111
116
|
| Where a budget sits, a split of a whole, or losses against gains | `DistributionBar` |
|
|
112
117
|
| Headline figures with their change | `SectionCards`, with a `Delta` in each badge |
|
|
118
|
+
| Many figures of equal weight, each with its change and recent run | `MetricStrip` |
|
|
119
|
+
| A run of values beside a figure, in a tile, a strip or a table cell | `Sparkline`; in a tile, `SectionCards`' `trend` |
|
|
120
|
+
| A table column that should read as a bar chart | `DataBar` in the column's cell |
|
|
113
121
|
| One instrument's price history | `PriceChart` |
|
|
114
122
|
| Holdings sized by weight and coloured by change | `Treemap` |
|
|
115
123
|
| Activity by day, by weekday and hour, or a status over time | `CalendarHeatmap`, `WeekdayHeatmap`, `StatusHeatmap` |
|
|
@@ -122,6 +130,8 @@ Every merge to `main` also attaches both tarballs to a GitHub release
|
|
|
122
130
|
| Label and value pairs, such as a record's fields | `DataList` and `DataListItem` |
|
|
123
131
|
| A command or file to copy, wrapped or scrolling | `CodeBlock` with `CodeBlockCopyButton` |
|
|
124
132
|
| A labelled copy action, such as "Copy all" for a section | `CopyButton` |
|
|
133
|
+
| Data blocks side by side: charts, tables, a strip of figures | `PanelGrid` |
|
|
134
|
+
| Boxes back, or no lines at all, for a page or a part of one | `SiyahiProvider` with `surface="card"` or `surface="open"` |
|
|
125
135
|
| A command, file or identifier inside prose | `InlineCode` |
|
|
126
136
|
| A signed figure (a gain, a loss, a change) | `Delta` |
|
|
127
137
|
| A time, with the viewer's own clock on hover | `LocalTime` |
|
|
@@ -166,6 +176,28 @@ loss, a change) goes through `<Delta>`, which adds ▲ or ▼ and the meaning
|
|
|
166
176
|
colour. Time zone names come from the runtime's ICU data; a slim Node or
|
|
167
177
|
browser build may print `GMT+5:30` where a full one prints `IST`.
|
|
168
178
|
|
|
179
|
+
## Surfaces
|
|
180
|
+
|
|
181
|
+
A data block sits on the page in one of three ways, set by `SiyahiProvider`'s
|
|
182
|
+
`surface`:
|
|
183
|
+
|
|
184
|
+
- `"ruled"`, the default: no box. Every `Card` loses its fill, corner and ring,
|
|
185
|
+
and blocks side by side in a `PanelGrid` are parted by hairlines, with a rule
|
|
186
|
+
above and below the grid. One surface, as on a trading screen.
|
|
187
|
+
- `"open"`: no box and no lines. The card's padding goes too, so a block's
|
|
188
|
+
content sits level with the page's text; for pages read top to bottom.
|
|
189
|
+
- `"card"`: shadcn's own Nova card, a filled box with a 1px ring.
|
|
190
|
+
|
|
191
|
+
A component outside any provider is ruled. A nested provider sets the surface
|
|
192
|
+
for one part of a page. A picked `SectionCards` tile keeps its ring on every
|
|
193
|
+
surface.
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
<SiyahiProvider surface="open">
|
|
197
|
+
<PageSection title="Why XIRR fell">…</PageSection>
|
|
198
|
+
</SiyahiProvider>
|
|
199
|
+
```
|
|
200
|
+
|
|
169
201
|
## Dark mode
|
|
170
202
|
|
|
171
203
|
The colour scheme follows the device (`prefers-color-scheme`). There is no
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -8,17 +8,17 @@ file as copied; `packages/ui/registry.lock.json` lists them all and
|
|
|
8
8
|
|
|
9
9
|
## Copied into `@siyahi/ui`
|
|
10
10
|
|
|
11
|
-
| What
|
|
12
|
-
|
|
|
13
|
-
| shadcn/ui core components (installed with `shadcn add`, never edited)
|
|
14
|
-
| shadcn `tailwind.css` (variants and utilities the components use)
|
|
15
|
-
| shadcn block `sidebar-07`
|
|
16
|
-
| shadcn block `dashboard-01`, `SectionCards` only
|
|
17
|
-
| Heatmaps: calendar, weekday by hour, status timeline
|
|
18
|
-
| niko-table data table on TanStack Table
|
|
19
|
-
| shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple`
|
|
20
|
-
| dashboardcn ranked list (`BarList`)
|
|
21
|
-
| MiniDev copy button (`CopyButton`)
|
|
11
|
+
| What | Where in the package | Origin | Licence |
|
|
12
|
+
| --------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
13
|
+
| shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts` | https://github.com/shadcn-ui/ui | MIT, Copyright (c) 2023 shadcn |
|
|
14
|
+
| shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css` | https://github.com/shadcn-ui/ui/tree/main/packages/shadcn | MIT, Copyright (c) 2023 shadcn |
|
|
15
|
+
| shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*` | https://ui.shadcn.com/r/styles/base-vega/sidebar-07.json | MIT, Copyright (c) 2023 shadcn |
|
|
16
|
+
| shadcn block `dashboard-01`, `SectionCards` only | `src/components/registry/dashboard-01/section-cards.tsx` | https://ui.shadcn.com/r/styles/base-vega/dashboard-01.json | MIT, Copyright (c) 2023 shadcn |
|
|
17
|
+
| Heatmaps: calendar, weekday by hour, status timeline | `src/components/registry/heatmap/*` | https://shadcn-heatmap.pages.dev/r/calendar-heatmap.json, https://shadcn-heatmap.pages.dev/r/weekday-heatmap.json, https://shadcn-heatmap.pages.dev/r/status-heatmap.json (source: https://github.com/rutopio/shadcn-heatmap) | MIT, Copyright (c) 2026 ChingRu |
|
|
18
|
+
| niko-table data table on TanStack Table | `src/components/registry/niko-table/*` | https://niko-table.com/r/data-table.json, https://niko-table.com/r/data-table-core.json, https://niko-table.com/r/data-table-ui.json, https://niko-table.com/r/data-table-faceted-filter.json, https://niko-table.com/r/data-table-column-sort.json, https://niko-table.com/r/data-table-search-filter.json (source: https://github.com/Semkoo/niko-table-registry) | MIT, Copyright (c) 2025 Semir N.; original work Copyright (c) 2025 WebDevSimplified |
|
|
19
|
+
| shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple` | `src/components/registry/charts/*` | https://ui.shadcn.com/r/styles/new-york-v4/chart-bar-multiple.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-area-stacked.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-line-multiple.json | MIT, Copyright (c) 2023 shadcn |
|
|
20
|
+
| dashboardcn ranked list (`BarList`), stacked bar (`DistributionBar`), `Sparkline` and `MetricStrip` | `src/components/registry/dashboardcn/*` | https://dashboardcn.com/r/bar-list.json, https://dashboardcn.com/r/distribution-bar.json, https://dashboardcn.com/r/sparkline.json, https://dashboardcn.com/r/kpi-row-card.json (source: https://github.com/NoahGdev/dashboardcn) | MIT, Copyright (c) 2026 dashboardcn contributors |
|
|
21
|
+
| MiniDev copy button (`CopyButton`) | `src/components/registry/minidev/copy-button.tsx` | https://ui.minidev.pro/r/copy-button.json (source: https://github.com/amankaushik481/minidev-ui) | MIT, Copyright (c) 2026 MiniDev |
|
|
22
22
|
|
|
23
23
|
## Runtime dependencies with attribution terms
|
|
24
24
|
|
|
@@ -6,6 +6,8 @@ export interface SectionCard {
|
|
|
6
6
|
value: React$1.ReactNode;
|
|
7
7
|
/** Outline badge, top right; usually a <Delta />. */
|
|
8
8
|
badge?: React$1.ReactNode;
|
|
9
|
+
/** A small chart under the value, usually a <Sparkline /> of the recent run. */
|
|
10
|
+
trend?: React$1.ReactNode;
|
|
9
11
|
/** Bold first footer line. */
|
|
10
12
|
headline?: React$1.ReactNode;
|
|
11
13
|
/** Muted second footer line. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Badge } from "../../ui/badge.js";
|
|
3
|
-
import { Card, CardAction, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
|
|
3
|
+
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
|
|
4
4
|
import { cn } from "../../../lib/utils.js";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import "react";
|
|
@@ -26,7 +26,7 @@ function SectionCards({ items, selected, onSelect }) {
|
|
|
26
26
|
"aria-pressed": item.label === selected,
|
|
27
27
|
disabled: item.disabled,
|
|
28
28
|
onClick: () => onSelect(item.label),
|
|
29
|
-
className: "absolute inset-0 z-10 rounded-
|
|
29
|
+
className: "absolute inset-0 z-10 rounded-[inherit] outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset"
|
|
30
30
|
}),
|
|
31
31
|
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
32
32
|
/* @__PURE__ */ jsx(CardDescription, { children: item.label }),
|
|
@@ -39,6 +39,7 @@ function SectionCards({ items, selected, onSelect }) {
|
|
|
39
39
|
children: item.badge
|
|
40
40
|
}) })
|
|
41
41
|
] }),
|
|
42
|
+
item.trend && /* @__PURE__ */ jsx(CardContent, { children: item.trend }),
|
|
42
43
|
(item.headline || item.detail) && /* @__PURE__ */ jsxs(CardFooter, {
|
|
43
44
|
className: "flex-col items-start gap-1.5 text-sm",
|
|
44
45
|
children: [item.headline && /* @__PURE__ */ jsx("div", {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Card } from "../../ui/card.js";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
//#region src/components/registry/dashboardcn/kpi-row-card.d.ts
|
|
4
|
+
export interface MetricStripItem {
|
|
5
|
+
/** Muted label above the figure. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** The figure, formatted by the page: money(4512300). */
|
|
8
|
+
value: React$1.ReactNode;
|
|
9
|
+
/** The signed change, drawn as a Delta under the figure; its sign colours the trend. For "pct", a fraction. */
|
|
10
|
+
change?: number;
|
|
11
|
+
changeFormat?: "pct" | "money";
|
|
12
|
+
/** Muted words after the change, such as "vs last month". */
|
|
13
|
+
note?: React$1.ReactNode;
|
|
14
|
+
/** Recent values, oldest first, drawn as a sparkline beside the figure. */
|
|
15
|
+
trend?: number[];
|
|
16
|
+
}
|
|
17
|
+
export interface MetricStripProps extends Omit<React$1.ComponentProps<typeof Card>, "title"> {
|
|
18
|
+
title?: React$1.ReactNode;
|
|
19
|
+
description?: React$1.ReactNode;
|
|
20
|
+
/** A range toggle, top right, that changes every figure. */
|
|
21
|
+
action?: React$1.ReactNode;
|
|
22
|
+
items: MetricStripItem[];
|
|
23
|
+
/** Lines under the strip, such as what the figures cover. */
|
|
24
|
+
footer?: React$1.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
/** A card holding a row of small figures, each with its change and a sparkline: more numbers in less room than stat tiles. */
|
|
27
|
+
declare function MetricStrip({ title, description, action, items, footer, className, ...props }: MetricStripProps): React$1.JSX.Element;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { MetricStrip };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
|
|
2
|
+
import { cn } from "../../../lib/utils.js";
|
|
3
|
+
import { Delta } from "../../siyahi/delta.js";
|
|
4
|
+
import { Sparkline } from "./sparkline.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import "react";
|
|
7
|
+
//#region src/components/registry/dashboardcn/kpi-row-card.tsx
|
|
8
|
+
const COLUMNS = {
|
|
9
|
+
1: "basis-full",
|
|
10
|
+
2: "basis-full @2xs/strip:basis-1/2",
|
|
11
|
+
3: "basis-full @lg/strip:basis-1/3",
|
|
12
|
+
4: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4",
|
|
13
|
+
5: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/5",
|
|
14
|
+
6: "basis-full @2xs/strip:basis-1/2 @xl/strip:basis-1/3 @5xl/strip:basis-1/6",
|
|
15
|
+
8: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4 @7xl/strip:basis-1/8"
|
|
16
|
+
};
|
|
17
|
+
function trendColor(change) {
|
|
18
|
+
if (change === void 0) return "var(--chart-1)";
|
|
19
|
+
if (change > 0) return "var(--positive)";
|
|
20
|
+
if (change < 0) return "var(--negative)";
|
|
21
|
+
return "var(--muted-foreground)";
|
|
22
|
+
}
|
|
23
|
+
/** A card holding a row of small figures, each with its change and a sparkline: more numbers in less room than stat tiles. */
|
|
24
|
+
function MetricStrip({ title, description, action, items, footer, className, ...props }) {
|
|
25
|
+
const columns = COLUMNS[Math.min(items.length, 8)] ?? COLUMNS[8];
|
|
26
|
+
return /* @__PURE__ */ jsxs(Card, {
|
|
27
|
+
className: cn("gap-4", className),
|
|
28
|
+
...props,
|
|
29
|
+
children: [
|
|
30
|
+
(title || description || action) && /* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
31
|
+
title && /* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
32
|
+
description && /* @__PURE__ */ jsx(CardDescription, { children: description }),
|
|
33
|
+
action && /* @__PURE__ */ jsx(CardAction, { children: action })
|
|
34
|
+
] }),
|
|
35
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", {
|
|
36
|
+
"data-slot": "metric-strip",
|
|
37
|
+
className: "@container/strip -mx-4 -my-3 overflow-hidden",
|
|
38
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
39
|
+
className: "-mt-px -ml-px flex flex-wrap",
|
|
40
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("div", {
|
|
41
|
+
"data-slot": "metric-strip-item",
|
|
42
|
+
className: cn("flex min-w-0 flex-col gap-1 border-t border-l px-4 py-3", columns),
|
|
43
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
44
|
+
className: "truncate text-xs text-muted-foreground",
|
|
45
|
+
children: item.label
|
|
46
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
47
|
+
className: "flex flex-wrap items-end justify-between gap-x-3 gap-y-1",
|
|
48
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
49
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
50
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
51
|
+
className: "text-xl font-semibold tracking-tight tabular-nums",
|
|
52
|
+
children: item.value
|
|
53
|
+
}), (item.change !== void 0 || item.note) && /* @__PURE__ */ jsxs("div", {
|
|
54
|
+
className: "flex flex-wrap items-center gap-x-1.5 text-xs",
|
|
55
|
+
children: [item.change !== void 0 && /* @__PURE__ */ jsx(Delta, {
|
|
56
|
+
value: item.change,
|
|
57
|
+
format: item.changeFormat
|
|
58
|
+
}), item.note && /* @__PURE__ */ jsx("span", {
|
|
59
|
+
className: "text-muted-foreground",
|
|
60
|
+
children: item.note
|
|
61
|
+
})]
|
|
62
|
+
})]
|
|
63
|
+
}), item.trend && item.trend.length > 1 && /* @__PURE__ */ jsx(Sparkline, {
|
|
64
|
+
data: item.trend,
|
|
65
|
+
variant: "line",
|
|
66
|
+
color: trendColor(item.change),
|
|
67
|
+
className: "h-8 w-16 shrink-0"
|
|
68
|
+
})]
|
|
69
|
+
})]
|
|
70
|
+
}, item.label))
|
|
71
|
+
})
|
|
72
|
+
}) }),
|
|
73
|
+
footer && /* @__PURE__ */ jsx(CardFooter, {
|
|
74
|
+
className: "flex-col items-start gap-2 text-sm",
|
|
75
|
+
children: footer
|
|
76
|
+
})
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { MetricStrip };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ChartColor } from "../../../lib/chart-series.js";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
//#region src/components/registry/dashboardcn/sparkline.d.ts
|
|
4
|
+
export interface SparklineProps extends React$1.ComponentProps<"div"> {
|
|
5
|
+
/** Series to plot, oldest first. */
|
|
6
|
+
data: number[];
|
|
7
|
+
variant?: "area" | "line";
|
|
8
|
+
/** A chart slot, or var(--positive) or var(--negative) for a gain or a loss. Defaults to var(--chart-1). */
|
|
9
|
+
color?: ChartColor;
|
|
10
|
+
curve?: "monotone" | "linear" | "step";
|
|
11
|
+
strokeWidth?: number;
|
|
12
|
+
/** Animate after hydration and when data changes. Respects reduced motion. */
|
|
13
|
+
animate?: boolean;
|
|
14
|
+
animationDuration?: number;
|
|
15
|
+
}
|
|
16
|
+
declare function Sparkline({ data, variant, color, curve, strokeWidth, animate, animationDuration, className, ...props }: SparklineProps): React$1.JSX.Element;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { Sparkline };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { cn } from "../../../lib/utils.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
import { Area, AreaChart, Line, LineChart, ResponsiveContainer, YAxis } from "recharts";
|
|
5
|
+
//#region src/components/registry/dashboardcn/sparkline.tsx
|
|
6
|
+
const reducedMotionQuery = "(prefers-reduced-motion: reduce)";
|
|
7
|
+
function subscribeToReducedMotion(onChange) {
|
|
8
|
+
const query = window.matchMedia(reducedMotionQuery);
|
|
9
|
+
query.addEventListener("change", onChange);
|
|
10
|
+
return () => query.removeEventListener("change", onChange);
|
|
11
|
+
}
|
|
12
|
+
function getReducedMotionSnapshot() {
|
|
13
|
+
return window.matchMedia(reducedMotionQuery).matches;
|
|
14
|
+
}
|
|
15
|
+
function getReducedMotionServerSnapshot() {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
function Sparkline({ data, variant = "area", color = "var(--chart-1)", curve = "monotone", strokeWidth = 1.5, animate = true, animationDuration = 500, className, ...props }) {
|
|
19
|
+
const id = React$1.useId();
|
|
20
|
+
const reducedMotion = React$1.useSyncExternalStore(subscribeToReducedMotion, getReducedMotionSnapshot, getReducedMotionServerSnapshot);
|
|
21
|
+
const animationActive = animate && !reducedMotion;
|
|
22
|
+
const points = React$1.useMemo(() => data.map((y, i) => ({
|
|
23
|
+
i,
|
|
24
|
+
y
|
|
25
|
+
})), [data]);
|
|
26
|
+
const margin = {
|
|
27
|
+
top: 2,
|
|
28
|
+
right: 0,
|
|
29
|
+
bottom: 2,
|
|
30
|
+
left: 0
|
|
31
|
+
};
|
|
32
|
+
const axis = /* @__PURE__ */ jsx(YAxis, {
|
|
33
|
+
hide: true,
|
|
34
|
+
domain: ["dataMin", "dataMax"]
|
|
35
|
+
});
|
|
36
|
+
return /* @__PURE__ */ jsx("div", {
|
|
37
|
+
"data-slot": "sparkline",
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
className: cn("h-10 w-full", className),
|
|
40
|
+
...props,
|
|
41
|
+
children: /* @__PURE__ */ jsx(ResponsiveContainer, {
|
|
42
|
+
width: "100%",
|
|
43
|
+
height: "100%",
|
|
44
|
+
children: variant === "line" ? /* @__PURE__ */ jsxs(LineChart, {
|
|
45
|
+
data: points,
|
|
46
|
+
margin,
|
|
47
|
+
children: [axis, /* @__PURE__ */ jsx(Line, {
|
|
48
|
+
type: curve,
|
|
49
|
+
dataKey: "y",
|
|
50
|
+
stroke: color,
|
|
51
|
+
strokeWidth,
|
|
52
|
+
dot: false,
|
|
53
|
+
isAnimationActive: animationActive,
|
|
54
|
+
animationDuration,
|
|
55
|
+
animationEasing: "ease-out"
|
|
56
|
+
})]
|
|
57
|
+
}) : /* @__PURE__ */ jsxs(AreaChart, {
|
|
58
|
+
data: points,
|
|
59
|
+
margin,
|
|
60
|
+
children: [
|
|
61
|
+
axis,
|
|
62
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
|
|
63
|
+
id,
|
|
64
|
+
x1: "0",
|
|
65
|
+
y1: "0",
|
|
66
|
+
x2: "0",
|
|
67
|
+
y2: "1",
|
|
68
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
69
|
+
offset: "0%",
|
|
70
|
+
stopColor: color,
|
|
71
|
+
stopOpacity: .3
|
|
72
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
73
|
+
offset: "100%",
|
|
74
|
+
stopColor: color,
|
|
75
|
+
stopOpacity: 0
|
|
76
|
+
})]
|
|
77
|
+
}) }),
|
|
78
|
+
/* @__PURE__ */ jsx(Area, {
|
|
79
|
+
type: curve,
|
|
80
|
+
dataKey: "y",
|
|
81
|
+
stroke: color,
|
|
82
|
+
strokeWidth,
|
|
83
|
+
fill: `url(#${id})`,
|
|
84
|
+
dot: false,
|
|
85
|
+
isAnimationActive: animationActive,
|
|
86
|
+
animationDuration,
|
|
87
|
+
animationEasing: "ease-out"
|
|
88
|
+
})
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { Sparkline };
|
|
@@ -52,14 +52,14 @@ function TableRow({ className, ...props }) {
|
|
|
52
52
|
function TableHead({ className, ...props }) {
|
|
53
53
|
return /* @__PURE__ */ jsx("th", {
|
|
54
54
|
"data-slot": "table-head",
|
|
55
|
-
className: cn("h-
|
|
55
|
+
className: cn("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
|
|
56
56
|
...props
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
function TableCell({ className, ...props }) {
|
|
60
60
|
return /* @__PURE__ */ jsx("td", {
|
|
61
61
|
"data-slot": "table-cell",
|
|
62
|
-
className: cn("p-
|
|
62
|
+
className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
|
|
63
63
|
...props
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/components/siyahi/data-bar.d.ts
|
|
3
|
+
export interface DataBarProps {
|
|
4
|
+
value: number;
|
|
5
|
+
/** The value a full bar stands for, usually the column's largest: Math.max(...rows.map((row) => row.value)). */
|
|
6
|
+
max: number;
|
|
7
|
+
/** "sign" draws a gain in --positive and a loss in --negative; by default every bar is --chart-1. */
|
|
8
|
+
tone?: "chart" | "sign";
|
|
9
|
+
/** The figure, as the page formats it. */
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A table cell's figure behind a short bar whose length is the figure's share of max, so a column reads as a chart.
|
|
15
|
+
* The bar has a fixed width, so every row draws to the same scale, and sits on the figure's line, so the row
|
|
16
|
+
* keeps its height.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DataBar({ value, max, tone, children, className }: DataBarProps): import("react").JSX.Element;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/siyahi/data-bar.tsx
|
|
4
|
+
/**
|
|
5
|
+
* A table cell's figure behind a short bar whose length is the figure's share of max, so a column reads as a chart.
|
|
6
|
+
* The bar has a fixed width, so every row draws to the same scale, and sits on the figure's line, so the row
|
|
7
|
+
* keeps its height.
|
|
8
|
+
*/
|
|
9
|
+
function DataBar({ value, max, tone = "chart", children, className }) {
|
|
10
|
+
const share = max > 0 ? Math.min(1, Math.abs(value) / max) : 0;
|
|
11
|
+
const fill = tone === "chart" ? "bg-chart-1" : value < 0 ? "bg-negative" : "bg-positive";
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
"data-slot": "data-bar",
|
|
14
|
+
className: cn("flex items-center gap-2", className),
|
|
15
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
16
|
+
"aria-hidden": "true",
|
|
17
|
+
className: "h-1.5 w-16 shrink-0 overflow-hidden rounded-full bg-muted",
|
|
18
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
19
|
+
className: cn("h-full rounded-full", fill),
|
|
20
|
+
style: { width: `${share * 100}%` }
|
|
21
|
+
})
|
|
22
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
23
|
+
className: "tabular-nums",
|
|
24
|
+
children
|
|
25
|
+
})]
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DataBar };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/components/siyahi/panel-grid.d.ts
|
|
3
|
+
declare const COLUMNS: {
|
|
4
|
+
readonly 1: "";
|
|
5
|
+
readonly 2: "@2xl/panels:grid-cols-2";
|
|
6
|
+
readonly 3: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-3";
|
|
7
|
+
readonly 4: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-4";
|
|
8
|
+
};
|
|
9
|
+
export interface PanelGridProps {
|
|
10
|
+
/** Blocks across on a wide page; two on a medium one, and one on a phone. */
|
|
11
|
+
columns?: keyof typeof COLUMNS;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Data blocks side by side: chart cards, tables, a MetricStrip. On a ruled surface a hairline parts them across and
|
|
17
|
+
* down, with a rule above and below the grid; open leaves whitespace between them, and card a gap between boxes.
|
|
18
|
+
* Each block's left and top edges carry its rules, and the grid clips the ones on its own edges.
|
|
19
|
+
*/
|
|
20
|
+
export declare function PanelGrid({ columns, children, className }: PanelGridProps): import("react").JSX.Element;
|
|
21
|
+
//#endregion
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useSurface } from "./siyahi-provider.js";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Children } from "react";
|
|
5
|
+
//#region src/components/siyahi/panel-grid.tsx
|
|
6
|
+
const COLUMNS = {
|
|
7
|
+
1: "",
|
|
8
|
+
2: "@2xl/panels:grid-cols-2",
|
|
9
|
+
3: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-3",
|
|
10
|
+
4: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-4"
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Data blocks side by side: chart cards, tables, a MetricStrip. On a ruled surface a hairline parts them across and
|
|
14
|
+
* down, with a rule above and below the grid; open leaves whitespace between them, and card a gap between boxes.
|
|
15
|
+
* Each block's left and top edges carry its rules, and the grid clips the ones on its own edges.
|
|
16
|
+
*/
|
|
17
|
+
function PanelGrid({ columns = 2, children, className }) {
|
|
18
|
+
const surface = useSurface();
|
|
19
|
+
const ruled = surface === "ruled";
|
|
20
|
+
return /* @__PURE__ */ jsx("div", {
|
|
21
|
+
"data-slot": "panel-grid",
|
|
22
|
+
className: cn("@container/panels", ruled && "overflow-hidden border-y", className),
|
|
23
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
24
|
+
className: cn("grid grid-cols-1", COLUMNS[columns], ruled ? "-mt-px -ml-px" : surface === "open" ? "gap-x-10 gap-y-8" : "gap-4"),
|
|
25
|
+
children: Children.map(children, (child) => /* @__PURE__ */ jsx("div", {
|
|
26
|
+
"data-slot": "panel",
|
|
27
|
+
className: cn("min-w-0", ruled && "border-t border-l"),
|
|
28
|
+
children: child
|
|
29
|
+
}))
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { PanelGrid };
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { SiyahiLocale } from "../../lib/locale.js";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
//#region src/components/siyahi/siyahi-provider.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* How a data block sits on the page. "ruled": no box, hairlines between blocks in a PanelGrid. "open": no box and no
|
|
6
|
+
* lines, the block's content level with the page's text. "card": shadcn's own card, a filled box with a 1px ring.
|
|
7
|
+
*/
|
|
8
|
+
export type Surface = "ruled" | "open" | "card";
|
|
4
9
|
export interface SiyahiProviderProps {
|
|
5
10
|
/** Any setting left out keeps its default: en-IN, INR, Asia/Kolkata. */
|
|
6
11
|
locale?: Partial<SiyahiLocale>;
|
|
12
|
+
/**
|
|
13
|
+
* Set it on a nested provider for one part of a page. Left out, a provider keeps the surface around it, so a
|
|
14
|
+
* provider that only changes the locale changes nothing else; the outermost default is "ruled".
|
|
15
|
+
*/
|
|
16
|
+
surface?: Surface;
|
|
7
17
|
children: ReactNode;
|
|
8
18
|
}
|
|
9
|
-
/** Wrap the app once. Carries the locale and the tooltip provider shadcn asks for. */
|
|
10
|
-
export declare function SiyahiProvider({ locale, children }: SiyahiProviderProps): import("react").JSX.Element;
|
|
19
|
+
/** Wrap the app once. Carries the locale, the surface and the tooltip provider shadcn asks for. */
|
|
20
|
+
export declare function SiyahiProvider({ locale, surface, children }: SiyahiProviderProps): import("react").JSX.Element;
|
|
11
21
|
export declare function useLocale(): SiyahiLocale;
|
|
22
|
+
export declare function useSurface(): Surface;
|
|
12
23
|
//#endregion
|
|
@@ -4,8 +4,9 @@ import { jsx } from "react/jsx-runtime";
|
|
|
4
4
|
import { createContext, use, useMemo } from "react";
|
|
5
5
|
//#region src/components/siyahi/siyahi-provider.tsx
|
|
6
6
|
const LocaleContext = createContext(defaultLocale);
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const SurfaceContext = createContext("ruled");
|
|
8
|
+
/** Wrap the app once. Carries the locale, the surface and the tooltip provider shadcn asks for. */
|
|
9
|
+
function SiyahiProvider({ locale, surface, children }) {
|
|
9
10
|
const { numberLocale, currency, timeZone } = {
|
|
10
11
|
...defaultLocale,
|
|
11
12
|
...locale
|
|
@@ -19,13 +20,25 @@ function SiyahiProvider({ locale, children }) {
|
|
|
19
20
|
currency,
|
|
20
21
|
timeZone
|
|
21
22
|
]);
|
|
23
|
+
const around = use(SurfaceContext);
|
|
22
24
|
return /* @__PURE__ */ jsx(LocaleContext, {
|
|
23
25
|
value,
|
|
24
|
-
children: /* @__PURE__ */ jsx(
|
|
26
|
+
children: /* @__PURE__ */ jsx(SurfaceContext, {
|
|
27
|
+
value: surface ?? around,
|
|
28
|
+
children: /* @__PURE__ */ jsx(TooltipProvider, { children: surface ? /* @__PURE__ */ jsx("div", {
|
|
29
|
+
"data-slot": "siyahi-provider",
|
|
30
|
+
"data-surface": surface,
|
|
31
|
+
className: "contents",
|
|
32
|
+
children
|
|
33
|
+
}) : children })
|
|
34
|
+
})
|
|
25
35
|
});
|
|
26
36
|
}
|
|
27
37
|
function useLocale() {
|
|
28
38
|
return use(LocaleContext);
|
|
29
39
|
}
|
|
40
|
+
function useSurface() {
|
|
41
|
+
return use(SurfaceContext);
|
|
42
|
+
}
|
|
30
43
|
//#endregion
|
|
31
|
-
export { SiyahiProvider, useLocale };
|
|
44
|
+
export { SiyahiProvider, useLocale, useSurface };
|
|
@@ -6,14 +6,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
function Accordion({ className, ...props }) {
|
|
7
7
|
return /* @__PURE__ */ jsx(Accordion$1.Root, {
|
|
8
8
|
"data-slot": "accordion",
|
|
9
|
-
className: cn("flex w-full flex-col
|
|
9
|
+
className: cn("flex w-full flex-col", className),
|
|
10
10
|
...props
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
function AccordionItem({ className, ...props }) {
|
|
14
14
|
return /* @__PURE__ */ jsx(Accordion$1.Item, {
|
|
15
15
|
"data-slot": "accordion-item",
|
|
16
|
-
className: cn("not-last:border-b
|
|
16
|
+
className: cn("not-last:border-b", className),
|
|
17
17
|
...props
|
|
18
18
|
});
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ function AccordionTrigger({ className, children, ...props }) {
|
|
|
22
22
|
className: "flex",
|
|
23
23
|
children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
|
|
24
24
|
"data-slot": "accordion-trigger",
|
|
25
|
-
className: cn("group/accordion-trigger relative flex flex-1 items-start justify-between
|
|
25
|
+
className: cn("group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground", className),
|
|
26
26
|
...props,
|
|
27
27
|
children: [
|
|
28
28
|
children,
|
|
@@ -41,10 +41,10 @@ function AccordionTrigger({ className, children, ...props }) {
|
|
|
41
41
|
function AccordionContent({ className, children, ...props }) {
|
|
42
42
|
return /* @__PURE__ */ jsx(Accordion$1.Panel, {
|
|
43
43
|
"data-slot": "accordion-content",
|
|
44
|
-
className: "overflow-hidden
|
|
44
|
+
className: "overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
45
45
|
...props,
|
|
46
46
|
children: /* @__PURE__ */ jsx("div", {
|
|
47
|
-
className: cn("h-(--accordion-panel-height) pt-0 pb-
|
|
47
|
+
className: cn("h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4", className),
|
|
48
48
|
children
|
|
49
49
|
})
|
|
50
50
|
});
|