@siyahi/ui 0.1.9-next.2 → 0.1.9-next.21
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/DESIGN.md +30 -0
- package/README.md +82 -176
- package/THIRD_PARTY_NOTICES.md +11 -11
- package/agents/examples/accordion.tsx +39 -0
- package/agents/examples/alert.tsx +23 -0
- package/agents/examples/app-sidebar.tsx +38 -0
- package/agents/examples/avatar.tsx +14 -0
- package/agents/examples/badge.tsx +18 -0
- package/agents/examples/bar-list-labels.tsx +22 -0
- package/agents/examples/bar-list-sides.tsx +38 -0
- package/agents/examples/bar-list.tsx +24 -0
- package/agents/examples/breadcrumb.tsx +28 -0
- package/agents/examples/button-states.tsx +23 -0
- package/agents/examples/button.tsx +21 -0
- package/agents/examples/calendar.tsx +15 -0
- package/agents/examples/callout.tsx +33 -0
- package/agents/examples/card.tsx +34 -0
- package/agents/examples/change-bar.tsx +104 -0
- package/agents/examples/chart-area.tsx +39 -0
- package/agents/examples/chart-bar-flows.tsx +32 -0
- package/agents/examples/chart-bar-hourly.tsx +28 -0
- package/agents/examples/chart-bar-losses.tsx +29 -0
- package/agents/examples/chart-bar-sectors.tsx +72 -0
- package/agents/examples/chart-bar-years.tsx +40 -0
- package/agents/examples/chart-bar.tsx +56 -0
- package/agents/examples/chart-category-ticks.tsx +50 -0
- package/agents/examples/chart-line-events.tsx +47 -0
- package/agents/examples/chart-line-timeline.tsx +41 -0
- package/agents/examples/chart-line.tsx +57 -0
- package/agents/examples/code-block.tsx +38 -0
- package/agents/examples/collapsible.tsx +16 -0
- package/agents/examples/command.tsx +27 -0
- package/agents/examples/context-menu.tsx +15 -0
- package/agents/examples/copy-button.tsx +8 -0
- package/agents/examples/data-bar.tsx +121 -0
- package/agents/examples/data-table-compact.tsx +95 -0
- package/agents/examples/data-table-filters.tsx +103 -0
- package/agents/examples/data-table.tsx +98 -0
- package/agents/examples/delta.tsx +13 -0
- package/agents/examples/dialog.tsx +28 -0
- package/agents/examples/distribution-bar-budget.tsx +30 -0
- package/agents/examples/distribution-bar-tug.tsx +72 -0
- package/agents/examples/dropdown-menu.tsx +31 -0
- package/agents/examples/formatters.tsx +42 -0
- package/agents/examples/heatmap-calendar.tsx +60 -0
- package/agents/examples/heatmap-status.tsx +57 -0
- package/agents/examples/heatmap-weekday.tsx +75 -0
- package/agents/examples/input-states.tsx +33 -0
- package/agents/examples/input.tsx +17 -0
- package/agents/examples/local-time.tsx +14 -0
- package/agents/examples/metric-strip.tsx +46 -0
- package/agents/examples/overview-dashboard.tsx +18 -0
- package/agents/examples/page-hero.tsx +38 -0
- package/agents/examples/page-section.tsx +52 -0
- package/agents/examples/popover.tsx +23 -0
- package/agents/examples/price-chart.tsx +32 -0
- package/agents/examples/progress-tone.tsx +28 -0
- package/agents/examples/progress.tsx +10 -0
- package/agents/examples/range-position-table.tsx +101 -0
- package/agents/examples/range-position.tsx +53 -0
- package/agents/examples/scroll-area.tsx +20 -0
- package/agents/examples/section-cards-select.tsx +30 -0
- package/agents/examples/section-cards-trend.tsx +30 -0
- package/agents/examples/section-cards.tsx +48 -0
- package/agents/examples/select.tsx +27 -0
- package/agents/examples/separator.tsx +13 -0
- package/agents/examples/sheet.tsx +15 -0
- package/agents/examples/skeleton.tsx +11 -0
- package/agents/examples/slider.tsx +5 -0
- package/agents/examples/surfaces.tsx +116 -0
- package/agents/examples/table.tsx +50 -0
- package/agents/examples/tabs.tsx +16 -0
- package/agents/examples/target-rows.tsx +70 -0
- package/agents/examples/toggle-group.tsx +12 -0
- package/agents/examples/toggle.tsx +11 -0
- package/agents/examples/tooltip.tsx +13 -0
- package/agents/examples/treemap.tsx +88 -0
- package/agents/manifest.json +1081 -0
- package/agents/report-rules.json +7 -0
- package/dist/components/registry/charts/area-chart-card.js +25 -7
- package/dist/components/registry/charts/bar-chart-card.d.ts +0 -1
- package/dist/components/registry/charts/bar-chart-card.js +40 -26
- package/dist/components/registry/charts/line-chart-card.js +2 -2
- package/dist/components/registry/dashboard-01/section-cards.d.ts +2 -0
- package/dist/components/registry/dashboard-01/section-cards.js +42 -35
- package/dist/components/registry/dashboardcn/bar-list.js +18 -11
- package/dist/components/registry/dashboardcn/distribution-bar.js +1 -1
- 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 +22 -0
- package/dist/components/registry/dashboardcn/sparkline.js +117 -0
- package/dist/components/registry/heatmap/calendar-heatmap.d.ts +4 -2
- package/dist/components/registry/heatmap/calendar-heatmap.js +74 -33
- package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
- package/dist/components/registry/heatmap/status-heatmap.js +37 -15
- package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
- package/dist/components/registry/heatmap/weekday-heatmap.js +82 -47
- package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
- package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
- package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
- package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
- package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
- package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
- package/dist/components/registry/niko-table/core/data-table.js +5 -1
- package/dist/components/registry/niko-table/filters/table-faceted-filter.js +4 -4
- package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
- package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/styles.js +3 -3
- package/dist/components/registry/niko-table/types/index.d.ts +9 -0
- package/dist/components/registry/niko-table/ui/table.js +2 -2
- package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
- package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
- package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
- package/dist/components/registry/sidebar-07/nav-main.js +16 -3
- package/dist/components/siyahi/callout.d.ts +24 -0
- package/dist/components/siyahi/callout.js +40 -0
- package/dist/components/siyahi/change-bar.d.ts +21 -0
- package/dist/components/siyahi/change-bar.js +35 -0
- package/dist/components/siyahi/data-bar.d.ts +19 -0
- package/dist/components/siyahi/data-bar.js +29 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
- package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
- package/dist/components/siyahi/data-table-footnote.js +35 -0
- package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
- package/dist/components/siyahi/default-sidebar-open.js +13 -0
- package/dist/components/siyahi/page-hero.d.ts +25 -0
- package/dist/components/siyahi/page-hero.js +41 -0
- package/dist/components/siyahi/page-section.d.ts +4 -1
- package/dist/components/siyahi/page-section.js +6 -3
- package/dist/components/siyahi/page-toc.d.ts +20 -0
- package/dist/components/siyahi/page-toc.js +76 -0
- package/dist/components/siyahi/panel-grid.d.ts +22 -0
- package/dist/components/siyahi/panel-grid.js +34 -0
- package/dist/components/siyahi/quote.d.ts +12 -0
- package/dist/components/siyahi/quote.js +23 -0
- package/dist/components/siyahi/range-position.d.ts +24 -0
- package/dist/components/siyahi/range-position.js +105 -0
- package/dist/components/siyahi/siyahi-provider.d.ts +13 -2
- package/dist/components/siyahi/siyahi-provider.js +17 -4
- package/dist/components/siyahi/target-rows.d.ts +34 -0
- package/dist/components/siyahi/target-rows.js +97 -0
- package/dist/components/siyahi/treemap.d.ts +4 -1
- package/dist/components/siyahi/treemap.js +78 -28
- package/dist/components/siyahi/warning-alert.d.ts +10 -0
- package/dist/components/siyahi/warning-alert.js +20 -0
- 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 +21 -7
- package/dist/index.js +18 -4
- package/dist/lib/chart-frame.d.ts +25 -7
- package/dist/lib/chart-frame.js +251 -127
- package/dist/lib/chart-series.d.ts +12 -6
- package/dist/lib/compact-columns.d.ts +19 -0
- package/dist/lib/compact-columns.js +55 -0
- package/dist/lib/format.d.ts +7 -2
- package/dist/lib/format.js +54 -16
- package/dist/lib/heatmap-navigation.d.ts +8 -0
- package/dist/lib/heatmap-navigation.js +49 -0
- package/dist/lib/treemap.js +6 -1
- package/dist/lib/use-element-width.d.ts +5 -0
- package/dist/lib/use-element-width.js +15 -0
- package/package.json +4 -1
- package/registry.lock.json +16 -0
- package/report.css +33 -32
- package/styles/siyahi.css +221 -39
- package/dist/lib/recharts.d.ts +0 -2
- package/dist/lib/recharts.js +0 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { LineChartCard, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A sar sample every 10 minutes from 15:00; the numbers are made up for the catalogue.
|
|
4
|
+
const data = [
|
|
5
|
+
{ minute: 0, used: 4.1, anon: 2.9 },
|
|
6
|
+
{ minute: 10, used: 4.3, anon: 3.1 },
|
|
7
|
+
{ minute: 20, used: 4.6, anon: 3.4 },
|
|
8
|
+
{ minute: 30, used: 5.2, anon: 4.2 },
|
|
9
|
+
{ minute: 40, used: 7.8, anon: 7.1 },
|
|
10
|
+
{ minute: 50, used: 8.1, anon: 7.6 },
|
|
11
|
+
{ minute: 60, used: 6.2, anon: 5.3 },
|
|
12
|
+
{ minute: 70, used: 4.4, anon: 3.2 },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
16
|
+
{ key: "used", label: "Used", color: "var(--chart-1)" },
|
|
17
|
+
{ key: "anon", label: "Anon", color: "var(--chart-2)" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const clock = (minute: number) => `${Math.floor(15 + minute / 60)}:${String(minute % 60).padStart(2, "0")}`;
|
|
21
|
+
|
|
22
|
+
export default function ChartLineTimelineExample() {
|
|
23
|
+
return (
|
|
24
|
+
<LineChartCard
|
|
25
|
+
title="Memory in use, GiB"
|
|
26
|
+
description="sar -r. Used excludes cache; anon is program memory."
|
|
27
|
+
data={data}
|
|
28
|
+
xKey="minute"
|
|
29
|
+
// Ticks on both ends of the domain: the first sits at the plot's left edge.
|
|
30
|
+
xDomain={[0, 70]}
|
|
31
|
+
xTicks={[0, 10, 20, 30, 40, 50, 60, 70]}
|
|
32
|
+
xFormatter={clock}
|
|
33
|
+
xTooltipFormatter={(minute) => `${clock(minute)} IST, 10-min average`}
|
|
34
|
+
series={series}
|
|
35
|
+
valueFormatter={(v) => v.toFixed(1)}
|
|
36
|
+
yTickFormatter={(v) => v.toFixed(0)}
|
|
37
|
+
curve="linear"
|
|
38
|
+
height={192}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { LineChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
|
+
|
|
4
|
+
const cumulative = [
|
|
5
|
+
{ month: "May", portfolio: 0.012, index: 0.008 },
|
|
6
|
+
{ month: "Jun", portfolio: 0.021, index: 0.015 },
|
|
7
|
+
{ month: "Jul", portfolio: 0.034, index: 0.029 },
|
|
8
|
+
{ month: "Aug", portfolio: -0.006, index: 0.004 },
|
|
9
|
+
{ month: "Sep", portfolio: 0.041, index: 0.031 },
|
|
10
|
+
{ month: "Oct", portfolio: 0.052, index: 0.036 },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const monthly = [
|
|
14
|
+
{ month: "May", portfolio: 0.012, index: 0.008 },
|
|
15
|
+
{ month: "Jun", portfolio: 0.009, index: 0.007 },
|
|
16
|
+
{ month: "Jul", portfolio: 0.013, index: 0.014 },
|
|
17
|
+
{ month: "Aug", portfolio: -0.039, index: -0.024 },
|
|
18
|
+
{ month: "Sep", portfolio: 0.047, index: 0.027 },
|
|
19
|
+
{ month: "Oct", portfolio: 0.011, index: 0.005 },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const series: ChartSeries<(typeof cumulative)[number]> = [
|
|
23
|
+
{ key: "portfolio", label: "Portfolio", color: "var(--chart-1)" },
|
|
24
|
+
{ key: "index", label: "Nifty 50", color: "var(--chart-2)" },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export default function ChartLineExample() {
|
|
28
|
+
const { pct } = useFormat();
|
|
29
|
+
const [mode, setMode] = useState("cumulative");
|
|
30
|
+
return (
|
|
31
|
+
<LineChartCard
|
|
32
|
+
title="Return against the index"
|
|
33
|
+
description={mode === "cumulative" ? "Cumulative, from the start of May" : "Each month on its own"}
|
|
34
|
+
action={
|
|
35
|
+
<ToggleGroup
|
|
36
|
+
value={[mode]}
|
|
37
|
+
onValueChange={([next]) => {
|
|
38
|
+
// Pressing the selected mode again would leave none selected; keep it.
|
|
39
|
+
if (next) setMode(next);
|
|
40
|
+
}}
|
|
41
|
+
variant="outline"
|
|
42
|
+
size="sm"
|
|
43
|
+
aria-label="Mode"
|
|
44
|
+
>
|
|
45
|
+
<ToggleGroupItem value="cumulative">Cumulative return</ToggleGroupItem>
|
|
46
|
+
<ToggleGroupItem value="monthly">Monthly return</ToggleGroupItem>
|
|
47
|
+
</ToggleGroup>
|
|
48
|
+
}
|
|
49
|
+
data={mode === "cumulative" ? cumulative : monthly}
|
|
50
|
+
xKey="month"
|
|
51
|
+
series={series}
|
|
52
|
+
// A formatter goes in as it is: the card calls it with the value alone.
|
|
53
|
+
valueFormatter={pct}
|
|
54
|
+
height={256}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CodeBlock,
|
|
3
|
+
CodeBlockActions,
|
|
4
|
+
CodeBlockContent,
|
|
5
|
+
CodeBlockCopyButton,
|
|
6
|
+
CodeBlockHeader,
|
|
7
|
+
CodeBlockTitle,
|
|
8
|
+
} from "@siyahi/ui";
|
|
9
|
+
|
|
10
|
+
const CHECK = "openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null";
|
|
11
|
+
|
|
12
|
+
const LOG = Array.from(
|
|
13
|
+
{ length: 24 },
|
|
14
|
+
(_, i) =>
|
|
15
|
+
`19:${String(33 + Math.floor(i / 4)).padStart(2, "0")}:${String((i * 15) % 60).padStart(2, "0")} memory.pressure some avg10=${(12 + i * 3.1).toFixed(2)}`,
|
|
16
|
+
).join("\n");
|
|
17
|
+
|
|
18
|
+
export default function CodeBlockExample() {
|
|
19
|
+
return (
|
|
20
|
+
<div className="flex flex-col gap-4">
|
|
21
|
+
<CodeBlock>
|
|
22
|
+
<CodeBlockHeader>
|
|
23
|
+
<CodeBlockTitle>Show the chain a server sends</CodeBlockTitle>
|
|
24
|
+
<CodeBlockActions>
|
|
25
|
+
<CodeBlockCopyButton value={CHECK} />
|
|
26
|
+
</CodeBlockActions>
|
|
27
|
+
</CodeBlockHeader>
|
|
28
|
+
<CodeBlockContent wrap>{CHECK}</CodeBlockContent>
|
|
29
|
+
</CodeBlock>
|
|
30
|
+
<CodeBlock size="sm">
|
|
31
|
+
<CodeBlockActions>
|
|
32
|
+
<CodeBlockCopyButton value={LOG} />
|
|
33
|
+
</CodeBlockActions>
|
|
34
|
+
<CodeBlockContent className="max-h-48">{LOG}</CodeBlockContent>
|
|
35
|
+
</CodeBlock>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Button, Collapsible, CollapsibleContent, CollapsibleTrigger } from "@siyahi/ui";
|
|
2
|
+
import { ChevronsUpDownIcon } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
export default function CollapsibleExample() {
|
|
5
|
+
return (
|
|
6
|
+
<Collapsible className="flex max-w-sm flex-col gap-2">
|
|
7
|
+
<CollapsibleTrigger render={<Button variant="outline" className="w-fit" />}>
|
|
8
|
+
<ChevronsUpDownIcon />
|
|
9
|
+
How lots are matched
|
|
10
|
+
</CollapsibleTrigger>
|
|
11
|
+
<CollapsibleContent className="text-muted-foreground">
|
|
12
|
+
Sells are matched to the oldest buy first, as the tax rules require.
|
|
13
|
+
</CollapsibleContent>
|
|
14
|
+
</Collapsible>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@siyahi/ui";
|
|
2
|
+
import { ChartLineIcon, LandmarkIcon, WalletIcon } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
export default function CommandExample() {
|
|
5
|
+
return (
|
|
6
|
+
<Command className="rounded-lg border">
|
|
7
|
+
<CommandInput placeholder="Jump to a page" />
|
|
8
|
+
<CommandList>
|
|
9
|
+
<CommandEmpty>No page matches.</CommandEmpty>
|
|
10
|
+
<CommandGroup heading="Pages">
|
|
11
|
+
<CommandItem>
|
|
12
|
+
<WalletIcon />
|
|
13
|
+
Holdings
|
|
14
|
+
</CommandItem>
|
|
15
|
+
<CommandItem>
|
|
16
|
+
<ChartLineIcon />
|
|
17
|
+
Realized
|
|
18
|
+
</CommandItem>
|
|
19
|
+
<CommandItem>
|
|
20
|
+
<LandmarkIcon />
|
|
21
|
+
Cash flow
|
|
22
|
+
</CommandItem>
|
|
23
|
+
</CommandGroup>
|
|
24
|
+
</CommandList>
|
|
25
|
+
</Command>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
export default function ContextMenuExample() {
|
|
4
|
+
return (
|
|
5
|
+
<ContextMenu>
|
|
6
|
+
<ContextMenuTrigger className="flex h-24 w-full items-center justify-center rounded-lg border border-dashed text-muted-foreground">
|
|
7
|
+
Right-click or long-press here
|
|
8
|
+
</ContextMenuTrigger>
|
|
9
|
+
<ContextMenuContent>
|
|
10
|
+
<ContextMenuItem>Copy symbol</ContextMenuItem>
|
|
11
|
+
<ContextMenuItem>Open chart</ContextMenuItem>
|
|
12
|
+
</ContextMenuContent>
|
|
13
|
+
</ContextMenu>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CopyButton } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Every command on a setup page, for a reader who wants them all at once.
|
|
4
|
+
const ALL = ["brew install node@24", "corepack enable", "pnpm install"].join("\n");
|
|
5
|
+
|
|
6
|
+
export default function CopyButtonExample() {
|
|
7
|
+
return <CopyButton value={ALL} label="Copy all" />;
|
|
8
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataBar,
|
|
8
|
+
DataTable,
|
|
9
|
+
DataTableBody,
|
|
10
|
+
DataTableHeader,
|
|
11
|
+
DataTableRoot,
|
|
12
|
+
DataTableSortHeader,
|
|
13
|
+
Sparkline,
|
|
14
|
+
useFormat,
|
|
15
|
+
type DataTableColumnDef,
|
|
16
|
+
} from "@siyahi/ui";
|
|
17
|
+
|
|
18
|
+
interface Holding {
|
|
19
|
+
symbol: string;
|
|
20
|
+
value: number;
|
|
21
|
+
gain: number;
|
|
22
|
+
/** Closing prices over the last ten sessions, oldest first. */
|
|
23
|
+
closes: number[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const holdings: Holding[] = [
|
|
27
|
+
{ symbol: "ITC", value: 276000, gain: -18400, closes: [478, 474, 470, 471, 466, 463, 465, 461, 459, 460] },
|
|
28
|
+
{
|
|
29
|
+
symbol: "HDFCBANK",
|
|
30
|
+
value: 262500,
|
|
31
|
+
gain: 21300,
|
|
32
|
+
closes: [1712, 1718, 1726, 1720, 1731, 1744, 1739, 1748, 1752, 1750],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
symbol: "ICICIBANK",
|
|
36
|
+
value: 258000,
|
|
37
|
+
gain: 44100,
|
|
38
|
+
closes: [1250, 1262, 1258, 1271, 1266, 1280, 1284, 1279, 1288, 1290],
|
|
39
|
+
},
|
|
40
|
+
{ symbol: "NIFTYBEES", value: 255600, gain: 12800, closes: [281, 282, 280, 283, 284, 283, 285, 284, 286, 284] },
|
|
41
|
+
{ symbol: "INFY", value: 224400, gain: 30900, closes: [1820, 1834, 1829, 1841, 1852, 1848, 1860, 1855, 1866, 1870] },
|
|
42
|
+
{ symbol: "TCS", value: 166000, gain: -2600, closes: [4180, 4172, 4165, 4170, 4158, 4150, 4161, 4155, 4148, 4150] },
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
// Each bar is a share of its column's largest figure, so the rows draw to one scale.
|
|
46
|
+
const largestValue = Math.max(...holdings.map((h) => h.value));
|
|
47
|
+
const largestGain = Math.max(...holdings.map((h) => Math.abs(h.gain)));
|
|
48
|
+
|
|
49
|
+
function Money({ amount }: { amount: number }) {
|
|
50
|
+
return useFormat().money(amount);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const header = () => <DataTableSortHeader />;
|
|
54
|
+
|
|
55
|
+
const columns: DataTableColumnDef<Holding>[] = [
|
|
56
|
+
{ accessorKey: "symbol", header, size: 120, meta: { label: "Symbol" } },
|
|
57
|
+
{
|
|
58
|
+
accessorKey: "value",
|
|
59
|
+
header,
|
|
60
|
+
size: 170,
|
|
61
|
+
meta: { label: "Value", variant: "number" },
|
|
62
|
+
cell: ({ row }) => (
|
|
63
|
+
<DataBar value={row.original.value} max={largestValue}>
|
|
64
|
+
<Money amount={row.original.value} />
|
|
65
|
+
</DataBar>
|
|
66
|
+
),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
accessorKey: "gain",
|
|
70
|
+
header,
|
|
71
|
+
size: 170,
|
|
72
|
+
meta: { label: "Gain", variant: "number" },
|
|
73
|
+
cell: ({ row }) => (
|
|
74
|
+
<DataBar value={row.original.gain} max={largestGain} tone="sign">
|
|
75
|
+
<Money amount={row.original.gain} />
|
|
76
|
+
</DataBar>
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "closes",
|
|
81
|
+
header: "10 days",
|
|
82
|
+
size: 110,
|
|
83
|
+
enableSorting: false,
|
|
84
|
+
cell: ({ row }) => {
|
|
85
|
+
const { closes } = row.original;
|
|
86
|
+
const rising = (closes.at(-1) ?? 0) >= (closes[0] ?? 0);
|
|
87
|
+
return (
|
|
88
|
+
<Sparkline
|
|
89
|
+
data={closes}
|
|
90
|
+
variant="line"
|
|
91
|
+
color={rising ? "var(--positive)" : "var(--negative)"}
|
|
92
|
+
animate={false}
|
|
93
|
+
className="h-5 w-20"
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
export default function DataBarExample() {
|
|
101
|
+
return (
|
|
102
|
+
<Card>
|
|
103
|
+
<CardHeader>
|
|
104
|
+
<CardTitle>Holdings</CardTitle>
|
|
105
|
+
<CardDescription>Bars give each figure's size against the column's largest</CardDescription>
|
|
106
|
+
</CardHeader>
|
|
107
|
+
<CardContent>
|
|
108
|
+
<DataTableRoot
|
|
109
|
+
data={holdings}
|
|
110
|
+
columns={columns}
|
|
111
|
+
initialState={{ columnPinning: { start: ["symbol"], end: [] } }}
|
|
112
|
+
>
|
|
113
|
+
<DataTable>
|
|
114
|
+
<DataTableHeader />
|
|
115
|
+
<DataTableBody />
|
|
116
|
+
</DataTable>
|
|
117
|
+
</DataTableRoot>
|
|
118
|
+
</CardContent>
|
|
119
|
+
</Card>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataTable,
|
|
8
|
+
DataTableBody,
|
|
9
|
+
DataTableCompactColumnsToggle,
|
|
10
|
+
DataTableHeader,
|
|
11
|
+
DataTableRoot,
|
|
12
|
+
DataTableRowCount,
|
|
13
|
+
DataTableSortHeader,
|
|
14
|
+
DataTableToolbarSection,
|
|
15
|
+
Delta,
|
|
16
|
+
useDataTable,
|
|
17
|
+
useFormat,
|
|
18
|
+
type DataTableColumnDef,
|
|
19
|
+
} from "@siyahi/ui";
|
|
20
|
+
|
|
21
|
+
interface Holding {
|
|
22
|
+
symbol: string;
|
|
23
|
+
sector: string;
|
|
24
|
+
quantity: number;
|
|
25
|
+
value: number;
|
|
26
|
+
change: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const holdings: Holding[] = [
|
|
30
|
+
{ symbol: "INFY", sector: "IT", quantity: 120, value: 224400, change: 0.018 },
|
|
31
|
+
{ symbol: "HDFCBANK", sector: "Banks", quantity: 150, value: 262500, change: -0.006 },
|
|
32
|
+
{ symbol: "TCS", sector: "IT", quantity: 40, value: 166000, change: 0.004 },
|
|
33
|
+
{ symbol: "ITC", sector: "Fast Moving Consumer Goods", quantity: 600, value: 276000, change: -0.012 },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const header = () => <DataTableSortHeader />;
|
|
37
|
+
|
|
38
|
+
// While the Day column is hidden to fit, the day's move rides under the value it belongs to.
|
|
39
|
+
function ValueCell({ holding }: { holding: Holding }) {
|
|
40
|
+
const format = useFormat();
|
|
41
|
+
const { compactColumns } = useDataTable<Holding>();
|
|
42
|
+
if (!compactColumns?.hidden.has("change")) return format.money(holding.value);
|
|
43
|
+
return (
|
|
44
|
+
<div className="flex flex-col items-end">
|
|
45
|
+
{format.money(holding.value)}
|
|
46
|
+
<Delta value={holding.change} />
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const columns: DataTableColumnDef<Holding>[] = [
|
|
52
|
+
{ accessorKey: "symbol", header, size: 140, meta: { label: "Symbol", compact: true } },
|
|
53
|
+
{ accessorKey: "sector", header, size: 120, meta: { label: "Sector" } },
|
|
54
|
+
{ accessorKey: "quantity", header, size: 100, meta: { label: "Qty", variant: "number" } },
|
|
55
|
+
{
|
|
56
|
+
accessorKey: "value",
|
|
57
|
+
header,
|
|
58
|
+
size: 140,
|
|
59
|
+
meta: { label: "Value", variant: "number", compact: true },
|
|
60
|
+
cell: ({ row }) => <ValueCell holding={row.original} />,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
accessorKey: "change",
|
|
64
|
+
header,
|
|
65
|
+
size: 110,
|
|
66
|
+
meta: { label: "Day", variant: "number" },
|
|
67
|
+
cell: ({ row }) => <Delta value={row.original.change} />,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
export default function DataTableCompactExample() {
|
|
72
|
+
return (
|
|
73
|
+
<Card>
|
|
74
|
+
<CardHeader>
|
|
75
|
+
<CardTitle>Holdings on a phone</CardTitle>
|
|
76
|
+
<CardDescription>
|
|
77
|
+
Symbol and value are the key columns. When the columns do not fit, the others hide from the right, and the
|
|
78
|
+
day's move rides under the value once its column is gone; All columns brings back the rest
|
|
79
|
+
</CardDescription>
|
|
80
|
+
</CardHeader>
|
|
81
|
+
<CardContent>
|
|
82
|
+
<DataTableRoot data={holdings} columns={columns}>
|
|
83
|
+
<DataTableToolbarSection>
|
|
84
|
+
<DataTableCompactColumnsToggle />
|
|
85
|
+
<DataTableRowCount unit="holdings" />
|
|
86
|
+
</DataTableToolbarSection>
|
|
87
|
+
<DataTable aria-label="Holdings on a phone">
|
|
88
|
+
<DataTableHeader />
|
|
89
|
+
<DataTableBody />
|
|
90
|
+
</DataTable>
|
|
91
|
+
</DataTableRoot>
|
|
92
|
+
</CardContent>
|
|
93
|
+
</Card>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardDescription,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
DataTable,
|
|
9
|
+
DataTableBody,
|
|
10
|
+
DataTableFacetedFilter,
|
|
11
|
+
DataTableHeader,
|
|
12
|
+
DataTableRoot,
|
|
13
|
+
DataTableRowCount,
|
|
14
|
+
DataTableSearchFilter,
|
|
15
|
+
DataTableSortHeader,
|
|
16
|
+
DataTableToolbarSection,
|
|
17
|
+
Sheet,
|
|
18
|
+
SheetClose,
|
|
19
|
+
SheetContent,
|
|
20
|
+
SheetDescription,
|
|
21
|
+
SheetFooter,
|
|
22
|
+
SheetHeader,
|
|
23
|
+
SheetTitle,
|
|
24
|
+
SheetTrigger,
|
|
25
|
+
useDataTable,
|
|
26
|
+
type DataTableColumnDef,
|
|
27
|
+
} from "@siyahi/ui";
|
|
28
|
+
|
|
29
|
+
interface Holding {
|
|
30
|
+
symbol: string;
|
|
31
|
+
sector: string;
|
|
32
|
+
broker: string;
|
|
33
|
+
}
|
|
34
|
+
const data: Holding[] = [
|
|
35
|
+
{ symbol: "INFY", sector: "Information technology", broker: "Kite" },
|
|
36
|
+
{ symbol: "HDFCBANK", sector: "Banks", broker: "Dhan" },
|
|
37
|
+
{ symbol: "TCS", sector: "Information technology", broker: "Dhan" },
|
|
38
|
+
];
|
|
39
|
+
const header = () => <DataTableSortHeader />;
|
|
40
|
+
const columns: DataTableColumnDef<Holding>[] = [
|
|
41
|
+
{ accessorKey: "symbol", header, size: 140, meta: { label: "Instrument" } },
|
|
42
|
+
{ accessorKey: "sector", header, meta: { label: "Sector" } },
|
|
43
|
+
{ accessorKey: "broker", header, meta: { label: "Broker" } },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function Filters() {
|
|
47
|
+
const { table, isCompact } = useDataTable<Holding>();
|
|
48
|
+
const active = table.state.columnFilters.length;
|
|
49
|
+
const controls = (
|
|
50
|
+
<div className="flex flex-wrap gap-2">
|
|
51
|
+
<DataTableFacetedFilter accessorKey="sector" title="Sector" />
|
|
52
|
+
<DataTableFacetedFilter accessorKey="broker" title="Broker" />
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
if (!isCompact) return controls;
|
|
56
|
+
return (
|
|
57
|
+
<Sheet>
|
|
58
|
+
<SheetTrigger render={<Button variant="outline" size="sm" />}>Filters{active ? ` (${active})` : ""}</SheetTrigger>
|
|
59
|
+
<SheetContent>
|
|
60
|
+
<SheetHeader>
|
|
61
|
+
<SheetTitle>Holding filters</SheetTitle>
|
|
62
|
+
<SheetDescription>Selections stay applied when this panel closes.</SheetDescription>
|
|
63
|
+
</SheetHeader>
|
|
64
|
+
<div className="overflow-y-auto px-4">{controls}</div>
|
|
65
|
+
<SheetFooter>
|
|
66
|
+
<Button variant="outline" disabled={!active} onClick={() => table.resetColumnFilters()}>
|
|
67
|
+
Clear filters
|
|
68
|
+
</Button>
|
|
69
|
+
<SheetClose render={<Button />}>Done</SheetClose>
|
|
70
|
+
</SheetFooter>
|
|
71
|
+
</SheetContent>
|
|
72
|
+
</Sheet>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default function DataTableFiltersExample() {
|
|
77
|
+
return (
|
|
78
|
+
<Card>
|
|
79
|
+
<CardHeader>
|
|
80
|
+
<CardTitle>Holdings with compact filters</CardTitle>
|
|
81
|
+
<CardDescription>Search stays visible; secondary filters move into a panel in narrow space.</CardDescription>
|
|
82
|
+
</CardHeader>
|
|
83
|
+
<CardContent>
|
|
84
|
+
{/* The closed filter panel is absent at first render, so configure its features explicitly. */}
|
|
85
|
+
<DataTableRoot data={data} columns={columns} config={{ enableFilters: true, enableSorting: true }}>
|
|
86
|
+
<DataTableToolbarSection>
|
|
87
|
+
<DataTableSearchFilter
|
|
88
|
+
label="Search compact example"
|
|
89
|
+
placeholder="Search holdings…"
|
|
90
|
+
className="w-full flex-none sm:w-64"
|
|
91
|
+
/>
|
|
92
|
+
<Filters />
|
|
93
|
+
<DataTableRowCount unit="holdings" />
|
|
94
|
+
</DataTableToolbarSection>
|
|
95
|
+
<DataTable aria-label="Holdings with compact filters">
|
|
96
|
+
<DataTableHeader />
|
|
97
|
+
<DataTableBody />
|
|
98
|
+
</DataTable>
|
|
99
|
+
</DataTableRoot>
|
|
100
|
+
</CardContent>
|
|
101
|
+
</Card>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataTable,
|
|
8
|
+
DataTableBody,
|
|
9
|
+
DataTableFacetedFilter,
|
|
10
|
+
DataTableHeader,
|
|
11
|
+
DataTableRoot,
|
|
12
|
+
DataTableRowCount,
|
|
13
|
+
DataTableSearchFilter,
|
|
14
|
+
DataTableSortHeader,
|
|
15
|
+
DataTableToolbarSection,
|
|
16
|
+
Delta,
|
|
17
|
+
useFormat,
|
|
18
|
+
type DataTableColumnDef,
|
|
19
|
+
} from "@siyahi/ui";
|
|
20
|
+
|
|
21
|
+
interface Holding {
|
|
22
|
+
symbol: string;
|
|
23
|
+
sector: string;
|
|
24
|
+
quantity: number;
|
|
25
|
+
value: number;
|
|
26
|
+
change: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const holdings: Holding[] = [
|
|
30
|
+
{ symbol: "INFY", sector: "IT", quantity: 120, value: 224400, change: 0.018 },
|
|
31
|
+
{ symbol: "HDFCBANK", sector: "Banks", quantity: 150, value: 262500, change: -0.006 },
|
|
32
|
+
{ symbol: "TCS", sector: "IT", quantity: 40, value: 166000, change: 0.004 },
|
|
33
|
+
{ symbol: "ITC", sector: "Fast Moving Consumer Goods", quantity: 600, value: 276000, change: -0.012 },
|
|
34
|
+
{ symbol: "ICICIBANK", sector: "Banks", quantity: 200, value: 258000, change: 0.022 },
|
|
35
|
+
{ symbol: "NIFTYBEES", sector: "ETF", quantity: 900, value: 255600, change: 0.009 },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// One click sorts largest (or Z) first; the title comes from meta.label.
|
|
39
|
+
const header = () => <DataTableSortHeader />;
|
|
40
|
+
|
|
41
|
+
function Money({ amount }: { amount: number }) {
|
|
42
|
+
return useFormat().money(amount);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const columns: DataTableColumnDef<Holding>[] = [
|
|
46
|
+
{ accessorKey: "symbol", header, size: 140, meta: { label: "Symbol" } },
|
|
47
|
+
{ accessorKey: "sector", header, size: 120, meta: { label: "Sector" } },
|
|
48
|
+
{ accessorKey: "quantity", header, size: 100, meta: { label: "Qty", variant: "number" } },
|
|
49
|
+
{
|
|
50
|
+
accessorKey: "value",
|
|
51
|
+
header,
|
|
52
|
+
size: 140,
|
|
53
|
+
meta: { label: "Value", variant: "number" },
|
|
54
|
+
cell: ({ row }) => <Money amount={row.original.value} />,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
accessorKey: "change",
|
|
58
|
+
header,
|
|
59
|
+
size: 110,
|
|
60
|
+
meta: { label: "Day", variant: "number" },
|
|
61
|
+
cell: ({ row }) => <Delta value={row.original.change} />,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export default function DataTableExample() {
|
|
66
|
+
return (
|
|
67
|
+
<Card>
|
|
68
|
+
<CardHeader>
|
|
69
|
+
<CardTitle>Holdings</CardTitle>
|
|
70
|
+
<CardDescription>
|
|
71
|
+
Search every column, filter by sector, sort any column in one click; the symbol stays put when the table
|
|
72
|
+
scrolls in wide panels. In narrow panels every column scrolls, leaving room for the values
|
|
73
|
+
</CardDescription>
|
|
74
|
+
</CardHeader>
|
|
75
|
+
<CardContent>
|
|
76
|
+
<DataTableRoot
|
|
77
|
+
data={holdings}
|
|
78
|
+
columns={columns}
|
|
79
|
+
initialState={{ columnPinning: { start: ["symbol"], end: [] } }}
|
|
80
|
+
>
|
|
81
|
+
<DataTableToolbarSection>
|
|
82
|
+
<DataTableSearchFilter
|
|
83
|
+
placeholder="Search holdings…"
|
|
84
|
+
label="Filter holdings"
|
|
85
|
+
className="flex-none sm:w-64"
|
|
86
|
+
/>
|
|
87
|
+
<DataTableFacetedFilter accessorKey="sector" title="Sector" />
|
|
88
|
+
<DataTableRowCount unit="holdings" />
|
|
89
|
+
</DataTableToolbarSection>
|
|
90
|
+
<DataTable aria-label="Holdings">
|
|
91
|
+
<DataTableHeader />
|
|
92
|
+
<DataTableBody />
|
|
93
|
+
</DataTable>
|
|
94
|
+
</DataTableRoot>
|
|
95
|
+
</CardContent>
|
|
96
|
+
</Card>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Delta } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
export default function DeltaExample() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex flex-wrap items-center gap-6">
|
|
6
|
+
<Delta value={0.0234} />
|
|
7
|
+
<Delta value={-0.0108} />
|
|
8
|
+
<Delta value={0} />
|
|
9
|
+
<Delta value={18250} format="money" />
|
|
10
|
+
<Delta value={-4300} format="money" />
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Dialog,
|
|
4
|
+
DialogClose,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogDescription,
|
|
7
|
+
DialogFooter,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
DialogTrigger,
|
|
11
|
+
} from "@siyahi/ui";
|
|
12
|
+
|
|
13
|
+
export default function DialogExample() {
|
|
14
|
+
return (
|
|
15
|
+
<Dialog>
|
|
16
|
+
<DialogTrigger render={<Button variant="outline" className="w-fit" />}>Show fills</DialogTrigger>
|
|
17
|
+
<DialogContent>
|
|
18
|
+
<DialogHeader>
|
|
19
|
+
<DialogTitle>Fills for this sell</DialogTitle>
|
|
20
|
+
<DialogDescription>Each lot this sale was matched against, oldest first.</DialogDescription>
|
|
21
|
+
</DialogHeader>
|
|
22
|
+
<DialogFooter>
|
|
23
|
+
<DialogClose render={<Button variant="outline" />}>Close</DialogClose>
|
|
24
|
+
</DialogFooter>
|
|
25
|
+
</DialogContent>
|
|
26
|
+
</Dialog>
|
|
27
|
+
);
|
|
28
|
+
}
|