@siyahi/ui 0.1.9-next.33 → 0.1.9-next.34
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 +20 -7
- package/agents/examples/chart-panels-three.tsx +51 -0
- package/agents/examples/context-menu.tsx +14 -4
- package/agents/examples/overview-dashboard.tsx +2 -2
- package/agents/examples/{page-hero.tsx → page-header.tsx} +4 -4
- package/agents/examples/select.tsx +2 -1
- package/agents/manifest.json +16 -3
- package/dist/components/registry/charts/area-chart-card.js +1 -0
- package/dist/components/registry/charts/bar-chart-card.js +0 -2
- package/dist/components/registry/heatmap/calendar-heatmap.js +1 -1
- package/dist/components/registry/heatmap/status-heatmap.js +1 -1
- package/dist/components/registry/heatmap/weekday-heatmap.js +1 -1
- package/dist/components/registry/niko-table/core/data-table-structure.js +6 -0
- package/dist/components/registry/niko-table/core/data-table.js +1 -1
- package/dist/components/registry/niko-table/filters/table-column-sort.js +2 -2
- package/dist/components/registry/niko-table/filters/table-faceted-filter.js +1 -1
- package/dist/components/registry/niko-table/lib/column-resize-handle.js +1 -1
- package/dist/components/registry/sidebar-07/nav-user.js +16 -19
- package/dist/components/siyahi/{page-hero.d.ts → page-header.d.ts} +3 -3
- package/dist/components/siyahi/{page-hero.js → page-header.js} +4 -4
- package/dist/components/siyahi/panel-grid.d.ts +5 -2
- package/dist/components/siyahi/panel-grid.js +1 -1
- package/dist/components/siyahi/range-position.js +1 -1
- package/dist/components/siyahi/scatter-chart.js +14 -1
- package/dist/components/siyahi/target-rows.js +2 -2
- package/dist/components/siyahi/treemap.js +0 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lib/chart-frame.d.ts +37 -9
- package/dist/lib/chart-frame.js +60 -30
- package/dist/lib/chart-series.d.ts +3 -2
- package/dist/lib/ticks.d.ts +9 -0
- package/dist/lib/ticks.js +25 -3
- package/dist/lib/use-render-when-fonts-load.d.ts +11 -0
- package/dist/lib/use-render-when-fonts-load.js +49 -0
- package/package.json +1 -1
- package/report.css +1 -0
- package/styles/siyahi.css +51 -4
package/DESIGN.md
CHANGED
|
@@ -24,7 +24,9 @@ a meaning:
|
|
|
24
24
|
inside a 1px border of the same colour all round. Large marks follow the same
|
|
25
25
|
rule: every bar is a tint inside a 1px full-colour edge, not a solid slab.
|
|
26
26
|
A bar is read by its edge, which reaches 3:1 against the card; the tint is a
|
|
27
|
-
fill carried by that edge
|
|
27
|
+
fill carried by that edge: half its colour (`--bar-tint`, 50%), strong
|
|
28
|
+
enough that a thin stacked segment, mostly edge, still shows its colour
|
|
29
|
+
against the next, and a pale slot's bar does not read as the card.
|
|
28
30
|
- **Never a stripe down one side.** Do not mark a notice, card, row or quote
|
|
29
31
|
with a left (or any single-side) coloured border; tint the box or add an
|
|
30
32
|
icon. 1px neutral dividers between columns are separators, not accents, and
|
|
@@ -83,10 +85,15 @@ mono face and the link colour, so the text can point to one.
|
|
|
83
85
|
## Shape
|
|
84
86
|
|
|
85
87
|
- **Square corners everywhere**: panels, cards, buttons, fields, badges,
|
|
86
|
-
toggles, menus,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
toggles, menus, bars and tracks (data bars, progress, a slider's track and
|
|
89
|
+
thumb, a scrollbar's thumb), heatmap cells, treemap tiles and the colour
|
|
90
|
+
chips of charts and legends alike (`--radius` is 0). Only what is round by
|
|
91
|
+
nature stays round: an avatar, a status dot, a line's end dot, a spinner,
|
|
92
|
+
and a signed calendar heatmap's loss day, whose shape carries its sign.
|
|
93
|
+
Never add a `rounded-*` class to a box.
|
|
94
|
+
- **Floating surfaces lie flat.** A menu, a select's list, a popover, a
|
|
95
|
+
dialog, a sheet and a chart's tooltip take no drop shadow and the card's
|
|
96
|
+
hairline for their edge, so they read as a sheet of the page.
|
|
90
97
|
- **Joined toggles.** The items of a `ToggleGroup` sit flush and share their
|
|
91
98
|
borders, one control; the pressed item fills with the foreground.
|
|
92
99
|
- **A code block's copy button sits in a header row** (`CodeBlockHeader`),
|
|
@@ -97,7 +104,7 @@ mono face and the link colour, so the text can point to one.
|
|
|
97
104
|
|
|
98
105
|
## Page header
|
|
99
106
|
|
|
100
|
-
An app page opens on its masthead, `
|
|
107
|
+
An app page opens on its masthead, `PageHeader`: a small mark and eyebrow in the
|
|
101
108
|
mono face and link colour, the title, one muted line saying what the page is,
|
|
102
109
|
the actions at the right, and a hairline under it. One per page; no hero card.
|
|
103
110
|
|
|
@@ -186,7 +193,8 @@ from the catalogue.
|
|
|
186
193
|
|
|
187
194
|
- **Labels are small monospaced capitals**: a stat tile's label and footer
|
|
188
195
|
lines, a `MetricStrip` label, a table's column heads, a sidebar group's
|
|
189
|
-
label,
|
|
196
|
+
label, a group's label in a menu, a select's list or the command palette,
|
|
197
|
+
and a form field's label (muted, above the field). The components and
|
|
190
198
|
the theme set them; never set a label in this style by hand elsewhere, and
|
|
191
199
|
never set a figure or a title in it.
|
|
192
200
|
- **A total row reads as a ledger's**: in `TableFooter`, one rule above it and
|
|
@@ -211,6 +219,11 @@ from the catalogue.
|
|
|
211
219
|
a stack's grey bands read in the legend's order, bottom to top.
|
|
212
220
|
- **No fill under overlapping areas**: from three series on, fills bury each
|
|
213
221
|
other. A stack fills each band with a flat tint, never a gradient.
|
|
222
|
+
- **The value axis just covers the data.** Unless the page fixes it, it ends
|
|
223
|
+
on the round tick just past what is drawn (a 46,800 peak at 50,000, by
|
|
224
|
+
10,000s), a stack's totals for a stack. Bars and stacks reach zero, since
|
|
225
|
+
their length is the value; lines and overlapping areas need not, so a
|
|
226
|
+
revenue line from ₹38L to ₹45L fills the plot rather than its top fifth.
|
|
214
227
|
- **Forecast and today.** `forecastFrom` dashes every line from that point,
|
|
215
228
|
hatches the stretch faintly behind lines on card-coloured halos, labels it
|
|
216
229
|
FORECAST and hollows the end dots (a stack keeps solid edges and no hatching:
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AreaChartCard, BarChartCard, LineChartCard, PanelGrid, useFormat } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// One fund over six months: its month-end growth, its value and what was added each month.
|
|
4
|
+
const months = [
|
|
5
|
+
{ month: "May", growth: 0, value: 410000, added: 20000 },
|
|
6
|
+
{ month: "Jun", growth: 0.025, value: 432000, added: 15000 },
|
|
7
|
+
{ month: "Jul", growth: 0.061, value: 455000, added: 10000 },
|
|
8
|
+
{ month: "Aug", growth: 0.047, value: 461000, added: 25000 },
|
|
9
|
+
{ month: "Sep", growth: 0.11, value: 498000, added: 15000 },
|
|
10
|
+
{ month: "Oct", growth: 0.156, value: 527000, added: 20000 },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// Three short panels in a reading column about as wide as an article (max-w-4xl, 56rem): three across from 42rem.
|
|
14
|
+
export default function ChartPanelsThreeExample() {
|
|
15
|
+
const { pct, money, moneyCompact } = useFormat();
|
|
16
|
+
return (
|
|
17
|
+
<div className="max-w-4xl">
|
|
18
|
+
<PanelGrid columns={3}>
|
|
19
|
+
<LineChartCard
|
|
20
|
+
title="Growth"
|
|
21
|
+
description="Since May, month-end"
|
|
22
|
+
data={months}
|
|
23
|
+
xKey="month"
|
|
24
|
+
series={[{ key: "growth", label: "Growth", color: "var(--chart-1)" }]}
|
|
25
|
+
valueFormatter={pct}
|
|
26
|
+
height={160}
|
|
27
|
+
/>
|
|
28
|
+
<AreaChartCard
|
|
29
|
+
title="Value"
|
|
30
|
+
description="Month-end, ₹"
|
|
31
|
+
data={months}
|
|
32
|
+
xKey="month"
|
|
33
|
+
series={[{ key: "value", label: "Value", color: "var(--chart-1)" }]}
|
|
34
|
+
valueFormatter={money}
|
|
35
|
+
yTickFormatter={moneyCompact}
|
|
36
|
+
height={160}
|
|
37
|
+
/>
|
|
38
|
+
<BarChartCard
|
|
39
|
+
title="Added"
|
|
40
|
+
description="Each month, ₹"
|
|
41
|
+
data={months}
|
|
42
|
+
xKey="month"
|
|
43
|
+
series={[{ key: "added", label: "Added", color: "var(--chart-1)" }]}
|
|
44
|
+
valueFormatter={money}
|
|
45
|
+
yTickFormatter={moneyCompact}
|
|
46
|
+
height={160}
|
|
47
|
+
/>
|
|
48
|
+
</PanelGrid>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ContextMenu,
|
|
3
|
+
ContextMenuContent,
|
|
4
|
+
ContextMenuGroup,
|
|
5
|
+
ContextMenuItem,
|
|
6
|
+
ContextMenuLabel,
|
|
7
|
+
ContextMenuTrigger,
|
|
8
|
+
} from "@siyahi/ui";
|
|
2
9
|
|
|
3
10
|
export default function ContextMenuExample() {
|
|
4
11
|
return (
|
|
5
12
|
<ContextMenu>
|
|
6
13
|
<ContextMenuTrigger className="w-full">
|
|
7
|
-
<div className="flex h-24 items-center justify-center
|
|
14
|
+
<div className="flex h-24 items-center justify-center border text-muted-foreground">
|
|
8
15
|
Right-click or long-press here
|
|
9
16
|
</div>
|
|
10
17
|
</ContextMenuTrigger>
|
|
11
18
|
<ContextMenuContent>
|
|
12
|
-
<
|
|
13
|
-
|
|
19
|
+
<ContextMenuGroup>
|
|
20
|
+
<ContextMenuLabel>Order</ContextMenuLabel>
|
|
21
|
+
<ContextMenuItem>Copy order number</ContextMenuItem>
|
|
22
|
+
<ContextMenuItem>Open order</ContextMenuItem>
|
|
23
|
+
</ContextMenuGroup>
|
|
14
24
|
</ContextMenuContent>
|
|
15
25
|
</ContextMenu>
|
|
16
26
|
);
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
CardTitle,
|
|
10
10
|
Delta,
|
|
11
11
|
Input,
|
|
12
|
-
|
|
12
|
+
PageHeader,
|
|
13
13
|
PanelGrid,
|
|
14
14
|
StatusBadge,
|
|
15
15
|
Table,
|
|
@@ -126,7 +126,7 @@ export default function OverviewDashboard() {
|
|
|
126
126
|
const shown = holdings.filter((row) => row.name.toLowerCase().includes(query.trim().toLowerCase()));
|
|
127
127
|
return (
|
|
128
128
|
<div className="flex flex-col gap-6">
|
|
129
|
-
<
|
|
129
|
+
<PageHeader
|
|
130
130
|
mark={<InkDrop />}
|
|
131
131
|
eyebrow="The Book"
|
|
132
132
|
title="Holdings"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Button,
|
|
1
|
+
import { Button, PageHeader } from "@siyahi/ui";
|
|
2
2
|
import { ArrowRightIcon } from "lucide-react";
|
|
3
3
|
|
|
4
|
-
// The catalogue's own ink drop, painted with currentColor so the
|
|
4
|
+
// The catalogue's own ink drop, painted with currentColor so the header tints it.
|
|
5
5
|
function InkDrop() {
|
|
6
6
|
return (
|
|
7
7
|
<svg viewBox="0 0 16 16">
|
|
@@ -14,9 +14,9 @@ function InkDrop() {
|
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export default function
|
|
17
|
+
export default function PageHeaderExample() {
|
|
18
18
|
return (
|
|
19
|
-
<
|
|
19
|
+
<PageHeader
|
|
20
20
|
eyebrow="@siyahi/ui"
|
|
21
21
|
title="Siyahi"
|
|
22
22
|
lead="Ink for numbers. A design system for pages people read figures from: dashboards, ledgers, reports."
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@siyahi/ui";
|
|
1
|
+
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@siyahi/ui";
|
|
2
2
|
|
|
3
3
|
const stores = [
|
|
4
4
|
{ label: "All stores", value: "all" },
|
|
@@ -15,6 +15,7 @@ export default function SelectExample() {
|
|
|
15
15
|
</SelectTrigger>
|
|
16
16
|
<SelectContent>
|
|
17
17
|
<SelectGroup>
|
|
18
|
+
<SelectLabel>Sales channel</SelectLabel>
|
|
18
19
|
{stores.map((store) => (
|
|
19
20
|
<SelectItem key={store.value} value={store.value}>
|
|
20
21
|
{store.label}
|
package/agents/manifest.json
CHANGED
|
@@ -671,6 +671,16 @@
|
|
|
671
671
|
"useFormat"
|
|
672
672
|
]
|
|
673
673
|
},
|
|
674
|
+
{
|
|
675
|
+
"file": "agents/examples/chart-panels-three.tsx",
|
|
676
|
+
"components": [
|
|
677
|
+
"AreaChartCard",
|
|
678
|
+
"BarChartCard",
|
|
679
|
+
"LineChartCard",
|
|
680
|
+
"PanelGrid",
|
|
681
|
+
"useFormat"
|
|
682
|
+
]
|
|
683
|
+
},
|
|
674
684
|
{
|
|
675
685
|
"file": "agents/examples/chart-panels.tsx",
|
|
676
686
|
"components": [
|
|
@@ -717,7 +727,9 @@
|
|
|
717
727
|
"components": [
|
|
718
728
|
"ContextMenu",
|
|
719
729
|
"ContextMenuContent",
|
|
730
|
+
"ContextMenuGroup",
|
|
720
731
|
"ContextMenuItem",
|
|
732
|
+
"ContextMenuLabel",
|
|
721
733
|
"ContextMenuTrigger"
|
|
722
734
|
]
|
|
723
735
|
},
|
|
@@ -1038,7 +1050,7 @@
|
|
|
1038
1050
|
"CardTitle",
|
|
1039
1051
|
"Delta",
|
|
1040
1052
|
"Input",
|
|
1041
|
-
"
|
|
1053
|
+
"PageHeader",
|
|
1042
1054
|
"PanelGrid",
|
|
1043
1055
|
"StatusBadge",
|
|
1044
1056
|
"Table",
|
|
@@ -1054,10 +1066,10 @@
|
|
|
1054
1066
|
]
|
|
1055
1067
|
},
|
|
1056
1068
|
{
|
|
1057
|
-
"file": "agents/examples/page-
|
|
1069
|
+
"file": "agents/examples/page-header.tsx",
|
|
1058
1070
|
"components": [
|
|
1059
1071
|
"Button",
|
|
1060
|
-
"
|
|
1072
|
+
"PageHeader"
|
|
1061
1073
|
]
|
|
1062
1074
|
},
|
|
1063
1075
|
{
|
|
@@ -1208,6 +1220,7 @@
|
|
|
1208
1220
|
"SelectContent",
|
|
1209
1221
|
"SelectGroup",
|
|
1210
1222
|
"SelectItem",
|
|
1223
|
+
"SelectLabel",
|
|
1211
1224
|
"SelectTrigger",
|
|
1212
1225
|
"SelectValue"
|
|
1213
1226
|
]
|
|
@@ -18,6 +18,7 @@ function AreaChartCard({ stacked = false, curve = "monotone", ...props }) {
|
|
|
18
18
|
return /* @__PURE__ */ jsxs(ChartFrame, {
|
|
19
19
|
chart: AreaChart,
|
|
20
20
|
logBlocked: stacked ? "Log cannot show stacked areas" : void 0,
|
|
21
|
+
stackOffset: stacked ? "none" : void 0,
|
|
21
22
|
endLabels: !stacked,
|
|
22
23
|
forecastHatch: !stacked,
|
|
23
24
|
curve,
|
|
@@ -3,13 +3,11 @@ import { ChartFrame, barFill, seriesFill } from "../../../lib/chart-frame.js";
|
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { Bar, BarChart, Cell } from "recharts";
|
|
5
5
|
//#region src/components/registry/charts/bar-chart-card.tsx
|
|
6
|
-
const DOWN_FROM_ZERO = ["auto", 0];
|
|
7
6
|
/** Values over an ordered axis as bars: one series, or several grouped or stacked. */
|
|
8
7
|
function BarChartCard({ stacked = false, selected = null, onSelect, ...props }) {
|
|
9
8
|
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
10
9
|
chart: BarChart,
|
|
11
10
|
...props,
|
|
12
|
-
yDomain: props.yDomain ?? (props.data.some((row) => props.series.some(({ key }) => Number(row[key]) > 0)) ? void 0 : DOWN_FROM_ZERO),
|
|
13
11
|
stackOffset: stacked ? "sign" : void 0,
|
|
14
12
|
onClick: onSelect ? ({ activeTooltipIndex, isTooltipActive }) => {
|
|
15
13
|
if (!isTooltipActive || activeTooltipIndex == null) return;
|
|
@@ -226,7 +226,7 @@ const getMonthLabels = (weeks, monthNames = generateMonthLabels(), yearTicks = f
|
|
|
226
226
|
* @param levels - Total number of legend cells (including empty when not normalized). Default: 5
|
|
227
227
|
* @param isNormalized - When true, uses min-max normalization across the dataset (suitable for signed values). When false (default), treats 0 as empty and scales from 0 to max.
|
|
228
228
|
*/
|
|
229
|
-
const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmptyColumn = false, blockSize: blockSizeProp, blockMargin = 4, blockRadius =
|
|
229
|
+
const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmptyColumn = false, blockSize: blockSizeProp, blockMargin = 4, blockRadius = 0, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, signed = false, range, colors, locale, labels: labelsProp, fontSize = 14, emptyState, totalCount: totalCountProp, style = EMPTY_STYLE, className, children, ...props }) => {
|
|
230
230
|
const levels = Math.max(1, levelsProp);
|
|
231
231
|
const [rootRef, rootWidth] = useElementWidth();
|
|
232
232
|
const dataWithLevels = useMemo(() => {
|
|
@@ -109,7 +109,7 @@ const useStatusHeatmap = () => {
|
|
|
109
109
|
* @param blockAspectRatio - Width/height ratio of blocks. Default: bars share the full width
|
|
110
110
|
* @param colors - Custom colors for critical, degraded, and healthy states
|
|
111
111
|
*/
|
|
112
|
-
const StatusHeatmap = ({ data, dateFormat = "MMM d", blockSize = 40, blockMargin = 2, blockRadius =
|
|
112
|
+
const StatusHeatmap = ({ data, dateFormat = "MMM d", blockSize = 40, blockMargin = 2, blockRadius = 0, blockAspectRatio: blockAspectRatioProp, colors, locale, labels: labelsProp, fontSize = 14, emptyState, statusValues = [
|
|
113
113
|
0,
|
|
114
114
|
1,
|
|
115
115
|
2,
|
|
@@ -89,7 +89,7 @@ const useWeekdayHeatmap = () => {
|
|
|
89
89
|
* @param extraRow - Appends an aggregated row below the grid. `compute` receives all activities and must return 24 values (one per hour). Rendered through `renderExtraRow` on the body, or falls back to `children`.
|
|
90
90
|
* @param extraColumn - Appends an aggregated column to the right of the grid. `compute` receives all activities and must return 7 values indexed by weekday 0–6. Rendered through `renderExtraColumn` on the body, or falls back to `children`.
|
|
91
91
|
*/
|
|
92
|
-
const WeekdayHeatmap = ({ data, weekStart = 0, hours = HOURS, weekdays: displayedWeekdays, use12Hour = false, blockSize: blockSizeProp, blockMargin = 4, blockRadius =
|
|
92
|
+
const WeekdayHeatmap = ({ data, weekStart = 0, hours = HOURS, weekdays: displayedWeekdays, use12Hour = false, blockSize: blockSizeProp, blockMargin = 4, blockRadius = 0, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, colors, locale, labels: labelsProp, fontSize = 14, emptyState, totalCount: totalCountProp, extraRow, extraColumn, style = EMPTY_STYLE, className, children, ...props }) => {
|
|
93
93
|
const levels = Math.max(1, levelsProp);
|
|
94
94
|
const [rootRef, rootWidth] = useElementWidth();
|
|
95
95
|
const weekdays = useMemo(() => displayedWeekdays ?? Array.from({ length: 7 }, (_, i) => (weekStart + i) % 7), [displayedWeekdays, weekStart]);
|
|
@@ -19,6 +19,10 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
19
19
|
import React from "react";
|
|
20
20
|
import { flexRender } from "@tanstack/react-table";
|
|
21
21
|
//#region src/components/registry/niko-table/core/data-table-structure.tsx
|
|
22
|
+
const ARIA_SORT = {
|
|
23
|
+
asc: "ascending",
|
|
24
|
+
desc: "descending"
|
|
25
|
+
};
|
|
22
26
|
const DataTableHeader = React.memo(function DataTableHeader({ className, sticky = true }) {
|
|
23
27
|
const { table, headerMinWidths, setColumnResizePreview, isCompact } = useDataTable();
|
|
24
28
|
const resizing = table?.options.enableColumnResizing ?? false;
|
|
@@ -39,8 +43,10 @@ const DataTableHeader = React.memo(function DataTableHeader({ className, sticky
|
|
|
39
43
|
}),
|
|
40
44
|
...getCommonPinningStyles(header.column, true, !isCompact)
|
|
41
45
|
};
|
|
46
|
+
const sorted = !header.isPlaceholder && header.column.getSortIndex() === 0 && header.column.getIsSorted();
|
|
42
47
|
return /* @__PURE__ */ jsxs(TableHead, {
|
|
43
48
|
"data-col-id": header.column.id,
|
|
49
|
+
"aria-sort": sorted ? ARIA_SORT[sorted] : void 0,
|
|
44
50
|
"data-numeric": header.column.columnDef.meta?.variant === "number" || void 0,
|
|
45
51
|
style: headerStyle,
|
|
46
52
|
className: cn(!isCompact && header.column.getIsPinned() && "bg-background", resizing && "relative overflow-hidden"),
|
|
@@ -117,7 +117,7 @@ function DataTable({ children, className, height, maxHeight, "aria-label": label
|
|
|
117
117
|
"aria-label": labelledBy ? void 0 : label,
|
|
118
118
|
"aria-labelledby": labelledBy,
|
|
119
119
|
tabIndex: 0,
|
|
120
|
-
className: cn("relative isolate w-full overflow-auto rounded-lg border", "[&::-webkit-scrollbar]:h-2.5 [&::-webkit-scrollbar]:w-2.5", "[&::-webkit-scrollbar-track]:bg-transparent", "[&::-webkit-scrollbar-thumb]:
|
|
120
|
+
className: cn("relative isolate w-full overflow-auto rounded-lg border", "[&::-webkit-scrollbar]:h-2.5 [&::-webkit-scrollbar]:w-2.5", "[&::-webkit-scrollbar-track]:bg-transparent", "[&::-webkit-scrollbar-thumb]:bg-border/40", "hover:[&::-webkit-scrollbar-thumb]:bg-border", "[&::-webkit-scrollbar-thumb:hover]:bg-border/80!", "scrollbar-thin scrollbar-thumb-border/40 scrollbar-track-transparent", "hover:scrollbar-thumb-border", parsed.safeClassName),
|
|
121
121
|
style: {
|
|
122
122
|
height: finalHeight,
|
|
123
123
|
maxHeight: finalMaxHeight
|
|
@@ -82,7 +82,7 @@ function TableColumnSortOptions({ column, table: propTable, variant: propVariant
|
|
|
82
82
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
83
83
|
className: "flex items-center gap-2",
|
|
84
84
|
children: [/* @__PURE__ */ jsx("span", { children: "Column Sort" }), showSortBadge && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
85
|
-
render: /* @__PURE__ */ jsx("span", { className: "flex size-4 cursor-help items-center justify-center
|
|
85
|
+
render: /* @__PURE__ */ jsx("span", { className: "flex size-4 cursor-help items-center justify-center bg-primary text-[10px] font-medium text-primary-foreground" }),
|
|
86
86
|
children: sortIndex + 1
|
|
87
87
|
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
88
88
|
side: "right",
|
|
@@ -159,7 +159,7 @@ function TableColumnSortMenu({ column, table: propTable, variant: propVariant, c
|
|
|
159
159
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
160
160
|
className: "relative flex items-center justify-center",
|
|
161
161
|
children: [/* @__PURE__ */ jsx(SortIcon, { className: "size-4" }), showSortBadge && /* @__PURE__ */ jsx("span", {
|
|
162
|
-
className: "absolute -top-1 -right-2 flex size-3 items-center justify-center
|
|
162
|
+
className: "absolute -top-1 -right-2 flex size-3 items-center justify-center bg-primary text-[9px] text-primary-foreground",
|
|
163
163
|
children: sortIndex + 1
|
|
164
164
|
})]
|
|
165
165
|
}), /* @__PURE__ */ jsx("span", {
|
|
@@ -107,7 +107,7 @@ function TableFacetedFilter({ column, title, options = [], multiple, onValueChan
|
|
|
107
107
|
children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: trigger || /* @__PURE__ */ jsxs(Button, {
|
|
108
108
|
variant: "outline",
|
|
109
109
|
size: "sm",
|
|
110
|
-
className: "h-8
|
|
110
|
+
className: "h-8",
|
|
111
111
|
children: [
|
|
112
112
|
selectedValues?.size > 0 ? /* @__PURE__ */ jsx("div", {
|
|
113
113
|
role: "button",
|
|
@@ -168,7 +168,7 @@ function DataTableColumnResizeHandle({ header, isFlex = false, setResizePreview
|
|
|
168
168
|
}
|
|
169
169
|
},
|
|
170
170
|
className: "group/resize absolute top-0 right-0 z-10 flex h-full w-2 cursor-col-resize touch-none justify-end outline-none select-none",
|
|
171
|
-
children: /* @__PURE__ */ jsx("div", { className: cn("my-1.5 w-px
|
|
171
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("my-1.5 w-px bg-border opacity-0 transition-all", "group-hover/resize:my-0 group-hover/resize:w-0.5 group-hover/resize:bg-primary group-hover/resize:opacity-100", "group-focus-visible/resize:my-0 group-focus-visible/resize:w-0.5 group-focus-visible/resize:bg-primary group-focus-visible/resize:opacity-100", isResizing && "my-0 w-0.5 bg-primary opacity-100") })
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
174
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Avatar, AvatarFallback, AvatarImage } from "../../ui/avatar.js";
|
|
2
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem,
|
|
2
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../../ui/dropdown-menu.js";
|
|
3
3
|
import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from "../../ui/sidebar.js";
|
|
4
4
|
import { BadgeCheckIcon, BellIcon, ChevronsUpDownIcon, CreditCardIcon, LogOutIcon, SparklesIcon } from "lucide-react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -34,25 +34,22 @@ function NavUser({ user }) {
|
|
|
34
34
|
align: "end",
|
|
35
35
|
sideOffset: 4,
|
|
36
36
|
children: [
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
-
className: "
|
|
39
|
-
children: /* @__PURE__ */ jsxs(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
className: "
|
|
46
|
-
children:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
className: "truncate text-xs",
|
|
51
|
-
children: user.email
|
|
52
|
-
})]
|
|
37
|
+
/* @__PURE__ */ jsxs("div", {
|
|
38
|
+
className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm",
|
|
39
|
+
children: [/* @__PURE__ */ jsxs(Avatar, { children: [/* @__PURE__ */ jsx(AvatarImage, {
|
|
40
|
+
src: user.avatar,
|
|
41
|
+
alt: user.name
|
|
42
|
+
}), /* @__PURE__ */ jsx(AvatarFallback, { children: "CN" })] }), /* @__PURE__ */ jsxs("div", {
|
|
43
|
+
className: "grid flex-1 text-left text-sm leading-tight",
|
|
44
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
45
|
+
className: "truncate font-medium",
|
|
46
|
+
children: user.name
|
|
47
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
48
|
+
className: "truncate text-xs",
|
|
49
|
+
children: user.email
|
|
53
50
|
})]
|
|
54
|
-
})
|
|
55
|
-
})
|
|
51
|
+
})]
|
|
52
|
+
}),
|
|
56
53
|
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
57
54
|
/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsxs(DropdownMenuItem, { children: [/* @__PURE__ */ jsx(SparklesIcon, {}), "Upgrade to Pro"] }) }),
|
|
58
55
|
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
-
//#region src/components/siyahi/page-
|
|
3
|
-
export interface
|
|
2
|
+
//#region src/components/siyahi/page-header.d.ts
|
|
3
|
+
export interface PageHeaderProps {
|
|
4
4
|
/** A short line above the title in the mono face and the link colour, such as the app or a section name. */
|
|
5
5
|
eyebrow?: ReactNode;
|
|
6
6
|
/** The page's h1. */
|
|
@@ -19,5 +19,5 @@ export interface PageHeroProps {
|
|
|
19
19
|
* the actions at the right, and a hairline under it all. One per page, above everything else; a section uses
|
|
20
20
|
* PageSection.
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function PageHeader({ eyebrow, title, lead, detail, actions, mark }: PageHeaderProps): import("react").JSX.Element;
|
|
23
23
|
//#endregion
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
//#region src/components/siyahi/page-
|
|
2
|
+
//#region src/components/siyahi/page-header.tsx
|
|
3
3
|
/**
|
|
4
4
|
* The masthead at the top of a page: a small mark and eyebrow, the title, one muted line saying what the page is,
|
|
5
5
|
* the actions at the right, and a hairline under it all. One per page, above everything else; a section uses
|
|
6
6
|
* PageSection.
|
|
7
7
|
*/
|
|
8
|
-
function
|
|
8
|
+
function PageHeader({ eyebrow, title, lead, detail, actions, mark }) {
|
|
9
9
|
return /* @__PURE__ */ jsxs("header", {
|
|
10
|
-
"data-slot": "page-
|
|
10
|
+
"data-slot": "page-header",
|
|
11
11
|
className: "flex flex-wrap items-end justify-between gap-x-6 gap-y-3 border-b pb-4",
|
|
12
12
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
13
13
|
className: "flex min-w-0 flex-col gap-1",
|
|
@@ -40,4 +40,4 @@ function PageHero({ eyebrow, title, lead, detail, actions, mark }) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
-
export {
|
|
43
|
+
export { PageHeader };
|
|
@@ -3,11 +3,14 @@ import { ReactNode } from "react";
|
|
|
3
3
|
declare const COLUMNS: {
|
|
4
4
|
readonly 1: "";
|
|
5
5
|
readonly 2: "@2xl/panels:grid-cols-2";
|
|
6
|
-
readonly 3: "@2xl/panels:grid-cols-
|
|
6
|
+
readonly 3: "@2xl/panels:grid-cols-3";
|
|
7
7
|
readonly 4: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-4";
|
|
8
8
|
};
|
|
9
9
|
export interface PanelGridProps {
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Blocks across from a 42rem grid, so three short ones fit a reading column (an article's 55rem); 4 goes two across
|
|
12
|
+
* there and four from 64rem. Below 42rem they sit one under another.
|
|
13
|
+
*/
|
|
11
14
|
columns?: keyof typeof COLUMNS | undefined;
|
|
12
15
|
children: ReactNode;
|
|
13
16
|
className?: string | undefined;
|
|
@@ -26,7 +26,7 @@ function RangePosition({ low, high, value, lowLabel = "Low", highLabel = "High",
|
|
|
26
26
|
style: { width: at }
|
|
27
27
|
}), /* @__PURE__ */ jsx("div", {
|
|
28
28
|
"data-slot": "range-thumb",
|
|
29
|
-
className: cn("absolute top-1/2 -translate-1/2
|
|
29
|
+
className: cn("absolute top-1/2 -translate-1/2 border-2 border-foreground bg-card", variant === "full" ? "size-3.5" : "size-2.5"),
|
|
30
30
|
style: { left: at }
|
|
31
31
|
})]
|
|
32
32
|
});
|
|
@@ -3,6 +3,7 @@ import { ChartContainer } from "../ui/chart.js";
|
|
|
3
3
|
import { LOG_BLOCKED, useAxisScale } from "./scale-toggle.js";
|
|
4
4
|
import { useLocale } from "./siyahi-provider.js";
|
|
5
5
|
import { fitsLog, ticksFor } from "../../lib/ticks.js";
|
|
6
|
+
import { fontLoads, useRenderWhenFontsLoad } from "../../lib/use-render-when-fonts-load.js";
|
|
6
7
|
import { corners, dotSizes, placeLabels, quadrantSplit } from "../../lib/scatter.js";
|
|
7
8
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
9
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -43,6 +44,10 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
43
44
|
const formatY = useMemo(() => yFormatter ?? new Intl.NumberFormat(numberLocale).format, [yFormatter, numberLocale]);
|
|
44
45
|
const formatSize = useMemo(() => sizeFormatter ?? new Intl.NumberFormat(numberLocale).format, [sizeFormatter, numberLocale]);
|
|
45
46
|
const drawn = useMemo(() => points.filter((p) => p.y !== null && Number.isFinite(p.y) && Number.isFinite(p.x)), [points]);
|
|
47
|
+
useRenderWhenFontsLoad(() => {
|
|
48
|
+
const { measure } = labelType();
|
|
49
|
+
return [...labels > 0 ? drawn.map(({ name }) => name) : [], ...Object.values(quadrants?.labels ?? {})].map((name) => name ? measure(name) : 0).join();
|
|
50
|
+
});
|
|
46
51
|
const both = xScaleToggle && yScaleToggle;
|
|
47
52
|
const across = useAxisScale({
|
|
48
53
|
initial: xScale,
|
|
@@ -297,8 +302,12 @@ function Dot({ cx, cy, payload, index, "data-recharts-item-id": itemId, selected
|
|
|
297
302
|
strokeWidth: RING
|
|
298
303
|
}), dot] });
|
|
299
304
|
}
|
|
300
|
-
/**
|
|
305
|
+
/**
|
|
306
|
+
* A name's width in the labels' type, measured on a canvas once per font and name, and again after each font load:
|
|
307
|
+
* the font string is the same before and after Geist arrives, and a width measured before was the fallback's.
|
|
308
|
+
*/
|
|
301
309
|
const widths = /* @__PURE__ */ new Map();
|
|
310
|
+
let widthsAfter = 0;
|
|
302
311
|
let canvas;
|
|
303
312
|
/** The labels' type as the page sets it: text-xs is three quarters of the root size, which a reader may enlarge. */
|
|
304
313
|
function labelType() {
|
|
@@ -309,6 +318,10 @@ function labelType() {
|
|
|
309
318
|
const size = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) * .75;
|
|
310
319
|
const font = `500 ${size}px ${getComputedStyle(document.body).fontFamily}`;
|
|
311
320
|
canvas ??= document.createElement("canvas").getContext("2d");
|
|
321
|
+
if (fontLoads() !== widthsAfter) {
|
|
322
|
+
widths.clear();
|
|
323
|
+
widthsAfter = fontLoads();
|
|
324
|
+
}
|
|
312
325
|
const measure = (text) => {
|
|
313
326
|
const id = `${font}\n${text}`;
|
|
314
327
|
let width = widths.get(id);
|
|
@@ -37,7 +37,7 @@ function TargetRows({ rows, domain, valueFormatter, className }) {
|
|
|
37
37
|
/* @__PURE__ */ jsxs("div", {
|
|
38
38
|
className: "flex items-baseline justify-between gap-3",
|
|
39
39
|
children: [/* @__PURE__ */ jsx("span", {
|
|
40
|
-
className: "
|
|
40
|
+
className: "min-w-0 font-medium wrap-anywhere",
|
|
41
41
|
children: row.label
|
|
42
42
|
}), /* @__PURE__ */ jsx("span", {
|
|
43
43
|
className: "shrink-0 text-base font-semibold tabular-nums",
|
|
@@ -47,7 +47,7 @@ function TargetRows({ rows, domain, valueFormatter, className }) {
|
|
|
47
47
|
/* @__PURE__ */ jsxs("div", {
|
|
48
48
|
className: "flex justify-between gap-3 text-muted-foreground",
|
|
49
49
|
children: [/* @__PURE__ */ jsx("span", {
|
|
50
|
-
className: "
|
|
50
|
+
className: "min-w-0 wrap-anywhere",
|
|
51
51
|
children: row.detail
|
|
52
52
|
}), /* @__PURE__ */ jsxs("span", {
|
|
53
53
|
className: "shrink-0 tabular-nums",
|
|
@@ -108,7 +108,6 @@ function Treemap({ items, height, range, onHover, selected, onSelect }) {
|
|
|
108
108
|
/* @__PURE__ */ jsx("rect", {
|
|
109
109
|
width: "100%",
|
|
110
110
|
height: "100%",
|
|
111
|
-
rx: 4,
|
|
112
111
|
style: { fill: heat(item.change, range) }
|
|
113
112
|
}),
|
|
114
113
|
key === selectedKey && /* @__PURE__ */ jsx("rect", {
|
|
@@ -116,7 +115,6 @@ function Treemap({ items, height, range, onHover, selected, onSelect }) {
|
|
|
116
115
|
y: 1,
|
|
117
116
|
width: box.width - 2,
|
|
118
117
|
height: box.height - 2,
|
|
119
|
-
rx: 3,
|
|
120
118
|
fill: "none",
|
|
121
119
|
strokeWidth: 2,
|
|
122
120
|
className: "stroke-foreground"
|
|
@@ -150,7 +148,6 @@ function Swatch({ label, fill }) {
|
|
|
150
148
|
children: [/* @__PURE__ */ jsx("title", { children: label }), /* @__PURE__ */ jsx("rect", {
|
|
151
149
|
width: "100%",
|
|
152
150
|
height: "100%",
|
|
153
|
-
rx: 2,
|
|
154
151
|
style: { fill }
|
|
155
152
|
})]
|
|
156
153
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ import { DrawdownChartCard, DrawdownChartCardProps, DrawdownPoint, drawdowns } f
|
|
|
64
64
|
import { HistogramBin, HistogramChartCard, HistogramChartCardProps, HistogramMark, bucketOf, histogram, markLines, percentile } from "./components/siyahi/histogram-chart.js";
|
|
65
65
|
import { InlineCode } from "./components/siyahi/inline-code.js";
|
|
66
66
|
import { LocalTime, LocalTimeProps } from "./components/siyahi/local-time.js";
|
|
67
|
-
import {
|
|
67
|
+
import { PageHeader, PageHeaderProps } from "./components/siyahi/page-header.js";
|
|
68
68
|
import { PageSection, PageSectionProps, PageSubheading } from "./components/siyahi/page-section.js";
|
|
69
69
|
import { PageToc, PageTocItem, PageTocProps } from "./components/siyahi/page-toc.js";
|
|
70
70
|
import { PanelGrid, PanelGridProps } from "./components/siyahi/panel-grid.js";
|
|
@@ -112,4 +112,4 @@ import { Textarea } from "./components/ui/textarea.js";
|
|
|
112
112
|
import { Toggle, toggleVariants } from "./components/ui/toggle.js";
|
|
113
113
|
import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group.js";
|
|
114
114
|
import { Formatters, TimeOptions, count, money, moneyCompact, pct, time, useFormat } from "./lib/format.js";
|
|
115
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, AreaChartCard, AreaChartCardProps, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, AxisScaleOptions, Badge, BarChartCard, BarChartCardProps, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Callout, CalloutProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeBarProps, ChangeGrid, ChangeGridProps, ChangeGridRow, ChartColor, ChartConfig, ChartContainer, ChartCurve, ChartLegend, ChartLegendContent, ChartReferenceLine, ChartSeries, ChartSeriesItem, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompactColumns, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataBarProps, DataList, DataListItem, DataListItemProps, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableCompactColumnsToggle, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableFootnoteProps, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowCount, DataTableRowCountProps, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSkeletonProps, DataTableSortHeader, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DistributionBarProps, DistributionMarker, DistributionSegment, DrawdownChartCard, DrawdownChartCardProps, DrawdownPoint, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, HistogramBin, HistogramChartCard, HistogramChartCardProps, HistogramMark, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, LOG_BLOCKED, Label, Labels, LineChartCard, LineChartCardProps, LineMarksProps, LocalTime, LocalTimeProps, MetricStrip, MetricStripItem, MetricStripProps, NavMain, NavProjects, NavUser, NumericKey, NumericXProps, type Option,
|
|
115
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, AreaChartCard, AreaChartCardProps, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, AxisScaleOptions, Badge, BarChartCard, BarChartCardProps, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Callout, CalloutProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeBarProps, ChangeGrid, ChangeGridProps, ChangeGridRow, ChartColor, ChartConfig, ChartContainer, ChartCurve, ChartLegend, ChartLegendContent, ChartReferenceLine, ChartSeries, ChartSeriesItem, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompactColumns, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataBarProps, DataList, DataListItem, DataListItemProps, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableCompactColumnsToggle, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableFootnoteProps, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowCount, DataTableRowCountProps, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSkeletonProps, DataTableSortHeader, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DistributionBarProps, DistributionMarker, DistributionSegment, DrawdownChartCard, DrawdownChartCardProps, DrawdownPoint, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, HistogramBin, HistogramChartCard, HistogramChartCardProps, HistogramMark, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, LOG_BLOCKED, Label, Labels, LineChartCard, LineChartCardProps, LineMarksProps, LocalTime, LocalTimeProps, MetricStrip, MetricStripItem, MetricStripProps, NavMain, NavProjects, NavUser, NumericKey, NumericXProps, type Option, PageHeader, PageHeaderProps, PageSection, PageSectionProps, PageSubheading, PageToc, PageTocItem, PageTocProps, PanelGrid, PanelGridProps, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, PriceChartProps, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, type QueryKeys, Quote, QuoteProps, RangePosition, RangePositionProps, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScaleToggle, ScaleToggleProps, ScatterChartCard, ScatterChartCardProps, ScatterDetail, ScatterPoint, type ScatterQuadrants, ScrollAlign, ScrollArea, ScrollBar, type ScrollEvent, ScrollRowIntoView, SectionCard, SectionCards, SectionCardsProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SeriesChartProps, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiLocale, SiyahiProvider, SiyahiProviderProps, Skeleton, Slider, SlopeChart, SlopeChartProps, SlopeItem, Sparkline, SparklineProps, StaleNote, StaleNoteProps, StatusActivity, StatusAlert, StatusAlertProps, StatusBadge, StatusBadgeProps, StatusColorConfig, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBlockProps, StatusHeatmapBody, StatusHeatmapBodyProps, StatusHeatmapFooter, StatusHeatmapFooterProps, StatusHeatmapLabels, StatusHeatmapLegend, StatusHeatmapLegendProps, StatusHeatmapProps, StatusHeatmapStat, StatusHeatmapStatProps, StatusValue, Surface, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnActionsProps, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFacetedFilterProps, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, TableSearchFilterProps, Tabs, TabsContent, TabsList, TabsTrigger, TargetRow, TargetRows, TargetRowsProps, TargetStatus, TeamSwitcher, Textarea, TimeOptions, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, ToneProgressProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapItem, TreemapLegend, TreemapLegendProps, TreemapProps, type ValueOf, ValueScaleProps, WaterfallBar, WaterfallChartCard, WaterfallChartCardProps, WaterfallStep, type ColorConfig$1 as WeekdayColorConfig, type WeekdayExtraColumnSpec, type WeekdayExtraRowSpec, WeekdayHeatmap, WeekdayHeatmapBlock, type WeekdayHeatmapBlockProps, WeekdayHeatmapBody, type WeekdayHeatmapBodyProps, WeekdayHeatmapFooter, type WeekdayHeatmapFooterProps, type WeekdayHeatmapLabels, WeekdayHeatmapLegend, type WeekdayHeatmapLegendProps, type WeekdayHeatmapProps, WeekdayHeatmapStat, type WeekdayHeatmapStatProps, type WeekdayHour, type WeekdayHourlyActivity, type WeekdayIndex, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useAxisScale, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
package/dist/index.js
CHANGED
|
@@ -93,7 +93,7 @@ import { DrawdownChartCard, drawdowns } from "./components/siyahi/drawdown-chart
|
|
|
93
93
|
import { HistogramChartCard, bucketOf, histogram, markLines, percentile } from "./components/siyahi/histogram-chart.js";
|
|
94
94
|
import { InlineCode } from "./components/siyahi/inline-code.js";
|
|
95
95
|
import { LocalTime } from "./components/siyahi/local-time.js";
|
|
96
|
-
import {
|
|
96
|
+
import { PageHeader } from "./components/siyahi/page-header.js";
|
|
97
97
|
import { PageSection, PageSubheading } from "./components/siyahi/page-section.js";
|
|
98
98
|
import { PageToc } from "./components/siyahi/page-toc.js";
|
|
99
99
|
import { PanelGrid } from "./components/siyahi/panel-grid.js";
|
|
@@ -108,4 +108,4 @@ import { TargetRows } from "./components/siyahi/target-rows.js";
|
|
|
108
108
|
import { ToneProgress } from "./components/siyahi/tone-progress.js";
|
|
109
109
|
import { Treemap, TreemapLegend } from "./components/siyahi/treemap.js";
|
|
110
110
|
import { WaterfallChartCard, waterfallBars } from "./components/siyahi/waterfall-chart.js";
|
|
111
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AreaChartCard, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartCard, BarList, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBody, CalendarHeatmapFooter, CalendarHeatmapLegend, CalendarHeatmapStat, Callout, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeGrid, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataList, DataListItem, DataTable, DataTableActions, DataTableBody, DataTableColumnActions, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, DataTableCompactColumnsToggle, DataTableContext, DataTableEmptyActions, DataTableEmptyBody, DataTableEmptyDescription, DataTableEmptyFilteredMessage, DataTableEmptyIcon, DataTableEmptyMessage, DataTableEmptyState, DataTableEmptyTitle, DataTableErrorBoundary, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableHeader, DataTableLoading, DataTableLoadingMore, DataTableProvider, DataTableRoot, DataTableRowContextMenu, DataTableRowContextMenuSlot, DataTableRowCount, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSortHeader, DataTableToolbarSection, Delta, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DrawdownChartCard, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, GroupedBodyRow, HistogramChartCard, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, LOG_BLOCKED, Label, LineChartCard, LocalTime, MetricStrip, NavMain, NavProjects, NavUser,
|
|
111
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AreaChartCard, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartCard, BarList, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBody, CalendarHeatmapFooter, CalendarHeatmapLegend, CalendarHeatmapStat, Callout, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeGrid, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataList, DataListItem, DataTable, DataTableActions, DataTableBody, DataTableColumnActions, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, DataTableCompactColumnsToggle, DataTableContext, DataTableEmptyActions, DataTableEmptyBody, DataTableEmptyDescription, DataTableEmptyFilteredMessage, DataTableEmptyIcon, DataTableEmptyMessage, DataTableEmptyState, DataTableEmptyTitle, DataTableErrorBoundary, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableHeader, DataTableLoading, DataTableLoadingMore, DataTableProvider, DataTableRoot, DataTableRowContextMenu, DataTableRowContextMenuSlot, DataTableRowCount, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSortHeader, DataTableToolbarSection, Delta, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DrawdownChartCard, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, GroupedBodyRow, HistogramChartCard, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, LOG_BLOCKED, Label, LineChartCard, LocalTime, MetricStrip, NavMain, NavProjects, NavUser, PageHeader, PageSection, PageSubheading, PageToc, PanelGrid, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, Quote, RangePosition, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScaleToggle, ScatterChartCard, ScrollArea, ScrollBar, SectionCards, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiProvider, Skeleton, Slider, SlopeChart, Sparkline, StaleNote, StatusAlert, StatusBadge, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBody, StatusHeatmapFooter, StatusHeatmapLegend, StatusHeatmapStat, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, Tabs, TabsContent, TabsList, TabsTrigger, TargetRows, TeamSwitcher, Textarea, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapLegend, WaterfallChartCard, WeekdayHeatmap, WeekdayHeatmapBlock, WeekdayHeatmapBody, WeekdayHeatmapFooter, WeekdayHeatmapLegend, WeekdayHeatmapStat, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useAxisScale, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ChartColor, ChartCurve, ChartSeries, ChartSeriesItem, LineMarksProps, NumericXProps, SeriesChartProps, ValueScaleProps } from "./chart-series.js";
|
|
1
|
+
import { ChartColor, ChartCurve, ChartReferenceLine, ChartSeries, ChartSeriesItem, LineMarksProps, NumericXProps, SeriesChartProps, ValueScaleProps } from "./chart-series.js";
|
|
2
2
|
import { ChartTooltipContent } from "../components/ui/chart.js";
|
|
3
3
|
import { ComponentProps, ReactElement, ReactNode } from "react";
|
|
4
|
-
import { AreaChart, BarChart, LineChart
|
|
4
|
+
import { AreaChart, BarChart, LineChart } from "recharts";
|
|
5
5
|
//#region src/lib/chart-frame.d.ts
|
|
6
6
|
/**
|
|
7
|
-
* A bar's fill:
|
|
8
|
-
* the bars it leaves out to a fainter tint; their edges stay, so they keep 3:1 against the card.
|
|
7
|
+
* A bar's fill: the theme's --bar-tint of its colour, inside a 1px edge of the full colour the bar is drawn with. A
|
|
8
|
+
* selection dims the bars it leaves out to a fainter tint; their edges stay, so they keep 3:1 against the card.
|
|
9
9
|
*/
|
|
10
10
|
export declare function barFill(color: string, dim?: boolean): string;
|
|
11
11
|
interface QuietLegendProps<T> {
|
|
@@ -21,10 +21,35 @@ interface QuietLegendProps<T> {
|
|
|
21
21
|
* the rest. A stack's grey bands sit in the legend's order, bottom to top.
|
|
22
22
|
*/
|
|
23
23
|
export declare function QuietLegend<T>({ series, raisable, raised, onRaise }: QuietLegendProps<T>): import("react").JSX.Element;
|
|
24
|
-
|
|
24
|
+
type StackOffset = "none" | "sign";
|
|
25
|
+
/**
|
|
26
|
+
* The values a value axis must reach: each one drawn, or a stack's running totals, where its segments end. A "sign"
|
|
27
|
+
* stack runs a row's losses down from zero and its gains up, so the row reaches its two sums.
|
|
28
|
+
*/
|
|
29
|
+
export declare function axisValues<T>(data: readonly T[], series: ChartSeries<T>, stackOffset?: StackOffset): number[];
|
|
30
|
+
/**
|
|
31
|
+
* A log value axis over the values and the page's levels above zero: a level at or under zero has no place on it, and
|
|
32
|
+
* must not turn Log off.
|
|
33
|
+
*/
|
|
34
|
+
export declare function logValueAxis(values: readonly number[], referenceLines: readonly ChartReferenceLine[], range?: readonly [number, number]): {
|
|
35
|
+
domain: [number, number];
|
|
36
|
+
ticks: number[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A linear value axis that just covers what is drawn: the values (a stack's totals), the page's levels and ticks, and
|
|
40
|
+
* zero under bars, so no bar hangs from its smallest loss and no level falls off the plot.
|
|
41
|
+
*/
|
|
42
|
+
export declare function linearValueAxis<T>(data: readonly T[], series: ChartSeries<T>, { stackOffset, referenceLines, yTicks, bars }: {
|
|
43
|
+
stackOffset?: StackOffset | undefined;
|
|
44
|
+
referenceLines?: readonly ChartReferenceLine[] | undefined;
|
|
45
|
+
yTicks?: readonly number[] | undefined;
|
|
46
|
+
bars?: boolean | undefined;
|
|
47
|
+
}): {
|
|
48
|
+
domain: [number, number];
|
|
49
|
+
ticks: number[];
|
|
50
|
+
} | undefined;
|
|
51
|
+
interface ChartFrameProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps, ValueScaleProps, LineMarksProps<T, K> {
|
|
25
52
|
chart: typeof AreaChart | typeof BarChart | typeof LineChart;
|
|
26
|
-
/** The value axis' range: a page's fixed one, or a card's rule such as bars reaching zero. */
|
|
27
|
-
yDomain?: YAxisProps["domain"] | undefined;
|
|
28
53
|
/** One Bar, Area or Line per series. */
|
|
29
54
|
children: ReactNode;
|
|
30
55
|
/**
|
|
@@ -33,8 +58,11 @@ interface ChartFrameProps<T extends object, K extends keyof T> extends Omit<Seri
|
|
|
33
58
|
* otherwise. x and y keep their meaning: x is the category, y the value.
|
|
34
59
|
*/
|
|
35
60
|
horizontal?: boolean | undefined;
|
|
36
|
-
/**
|
|
37
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The series stack: "none" adds each onto the running total, as a stacked area does; "sign" stacks negative values
|
|
63
|
+
* below zero and positive ones above.
|
|
64
|
+
*/
|
|
65
|
+
stackOffset?: StackOffset | undefined;
|
|
38
66
|
onClick?: ComponentProps<typeof BarChart>["onClick"] | undefined;
|
|
39
67
|
/** A tooltip row per hovered mark; by default each series' colour, label and formatted value (seriesRow). */
|
|
40
68
|
tooltipRow?: ComponentProps<typeof ChartTooltipContent>["formatter"] | undefined;
|
package/dist/lib/chart-frame.js
CHANGED
|
@@ -5,34 +5,23 @@ import { useAxisScale } from "../components/siyahi/scale-toggle.js";
|
|
|
5
5
|
import { StaleNote } from "../components/siyahi/stale-note.js";
|
|
6
6
|
import { useLocale } from "../components/siyahi/siyahi-provider.js";
|
|
7
7
|
import { EndLabels, QUIET, TimeMarks, endLabelRoom, endLabelsFit, linesEndAtEdge } from "./chart-marks.js";
|
|
8
|
-
import { fitsLog, logAxis } from "./ticks.js";
|
|
8
|
+
import { fitsLog, linearAxis, logAxis } from "./ticks.js";
|
|
9
9
|
import { useElementWidth } from "./use-element-width.js";
|
|
10
|
+
import { useRenderWhenFontsLoad } from "./use-render-when-fonts-load.js";
|
|
10
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import {
|
|
12
|
-
import { CartesianGrid, Line, ReferenceLine, Text, XAxis, YAxis, useChartWidth, useXAxisTicks, useYAxisTicks } from "recharts";
|
|
12
|
+
import { useId, useMemo, useState } from "react";
|
|
13
|
+
import { BarChart, CartesianGrid, Line, ReferenceLine, Text, XAxis, YAxis, useChartWidth, useXAxisTicks, useYAxisTicks } from "recharts";
|
|
13
14
|
//#region src/lib/chart-frame.tsx
|
|
14
15
|
const AXIS_TITLE = "fill-muted-foreground text-xs";
|
|
15
16
|
const TICK = { className: "fill-muted-foreground font-mono" };
|
|
16
17
|
const NO_LINES = [];
|
|
17
18
|
const SERIES_LEGEND = /* @__PURE__ */ jsx(ChartLegendContent, { className: "flex-wrap gap-y-1" });
|
|
18
19
|
/**
|
|
19
|
-
* A bar's fill:
|
|
20
|
-
* the bars it leaves out to a fainter tint; their edges stay, so they keep 3:1 against the card.
|
|
20
|
+
* A bar's fill: the theme's --bar-tint of its colour, inside a 1px edge of the full colour the bar is drawn with. A
|
|
21
|
+
* selection dims the bars it leaves out to a fainter tint; their edges stay, so they keep 3:1 against the card.
|
|
21
22
|
*/
|
|
22
23
|
function barFill(color, dim = false) {
|
|
23
|
-
return `color-mix(in oklab, ${color} ${dim ? 10 :
|
|
24
|
-
}
|
|
25
|
-
/** Renders the component again once the page's fonts load, so text measured on a canvas is measured in Geist. */
|
|
26
|
-
function useRenderWhenFontsLoad() {
|
|
27
|
-
const [loaded, setLoaded] = useState(() => typeof document === "undefined" || document.fonts?.status === "loaded");
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
if (loaded || !document.fonts) return;
|
|
30
|
-
let live = true;
|
|
31
|
-
document.fonts.ready.then(() => live && setLoaded(true));
|
|
32
|
-
return () => {
|
|
33
|
-
live = false;
|
|
34
|
-
};
|
|
35
|
-
}, [loaded]);
|
|
24
|
+
return `color-mix(in oklab, ${color} ${dim ? "10%" : "var(--bar-tint)"}, var(--card))`;
|
|
36
25
|
}
|
|
37
26
|
/**
|
|
38
27
|
* The legend when some series are quiet: every series by name. The grey ones share a colour, so a legend square
|
|
@@ -83,6 +72,43 @@ function haloLine({ x1, y1, x2, y2, stroke, strokeDasharray }) {
|
|
|
83
72
|
strokeWidth: 1
|
|
84
73
|
})] });
|
|
85
74
|
}
|
|
75
|
+
const sum = (values) => values.reduce((total, value) => total + value, 0);
|
|
76
|
+
/**
|
|
77
|
+
* The values a value axis must reach: each one drawn, or a stack's running totals, where its segments end. A "sign"
|
|
78
|
+
* stack runs a row's losses down from zero and its gains up, so the row reaches its two sums.
|
|
79
|
+
*/
|
|
80
|
+
function axisValues(data, series, stackOffset) {
|
|
81
|
+
return data.flatMap((row) => {
|
|
82
|
+
const values = series.map(({ key }) => row[key]).filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
83
|
+
if (stackOffset === "none") {
|
|
84
|
+
let total = 0;
|
|
85
|
+
return [0, ...values.map((value) => total += value)];
|
|
86
|
+
}
|
|
87
|
+
if (stackOffset === "sign") return [sum(values.filter((value) => value < 0)), sum(values.filter((value) => value > 0))];
|
|
88
|
+
return values;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/** The value levels a page marks with reference lines. */
|
|
92
|
+
const levelsOf = (lines) => lines.flatMap(({ y }) => y === void 0 ? [] : [y]);
|
|
93
|
+
/**
|
|
94
|
+
* A log value axis over the values and the page's levels above zero: a level at or under zero has no place on it, and
|
|
95
|
+
* must not turn Log off.
|
|
96
|
+
*/
|
|
97
|
+
function logValueAxis(values, referenceLines, range) {
|
|
98
|
+
return logAxis([...values, ...levelsOf(referenceLines).filter((level) => level > 0)], range);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A linear value axis that just covers what is drawn: the values (a stack's totals), the page's levels and ticks, and
|
|
102
|
+
* zero under bars, so no bar hangs from its smallest loss and no level falls off the plot.
|
|
103
|
+
*/
|
|
104
|
+
function linearValueAxis(data, series, { stackOffset, referenceLines = NO_LINES, yTicks = [], bars = false }) {
|
|
105
|
+
return linearAxis([
|
|
106
|
+
...axisValues(data, series, stackOffset),
|
|
107
|
+
...levelsOf(referenceLines),
|
|
108
|
+
...yTicks,
|
|
109
|
+
...bars ? [0] : []
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
86
112
|
/**
|
|
87
113
|
* The colour a series' Bar takes, which its legend chip shows: the negative colour when every value drawn is below
|
|
88
114
|
* zero, since each bar's own Cell follows its sign but the chip follows the Bar.
|
|
@@ -246,10 +272,10 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
246
272
|
const { numberLocale } = useLocale();
|
|
247
273
|
const clipId = useId();
|
|
248
274
|
const [contentRef, contentWidth] = useElementWidth();
|
|
249
|
-
useRenderWhenFontsLoad();
|
|
250
275
|
const [raisedKey, setRaisedKey] = useState();
|
|
251
276
|
const names = endLabels ? series.map(({ label }) => label) : [];
|
|
252
277
|
const labelRoom = endLabels ? endLabelRoom(names) : 0;
|
|
278
|
+
useRenderWhenFontsLoad(() => endLabels ? endLabelRoom(names) : 0);
|
|
253
279
|
const plotHeight = height - 12 - (xTickDetail ? 40 : 30) - (xLabel ? 18 : 0);
|
|
254
280
|
const ends = endLabels && linesEndAtEdge(data, xKey, series, xDomain) && endLabelsFit(names, contentWidth, plotHeight);
|
|
255
281
|
const quiet = series.some(({ color }) => color === QUIET);
|
|
@@ -260,16 +286,20 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
260
286
|
color
|
|
261
287
|
}]));
|
|
262
288
|
const crossesZero = data.some((row) => series.some(({ key }) => Number(row[key]) < 0));
|
|
263
|
-
const
|
|
264
|
-
const range = typeof low === "number" && typeof high === "number" ? [low, high] : void 0;
|
|
265
|
-
const values = [...data.flatMap((row) => series.map(({ key }) => row[key])), ...range ?? []].filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
289
|
+
const values = [...data.flatMap((row) => series.map(({ key }) => row[key])), ...yDomain ?? []].filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
266
290
|
const valueAxis = useAxisScale({
|
|
267
291
|
initial: yScale,
|
|
268
292
|
toggle: yScaleToggle,
|
|
269
293
|
label: yLabel ? `${yLabel} scale` : "Value axis scale",
|
|
270
294
|
logBlocked: logBlocked ?? (fitsLog(values) ? void 0 : "Log needs every value above zero")
|
|
271
295
|
});
|
|
272
|
-
const log = valueAxis.scale === "log" ?
|
|
296
|
+
const log = valueAxis.scale === "log" ? logValueAxis(values, referenceLines, yDomain) : void 0;
|
|
297
|
+
const linear = log || yDomain !== void 0 ? void 0 : linearValueAxis(data, series, {
|
|
298
|
+
stackOffset,
|
|
299
|
+
referenceLines,
|
|
300
|
+
yTicks,
|
|
301
|
+
bars: Chart === BarChart
|
|
302
|
+
});
|
|
273
303
|
const detailedRows = horizontal && xTickDetail !== void 0;
|
|
274
304
|
const rowCount = (xTicks ?? data).length;
|
|
275
305
|
const plotClass = detailedRows ? "min-h-(--wrapped-chart-height) @min-[24rem]/chart:min-h-0" : void 0;
|
|
@@ -336,10 +366,10 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
336
366
|
}),
|
|
337
367
|
horizontal ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(XAxis, {
|
|
338
368
|
type: "number",
|
|
339
|
-
niceTicks: "snap125",
|
|
369
|
+
niceTicks: linear ? void 0 : "snap125",
|
|
340
370
|
hide: !yTickFormatter,
|
|
341
|
-
domain: yDomain,
|
|
342
|
-
ticks: yTicks,
|
|
371
|
+
domain: linear?.domain ?? yDomain,
|
|
372
|
+
ticks: yTicks ?? linear?.ticks,
|
|
343
373
|
tickLine: false,
|
|
344
374
|
axisLine: false,
|
|
345
375
|
tickMargin: 8,
|
|
@@ -373,12 +403,12 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
373
403
|
interval: xTickDetail || xTicks ? 0 : void 0
|
|
374
404
|
}), /* @__PURE__ */ jsx(YAxis, {
|
|
375
405
|
scale: valueAxis.scale,
|
|
376
|
-
niceTicks: log ? void 0 : "snap125",
|
|
406
|
+
niceTicks: log || linear ? void 0 : "snap125",
|
|
377
407
|
tickLine: false,
|
|
378
408
|
axisLine: false,
|
|
379
409
|
width: "auto",
|
|
380
|
-
domain: log?.domain ?? yDomain,
|
|
381
|
-
ticks: log?.ticks ?? yTicks,
|
|
410
|
+
domain: log?.domain ?? linear?.domain ?? yDomain,
|
|
411
|
+
ticks: log?.ticks ?? yTicks ?? linear?.ticks,
|
|
382
412
|
label: yLabel ? {
|
|
383
413
|
value: yLabel,
|
|
384
414
|
angle: -90,
|
|
@@ -477,4 +507,4 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
477
507
|
});
|
|
478
508
|
}
|
|
479
509
|
//#endregion
|
|
480
|
-
export { ChartFrame, QuietLegend, barFill, endDot, seriesFill, seriesRow };
|
|
510
|
+
export { ChartFrame, QuietLegend, axisValues, barFill, endDot, linearValueAxis, logValueAxis, seriesFill, seriesRow };
|
|
@@ -64,8 +64,9 @@ export interface SeriesChartProps<T extends object, K extends keyof T> {
|
|
|
64
64
|
*/
|
|
65
65
|
yTickFormatter?: ((value: number, scale: number) => string) | undefined;
|
|
66
66
|
/**
|
|
67
|
-
* A fixed range for the value axis, such as [0, 100] for a percentage. By default
|
|
68
|
-
*
|
|
67
|
+
* A fixed range for the value axis, such as [0, 100] for a percentage. By default the axis ends on the round
|
|
68
|
+
* ticks that just cover the data (a 46,800 peak ends at 50,000), a stack's totals for a stack, and a bar chart's
|
|
69
|
+
* always reaches zero.
|
|
69
70
|
*/
|
|
70
71
|
yDomain?: [number, number] | undefined;
|
|
71
72
|
/** Where the value axis puts its ticks, such as [0, 25, 50, 75, 100]. */
|
package/dist/lib/ticks.d.ts
CHANGED
|
@@ -10,6 +10,15 @@ export declare function logTicks(min: number, max: number): number[];
|
|
|
10
10
|
* noise, such as 0.3 and 0.30000000000000004, count as one value and get that value as their only tick.
|
|
11
11
|
*/
|
|
12
12
|
export declare function linearTicks(min: number, max: number, count?: number): number[];
|
|
13
|
+
/**
|
|
14
|
+
* A value axis' ends and ticks: the round ticks that just cover the values, and their outer two as the ends. About
|
|
15
|
+
* six, not five, so a 46,800 peak ends at 50,000 by 10,000s rather than at 60,000 by 20,000s. None when the values
|
|
16
|
+
* span no range (no values, or one), which leaves the axis to the chart.
|
|
17
|
+
*/
|
|
18
|
+
export declare function linearAxis(values: readonly number[]): {
|
|
19
|
+
domain: [number, number];
|
|
20
|
+
ticks: number[];
|
|
21
|
+
} | undefined;
|
|
13
22
|
/** How an axis spaces its values: evenly, or by powers of ten for values that run from tiny to large. */
|
|
14
23
|
export type AxisScale = "linear" | "log";
|
|
15
24
|
/** An axis' ticks for its scale: round steps either way, so a linear axis starting at 0.4% reads 0%, 5%, 10%. */
|
package/dist/lib/ticks.js
CHANGED
|
@@ -39,6 +39,29 @@ function linearTicks(min, max, count = 5) {
|
|
|
39
39
|
const last = Math.ceil(max / step - 1e-9);
|
|
40
40
|
return Array.from({ length: last - first + 1 }, (_, i) => clean((first + i) * step));
|
|
41
41
|
}
|
|
42
|
+
/** The smallest and largest value, by a loop: Math.min(...values) overflows the call stack past about 100,000. */
|
|
43
|
+
function extent(values) {
|
|
44
|
+
let low = Number.POSITIVE_INFINITY;
|
|
45
|
+
let high = Number.NEGATIVE_INFINITY;
|
|
46
|
+
for (const value of values) {
|
|
47
|
+
low = Math.min(low, value);
|
|
48
|
+
high = Math.max(high, value);
|
|
49
|
+
}
|
|
50
|
+
return [low, high];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A value axis' ends and ticks: the round ticks that just cover the values, and their outer two as the ends. About
|
|
54
|
+
* six, not five, so a 46,800 peak ends at 50,000 by 10,000s rather than at 60,000 by 20,000s. None when the values
|
|
55
|
+
* span no range (no values, or one), which leaves the axis to the chart.
|
|
56
|
+
*/
|
|
57
|
+
function linearAxis(values) {
|
|
58
|
+
const ticks = linearTicks(...extent(values), 6);
|
|
59
|
+
const [low, high] = [ticks[0], ticks.at(-1)];
|
|
60
|
+
return low !== void 0 && high !== void 0 && low < high ? {
|
|
61
|
+
domain: [low, high],
|
|
62
|
+
ticks
|
|
63
|
+
} : void 0;
|
|
64
|
+
}
|
|
42
65
|
/** An axis' ticks for its scale: round steps either way, so a linear axis starting at 0.4% reads 0%, 5%, 10%. */
|
|
43
66
|
const ticksFor = (scale, min, max) => scale === "log" ? logTicks(min, max) : linearTicks(min, max);
|
|
44
67
|
/** A log axis has no place for zero or below, so it can draw a set of values only when every one is above zero. */
|
|
@@ -55,8 +78,7 @@ function logAxis(values, range) {
|
|
|
55
78
|
ticks: logTicks(low, high).filter((tick) => tick >= low && tick <= high)
|
|
56
79
|
};
|
|
57
80
|
}
|
|
58
|
-
const low =
|
|
59
|
-
const high = Math.max(...values);
|
|
81
|
+
const [low, high] = extent(values);
|
|
60
82
|
const ticks = logTicks(low, high);
|
|
61
83
|
return {
|
|
62
84
|
domain: [ticks[0] ?? low, ticks.at(-1) ?? high],
|
|
@@ -64,4 +86,4 @@ function logAxis(values, range) {
|
|
|
64
86
|
};
|
|
65
87
|
}
|
|
66
88
|
//#endregion
|
|
67
|
-
export { fitsLog, linearTicks, logAxis, logTicks, ticksFor };
|
|
89
|
+
export { fitsLog, linearAxis, linearTicks, logAxis, logTicks, ticksFor };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/lib/use-render-when-fonts-load.d.ts
|
|
2
|
+
/** How many font loads the page has finished: a width a canvas measured before the last one may be the fallback's. */
|
|
3
|
+
export declare function fontLoads(): number;
|
|
4
|
+
/**
|
|
5
|
+
* Renders the component again when a font load changes what `measure` returns: the width of the component's own
|
|
6
|
+
* text, measured on a canvas. Any face may change it, whenever it loads: Geist after the fallback, a subset for other
|
|
7
|
+
* characters, another family. A load that changes nothing the component measures leaves it alone, as Recharts redraws
|
|
8
|
+
* a chart's marks on every render and their fade-in would play again.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useRenderWhenFontsLoad(measure: () => number | string): void;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useLayoutEffect, useReducer, useRef } from "react";
|
|
2
|
+
//#region src/lib/use-render-when-fonts-load.ts
|
|
3
|
+
let loads = 0;
|
|
4
|
+
const counted = /* @__PURE__ */ new WeakSet();
|
|
5
|
+
/** How many font loads the page has finished: a width a canvas measured before the last one may be the fallback's. */
|
|
6
|
+
function fontLoads() {
|
|
7
|
+
if (typeof document !== "undefined" && document.fonts && !counted.has(document.fonts)) {
|
|
8
|
+
counted.add(document.fonts);
|
|
9
|
+
document.fonts.addEventListener("loadingdone", () => loads++);
|
|
10
|
+
}
|
|
11
|
+
return loads;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders the component again when a font load changes what `measure` returns: the width of the component's own
|
|
15
|
+
* text, measured on a canvas. Any face may change it, whenever it loads: Geist after the fallback, a subset for other
|
|
16
|
+
* characters, another family. A load that changes nothing the component measures leaves it alone, as Recharts redraws
|
|
17
|
+
* a chart's marks on every render and their fade-in would play again.
|
|
18
|
+
*/
|
|
19
|
+
function useRenderWhenFontsLoad(measure) {
|
|
20
|
+
const drawn = measure();
|
|
21
|
+
const seen = fontLoads();
|
|
22
|
+
const committed = useRef({
|
|
23
|
+
measure,
|
|
24
|
+
drawn
|
|
25
|
+
});
|
|
26
|
+
const [, render] = useReducer((count) => count + 1, 0);
|
|
27
|
+
useLayoutEffect(() => {
|
|
28
|
+
committed.current = {
|
|
29
|
+
measure,
|
|
30
|
+
drawn
|
|
31
|
+
};
|
|
32
|
+
if (fontLoads() !== seen && measure() !== drawn) render();
|
|
33
|
+
}, [
|
|
34
|
+
measure,
|
|
35
|
+
drawn,
|
|
36
|
+
seen
|
|
37
|
+
]);
|
|
38
|
+
useLayoutEffect(() => {
|
|
39
|
+
const fonts = document.fonts;
|
|
40
|
+
if (!fonts) return;
|
|
41
|
+
const recheck = () => {
|
|
42
|
+
if (committed.current.measure() !== committed.current.drawn) render();
|
|
43
|
+
};
|
|
44
|
+
fonts.addEventListener("loadingdone", recheck);
|
|
45
|
+
return () => fonts.removeEventListener("loadingdone", recheck);
|
|
46
|
+
}, []);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { fontLoads, useRenderWhenFontsLoad };
|
package/package.json
CHANGED
package/report.css
CHANGED
package/styles/siyahi.css
CHANGED
|
@@ -140,6 +140,12 @@
|
|
|
140
140
|
--wash-edge: 45%;
|
|
141
141
|
/* An invalid field's wash: this share of --destructive over the card. */
|
|
142
142
|
--field-wash: 8%;
|
|
143
|
+
/*
|
|
144
|
+
* Every bar takes this share of its colour over the card, inside a 1px edge of the full colour (lib/chart-frame
|
|
145
|
+
* barFill). At 25% a pale slot's bar barely left the card and a thin stacked segment was two edge lines; the
|
|
146
|
+
* contrast check holds each bar colour's tint against the card and each slot's against the next slot's.
|
|
147
|
+
*/
|
|
148
|
+
--bar-tint: 50%;
|
|
143
149
|
--link: oklch(0.51 0.2 275);
|
|
144
150
|
/*
|
|
145
151
|
* Indigo, amber, plum, sky, teal: no green or red, so no series reads as a
|
|
@@ -220,6 +226,7 @@
|
|
|
220
226
|
--wash: 12%;
|
|
221
227
|
--wash-edge: 55%;
|
|
222
228
|
--field-wash: 12%;
|
|
229
|
+
--bar-tint: 50%;
|
|
223
230
|
--link: oklch(0.75 0.128 275);
|
|
224
231
|
--chart-1: oklch(0.58 0.2 275);
|
|
225
232
|
--chart-2: oklch(0.88 0.08 75);
|
|
@@ -265,13 +272,15 @@
|
|
|
265
272
|
* foreground, black on white and white on black, so the reader sees at once
|
|
266
273
|
* what is on; stock shadcn marks it with a faint grey. A default (pill) tab
|
|
267
274
|
* selects the same way: stock fills it with the canvas colour, 1.05:1 against
|
|
268
|
-
* its grey list. Unlayered, to outrank the stock
|
|
275
|
+
* its grey list, lifted on a drop shadow, which the fill makes needless. Unlayered, to outrank the stock
|
|
276
|
+
* aria-pressed:bg-muted.
|
|
269
277
|
*/
|
|
270
278
|
:is([data-slot="toggle"], [data-slot="toggle-group-item"]):is([aria-pressed="true"], [data-pressed]),
|
|
271
279
|
[data-slot="tabs-list"][data-variant="default"] [data-slot="tabs-trigger"][data-active] {
|
|
272
280
|
background-color: var(--foreground);
|
|
273
281
|
color: var(--background);
|
|
274
282
|
border-color: var(--foreground);
|
|
283
|
+
--tw-shadow: 0 0 #0000;
|
|
275
284
|
}
|
|
276
285
|
|
|
277
286
|
/*
|
|
@@ -476,8 +485,47 @@ svg :is(rect, circle, path)[tabindex]:focus-visible,
|
|
|
476
485
|
@apply font-mono text-2xs tracking-wider text-muted-foreground uppercase;
|
|
477
486
|
}
|
|
478
487
|
|
|
479
|
-
/*
|
|
480
|
-
|
|
488
|
+
/* A group's label in a menu, a select's list or the command palette is a label over its items, set as one. */
|
|
489
|
+
:is(
|
|
490
|
+
[data-slot="dropdown-menu-label"],
|
|
491
|
+
[data-slot="context-menu-label"],
|
|
492
|
+
[data-slot="select-label"],
|
|
493
|
+
[data-slot="command-group"] [cmdk-group-heading]
|
|
494
|
+
) {
|
|
495
|
+
@apply font-mono text-2xs tracking-wider text-muted-foreground uppercase;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/*
|
|
499
|
+
* A menu, a select's list, a popover, a dialog, a sheet and a chart's tooltip read as a sheet of the page, not a
|
|
500
|
+
* bubble floating over it: no drop shadow, and the card's hairline for an edge (stock rings them fainter).
|
|
501
|
+
*/
|
|
502
|
+
:is(
|
|
503
|
+
[data-slot="dropdown-menu-content"],
|
|
504
|
+
[data-slot="dropdown-menu-sub-content"],
|
|
505
|
+
[data-slot="context-menu-content"],
|
|
506
|
+
[data-slot="context-menu-sub-content"],
|
|
507
|
+
[data-slot="select-content"],
|
|
508
|
+
[data-slot="popover-content"],
|
|
509
|
+
[data-slot="dialog-content"],
|
|
510
|
+
[data-slot="sheet-content"],
|
|
511
|
+
[data-slot="chart"] .recharts-tooltip-wrapper > div
|
|
512
|
+
) {
|
|
513
|
+
--tw-shadow: 0 0 #0000;
|
|
514
|
+
--tw-ring-color: var(--border);
|
|
515
|
+
border-color: var(--border);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/*
|
|
519
|
+
* Square as every box is: progress, a slider's track and thumb, a scrollbar's thumb, and the colour chips core's
|
|
520
|
+
* chart tooltip and legend draw at a fixed 2px, which no radius token reaches.
|
|
521
|
+
*/
|
|
522
|
+
:is(
|
|
523
|
+
[data-slot="progress-track"],
|
|
524
|
+
[data-slot="slider-track"],
|
|
525
|
+
[data-slot="slider-thumb"],
|
|
526
|
+
[data-slot="scroll-area-thumb"],
|
|
527
|
+
[data-slot="chart"] :is(.recharts-tooltip-wrapper, .recharts-legend-wrapper) [class~="rounded-[2px]"]
|
|
528
|
+
) {
|
|
481
529
|
border-radius: 0;
|
|
482
530
|
}
|
|
483
531
|
|
|
@@ -750,7 +798,6 @@ div[data-slot="sidebar"]:not([data-side], [data-mobile]) {
|
|
|
750
798
|
inset-block: 2px;
|
|
751
799
|
left: -11px;
|
|
752
800
|
width: 2px;
|
|
753
|
-
border-radius: 1px;
|
|
754
801
|
background: var(--sidebar-accent-foreground);
|
|
755
802
|
}
|
|
756
803
|
|