@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.
Files changed (38) hide show
  1. package/DESIGN.md +20 -7
  2. package/agents/examples/chart-panels-three.tsx +51 -0
  3. package/agents/examples/context-menu.tsx +14 -4
  4. package/agents/examples/overview-dashboard.tsx +2 -2
  5. package/agents/examples/{page-hero.tsx → page-header.tsx} +4 -4
  6. package/agents/examples/select.tsx +2 -1
  7. package/agents/manifest.json +16 -3
  8. package/dist/components/registry/charts/area-chart-card.js +1 -0
  9. package/dist/components/registry/charts/bar-chart-card.js +0 -2
  10. package/dist/components/registry/heatmap/calendar-heatmap.js +1 -1
  11. package/dist/components/registry/heatmap/status-heatmap.js +1 -1
  12. package/dist/components/registry/heatmap/weekday-heatmap.js +1 -1
  13. package/dist/components/registry/niko-table/core/data-table-structure.js +6 -0
  14. package/dist/components/registry/niko-table/core/data-table.js +1 -1
  15. package/dist/components/registry/niko-table/filters/table-column-sort.js +2 -2
  16. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +1 -1
  17. package/dist/components/registry/niko-table/lib/column-resize-handle.js +1 -1
  18. package/dist/components/registry/sidebar-07/nav-user.js +16 -19
  19. package/dist/components/siyahi/{page-hero.d.ts → page-header.d.ts} +3 -3
  20. package/dist/components/siyahi/{page-hero.js → page-header.js} +4 -4
  21. package/dist/components/siyahi/panel-grid.d.ts +5 -2
  22. package/dist/components/siyahi/panel-grid.js +1 -1
  23. package/dist/components/siyahi/range-position.js +1 -1
  24. package/dist/components/siyahi/scatter-chart.js +14 -1
  25. package/dist/components/siyahi/target-rows.js +2 -2
  26. package/dist/components/siyahi/treemap.js +0 -3
  27. package/dist/index.d.ts +2 -2
  28. package/dist/index.js +2 -2
  29. package/dist/lib/chart-frame.d.ts +37 -9
  30. package/dist/lib/chart-frame.js +60 -30
  31. package/dist/lib/chart-series.d.ts +3 -2
  32. package/dist/lib/ticks.d.ts +9 -0
  33. package/dist/lib/ticks.js +25 -3
  34. package/dist/lib/use-render-when-fonts-load.d.ts +11 -0
  35. package/dist/lib/use-render-when-fonts-load.js +49 -0
  36. package/package.json +1 -1
  37. package/report.css +1 -0
  38. 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, and bars and tracks (data bars, progress) alike (`--radius`
87
- is 0). Only a dot, an avatar, a slider, a spinner or a scrollbar is round;
88
- the stock chart tooltip's colour chips keep shadcn's 2px. Never add a
89
- `rounded-*` class to a box.
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, `PageHero`: a small mark and eyebrow in the
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, and a form field's label (muted, above the field). The components and
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 { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@siyahi/ui";
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 rounded-lg border border-dashed text-muted-foreground">
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
- <ContextMenuItem>Copy order number</ContextMenuItem>
13
- <ContextMenuItem>Open order</ContextMenuItem>
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
- PageHero,
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
- <PageHero
129
+ <PageHeader
130
130
  mark={<InkDrop />}
131
131
  eyebrow="The Book"
132
132
  title="Holdings"
@@ -1,7 +1,7 @@
1
- import { Button, PageHero } from "@siyahi/ui";
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 hero tints it.
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 PageHeroExample() {
17
+ export default function PageHeaderExample() {
18
18
  return (
19
- <PageHero
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}
@@ -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
- "PageHero",
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-hero.tsx",
1069
+ "file": "agents/examples/page-header.tsx",
1058
1070
  "components": [
1059
1071
  "Button",
1060
- "PageHero"
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 = 2, 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 }) => {
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 = 2, blockAspectRatio: blockAspectRatioProp, colors, locale, labels: labelsProp, fontSize = 14, emptyState, statusValues = [
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 = 2, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, colors, locale, labels: labelsProp, fontSize = 14, emptyState, totalCount: totalCountProp, extraRow, extraColumn, style = EMPTY_STYLE, className, children, ...props }) => {
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]:rounded-full [&::-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),
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 rounded-full bg-primary text-[10px] font-medium text-primary-foreground" }),
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 rounded-full bg-primary text-[9px] text-primary-foreground",
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 border-dashed",
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 rounded 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") })
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, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../ui/dropdown-menu.js";
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__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, {
38
- className: "p-0 font-normal",
39
- children: /* @__PURE__ */ jsxs("div", {
40
- className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm",
41
- children: [/* @__PURE__ */ jsxs(Avatar, { children: [/* @__PURE__ */ jsx(AvatarImage, {
42
- src: user.avatar,
43
- alt: user.name
44
- }), /* @__PURE__ */ jsx(AvatarFallback, { children: "CN" })] }), /* @__PURE__ */ jsxs("div", {
45
- className: "grid flex-1 text-left text-sm leading-tight",
46
- children: [/* @__PURE__ */ jsx("span", {
47
- className: "truncate font-medium",
48
- children: user.name
49
- }), /* @__PURE__ */ jsx("span", {
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-hero.d.ts
3
- export interface PageHeroProps {
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 PageHero({ eyebrow, title, lead, detail, actions, mark }: PageHeroProps): import("react").JSX.Element;
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-hero.tsx
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 PageHero({ eyebrow, title, lead, detail, actions, mark }) {
8
+ function PageHeader({ eyebrow, title, lead, detail, actions, mark }) {
9
9
  return /* @__PURE__ */ jsxs("header", {
10
- "data-slot": "page-hero",
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 { PageHero };
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-2 @5xl/panels:grid-cols-3";
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
- /** Blocks across on a wide page; two on a medium one, and one on a phone. */
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;
@@ -6,7 +6,7 @@ import { Children } from "react";
6
6
  const COLUMNS = {
7
7
  1: "",
8
8
  2: "@2xl/panels:grid-cols-2",
9
- 3: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-3",
9
+ 3: "@2xl/panels:grid-cols-3",
10
10
  4: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-4"
11
11
  };
12
12
  /**
@@ -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 rounded-full border-2 border-foreground bg-card", variant === "full" ? "size-3.5" : "size-2.5"),
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
- /** A name's width in the labels' type, measured on a canvas once per font and name. */
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: "truncate font-medium",
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: "truncate",
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 { PageHero, PageHeroProps } from "./components/siyahi/page-hero.js";
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, PageHero, PageHeroProps, 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 };
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 { PageHero } from "./components/siyahi/page-hero.js";
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, PageHero, 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 };
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, YAxisProps } from "recharts";
4
+ import { AreaChart, BarChart, LineChart } from "recharts";
5
5
  //#region src/lib/chart-frame.d.ts
6
6
  /**
7
- * A bar's fill: a tint of its colour, inside a 1px edge of the full colour the bar is drawn with. A selection dims
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
- interface ChartFrameProps<T extends object, K extends keyof T> extends Omit<SeriesChartProps<T, K>, "yDomain">, NumericXProps, ValueScaleProps, LineMarksProps<T, K> {
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
- /** "sign" stacks negative values below zero and positive ones above, rather than on one running total. */
37
- stackOffset?: "sign" | undefined;
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;
@@ -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 { useEffect, useId, useMemo, useState } from "react";
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: a tint of its colour, inside a 1px edge of the full colour the bar is drawn with. A selection dims
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 : 25}%, var(--card))`;
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 [low, high] = Array.isArray(yDomain) ? yDomain : [];
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" ? logAxis(values, range) : void 0;
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 it fits the data; a bar
68
- * chart's always reaches zero.
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]. */
@@ -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 = Math.min(...values);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siyahi/ui",
3
- "version": "0.1.9-next.33",
3
+ "version": "0.1.9-next.34",
4
4
  "description": "Stock shadcn/ui on Base UI and Tailwind v4, a finance theme, a few compositions and formatters.",
5
5
  "keywords": [
6
6
  "base-ui",
package/report.css CHANGED
@@ -38,6 +38,7 @@
38
38
  --wash: 7%;
39
39
  --wash-edge: 45%;
40
40
  --field-wash: 8%;
41
+ --bar-tint: 50%;
41
42
  --link: oklch(0.51 0.2 275);
42
43
  --chart-1: oklch(0.4 0.17 275);
43
44
  --chart-2: oklch(0.66 0.13 70);
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 aria-pressed:bg-muted.
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
- /* Progress is a bar, square as every bar is; stock draws it as a pill. */
480
- [data-slot="progress-track"] {
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