@siyahi/ui 0.1.9-next.33 → 0.1.9-next.35

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 (106) hide show
  1. package/DESIGN.md +21 -7
  2. package/README.md +5 -5
  3. package/agents/examples/app-sidebar.tsx +0 -2
  4. package/agents/examples/chart-panels-three.tsx +51 -0
  5. package/agents/examples/context-menu.tsx +14 -4
  6. package/agents/examples/overview-dashboard.tsx +2 -2
  7. package/agents/examples/{page-hero.tsx → page-header.tsx} +4 -4
  8. package/agents/examples/select.tsx +2 -1
  9. package/agents/manifest.json +16 -5
  10. package/dist/components/registry/charts/area-chart-card.js +1 -0
  11. package/dist/components/registry/charts/bar-chart-card.js +0 -2
  12. package/dist/components/registry/heatmap/calendar-heatmap.js +1 -1
  13. package/dist/components/registry/heatmap/status-heatmap.js +1 -1
  14. package/dist/components/registry/heatmap/weekday-heatmap.js +1 -1
  15. package/dist/components/registry/niko-table/core/data-table-error-boundary.js +1 -1
  16. package/dist/components/registry/niko-table/core/data-table-structure.js +6 -0
  17. package/dist/components/registry/niko-table/core/data-table.js +1 -1
  18. package/dist/components/registry/niko-table/filters/table-column-sort.js +2 -2
  19. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +3 -3
  20. package/dist/components/registry/niko-table/lib/column-resize-handle.js +1 -1
  21. package/dist/components/registry/sidebar-07/nav-user.js +16 -19
  22. package/dist/components/siyahi/{page-hero.d.ts → page-header.d.ts} +3 -3
  23. package/dist/components/siyahi/{page-hero.js → page-header.js} +4 -4
  24. package/dist/components/siyahi/panel-grid.d.ts +5 -2
  25. package/dist/components/siyahi/panel-grid.js +1 -1
  26. package/dist/components/siyahi/range-position.js +1 -1
  27. package/dist/components/siyahi/scatter-chart.js +15 -2
  28. package/dist/components/siyahi/status-badge.js +1 -0
  29. package/dist/components/siyahi/target-rows.js +2 -2
  30. package/dist/components/siyahi/treemap.js +0 -3
  31. package/dist/components/ui/alert-dialog.d.ts +20 -0
  32. package/dist/components/ui/alert-dialog.js +94 -0
  33. package/dist/components/ui/aspect-ratio.d.ts +6 -0
  34. package/dist/components/ui/aspect-ratio.js +13 -0
  35. package/dist/components/ui/attachment.d.ts +25 -0
  36. package/dist/components/ui/attachment.js +104 -0
  37. package/dist/components/ui/bubble.d.ts +18 -0
  38. package/dist/components/ui/bubble.js +73 -0
  39. package/dist/components/ui/button-group.d.ts +12 -0
  40. package/dist/components/ui/button-group.js +41 -0
  41. package/dist/components/ui/button.d.ts +1 -1
  42. package/dist/components/ui/button.js +1 -1
  43. package/dist/components/ui/carousel.d.ts +30 -0
  44. package/dist/components/ui/carousel.js +131 -0
  45. package/dist/components/ui/checkbox.d.ts +5 -0
  46. package/dist/components/ui/checkbox.js +20 -0
  47. package/dist/components/ui/combobox.d.ts +26 -0
  48. package/dist/components/ui/combobox.js +162 -0
  49. package/dist/components/ui/command.js +1 -1
  50. package/dist/components/ui/direction.d.ts +2 -0
  51. package/dist/components/ui/direction.js +1 -0
  52. package/dist/components/ui/drawer.d.ts +18 -0
  53. package/dist/components/ui/drawer.js +123 -0
  54. package/dist/components/ui/empty.d.ts +13 -0
  55. package/dist/components/ui/empty.js +59 -0
  56. package/dist/components/ui/field.js +1 -1
  57. package/dist/components/ui/hover-card.d.ts +7 -0
  58. package/dist/components/ui/hover-card.js +36 -0
  59. package/dist/components/ui/input-otp.d.ts +13 -0
  60. package/dist/components/ui/input-otp.js +46 -0
  61. package/dist/components/ui/item.d.ts +24 -0
  62. package/dist/components/ui/item.js +121 -0
  63. package/dist/components/ui/kbd.d.ts +5 -0
  64. package/dist/components/ui/kbd.js +19 -0
  65. package/dist/components/ui/marker.d.ts +12 -0
  66. package/dist/components/ui/marker.js +43 -0
  67. package/dist/components/ui/menubar.d.ts +31 -0
  68. package/dist/components/ui/menubar.js +136 -0
  69. package/dist/components/ui/message-scroller.d.ts +12 -0
  70. package/dist/components/ui/message-scroller.js +60 -0
  71. package/dist/components/ui/message.d.ts +12 -0
  72. package/dist/components/ui/message.js +49 -0
  73. package/dist/components/ui/native-select.d.ts +10 -0
  74. package/dist/components/ui/native-select.js +38 -0
  75. package/dist/components/ui/navigation-menu.d.ts +13 -0
  76. package/dist/components/ui/navigation-menu.js +82 -0
  77. package/dist/components/ui/pagination.d.ts +19 -0
  78. package/dist/components/ui/pagination.js +80 -0
  79. package/dist/components/ui/questionnaire.d.ts +21 -0
  80. package/dist/components/ui/questionnaire.js +170 -0
  81. package/dist/components/ui/radio-group.d.ts +7 -0
  82. package/dist/components/ui/radio-group.js +26 -0
  83. package/dist/components/ui/resizable.d.ts +9 -0
  84. package/dist/components/ui/resizable.js +28 -0
  85. package/dist/components/ui/sidebar.js +1 -1
  86. package/dist/components/ui/spinner.d.ts +4 -0
  87. package/dist/components/ui/spinner.js +15 -0
  88. package/dist/components/ui/switch.d.ts +7 -0
  89. package/dist/components/ui/switch.js +19 -0
  90. package/dist/components/ui/toast.d.ts +18 -0
  91. package/dist/components/ui/toast.js +123 -0
  92. package/dist/components/ui/trace.d.ts +20 -0
  93. package/dist/components/ui/trace.js +75 -0
  94. package/dist/index.d.ts +32 -2
  95. package/dist/index.js +35 -5
  96. package/dist/lib/chart-frame.d.ts +37 -9
  97. package/dist/lib/chart-frame.js +60 -30
  98. package/dist/lib/chart-series.d.ts +3 -2
  99. package/dist/lib/ticks.d.ts +9 -0
  100. package/dist/lib/ticks.js +25 -3
  101. package/dist/lib/use-render-when-fonts-load.d.ts +11 -0
  102. package/dist/lib/use-render-when-fonts-load.js +49 -0
  103. package/package.json +5 -3
  104. package/styles/siyahi.css +224 -26
  105. package/agents/report-rules.json +0 -7
  106. package/report.css +0 -145
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,16 @@ 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 radio, a status dot, a line's end dot, a
92
+ spinner, and a signed calendar heatmap's loss day, whose shape carries its
93
+ sign. The theme squares every other rounding, on any component.
94
+ Never add a `rounded-*` class to a box.
95
+ - **Floating surfaces lie flat.** Nothing casts a drop shadow: a menu, a
96
+ list, a popover, a dialog, a sheet, a hover card and a chart's tooltip take
97
+ the card's hairline for their edge, so they read as a sheet of the page.
90
98
  - **Joined toggles.** The items of a `ToggleGroup` sit flush and share their
91
99
  borders, one control; the pressed item fills with the foreground.
92
100
  - **A code block's copy button sits in a header row** (`CodeBlockHeader`),
@@ -97,7 +105,7 @@ mono face and the link colour, so the text can point to one.
97
105
 
98
106
  ## Page header
99
107
 
100
- An app page opens on its masthead, `PageHero`: a small mark and eyebrow in the
108
+ An app page opens on its masthead, `PageHeader`: a small mark and eyebrow in the
101
109
  mono face and link colour, the title, one muted line saying what the page is,
102
110
  the actions at the right, and a hairline under it. One per page; no hero card.
103
111
 
@@ -186,7 +194,8 @@ from the catalogue.
186
194
 
187
195
  - **Labels are small monospaced capitals**: a stat tile's label and footer
188
196
  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
197
+ label, a group's label in a menu, a select's list or the command palette,
198
+ and a form field's label (muted, above the field). The components and
190
199
  the theme set them; never set a label in this style by hand elsewhere, and
191
200
  never set a figure or a title in it.
192
201
  - **A total row reads as a ledger's**: in `TableFooter`, one rule above it and
@@ -211,6 +220,11 @@ from the catalogue.
211
220
  a stack's grey bands read in the legend's order, bottom to top.
212
221
  - **No fill under overlapping areas**: from three series on, fills bury each
213
222
  other. A stack fills each band with a flat tint, never a gradient.
223
+ - **The value axis just covers the data.** Unless the page fixes it, it ends
224
+ on the round tick just past what is drawn (a 46,800 peak at 50,000, by
225
+ 10,000s), a stack's totals for a stack. Bars and stacks reach zero, since
226
+ their length is the value; lines and overlapping areas need not, so a
227
+ revenue line from ₹38L to ₹45L fills the plot rather than its top fifth.
214
228
  - **Forecast and today.** `forecastFrom` dashes every line from that point,
215
229
  hatches the stretch faintly behind lines on card-coloured halos, labels it
216
230
  FORECAST and hollows the end dots (a stack keeps solid edges and no hatching:
package/README.md CHANGED
@@ -58,8 +58,8 @@ createRoot(root).render(
58
58
 
59
59
  `preloadFonts()` loads Geist and Geist Mono with the scripts. Add `lucide-react`
60
60
  only when your own code imports icons. Next.js compiles the stylesheet through
61
- `@tailwindcss/postcss` instead of the Vite plugin. Static HTML reports inline the
62
- package's `report.css` and follow `agents/report-rules.json`.
61
+ `@tailwindcss/postcss` instead of the Vite plugin. To host one page as a single
62
+ HTML file, build it with `siyahi-page` from `@siyahi/tools`.
63
63
 
64
64
  If npm is unreachable, both package tarballs are attached to
65
65
  [GitHub releases](https://github.com/jatinbansal1998/siyahi/releases).
@@ -136,8 +136,8 @@ Set `color-scheme` on `<html>` as well so native controls match.
136
136
  ## Tools
137
137
 
138
138
  `@siyahi/tools` provides theme lint rules, font preload, layout screenshots
139
- (`siyahi-shots`), loading-shift checks (`siyahi-cls`) and contrast checks
140
- (`siyahi-contrast`). See the
139
+ (`siyahi-shots`), loading-shift checks (`siyahi-cls`), contrast checks
140
+ (`siyahi-contrast`) and a one-file page build (`siyahi-page`). See the
141
141
  [tools guide](https://github.com/jatinbansal1998/siyahi/blob/main/packages/tools/README.md)
142
142
  for configuration and commands.
143
143
 
@@ -146,7 +146,7 @@ for configuration and commands.
146
146
  ```sh
147
147
  pnpm install
148
148
  pnpm --filter @siyahi/tools exec playwright install chromium
149
- pnpm check
149
+ pnpm check:static # the full suite runs on each pull request's CI
150
150
  pnpm dev
151
151
  ```
152
152
 
@@ -3,7 +3,6 @@ import {
3
3
  BlocksIcon,
4
4
  ChartAreaIcon,
5
5
  CodeIcon,
6
- FileTextIcon,
7
6
  HouseIcon,
8
7
  LayersIcon,
9
8
  PaletteIcon,
@@ -18,7 +17,6 @@ const views = [
18
17
  { title: "Inputs and overlays", url: "#/inputs", icon: <SlidersHorizontalIcon /> },
19
18
  { title: "Data", url: "#/data", icon: <ChartAreaIcon /> },
20
19
  { title: "Blocks", url: "#/blocks", icon: <BlocksIcon />, isActive: true },
21
- { title: "Reports", url: "#/reports", icon: <FileTextIcon /> },
22
20
  // linkProps go onto the anchor: here a new tab, in an app often onMouseEnter to prefetch the view's data.
23
21
  {
24
22
  title: "Source",
@@ -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}
@@ -4,8 +4,6 @@
4
4
  "props": "dist/index.d.ts",
5
5
  "setup": "README.md#install",
6
6
  "layout": "README.md#surfaces",
7
- "report": "report.css",
8
- "reportRules": "agents/report-rules.json",
9
7
  "recipes": {
10
8
  "dashboard": "agents/examples/surfaces.tsx",
11
9
  "table": "agents/examples/data-table.tsx",
@@ -671,6 +669,16 @@
671
669
  "useFormat"
672
670
  ]
673
671
  },
672
+ {
673
+ "file": "agents/examples/chart-panels-three.tsx",
674
+ "components": [
675
+ "AreaChartCard",
676
+ "BarChartCard",
677
+ "LineChartCard",
678
+ "PanelGrid",
679
+ "useFormat"
680
+ ]
681
+ },
674
682
  {
675
683
  "file": "agents/examples/chart-panels.tsx",
676
684
  "components": [
@@ -717,7 +725,9 @@
717
725
  "components": [
718
726
  "ContextMenu",
719
727
  "ContextMenuContent",
728
+ "ContextMenuGroup",
720
729
  "ContextMenuItem",
730
+ "ContextMenuLabel",
721
731
  "ContextMenuTrigger"
722
732
  ]
723
733
  },
@@ -1038,7 +1048,7 @@
1038
1048
  "CardTitle",
1039
1049
  "Delta",
1040
1050
  "Input",
1041
- "PageHero",
1051
+ "PageHeader",
1042
1052
  "PanelGrid",
1043
1053
  "StatusBadge",
1044
1054
  "Table",
@@ -1054,10 +1064,10 @@
1054
1064
  ]
1055
1065
  },
1056
1066
  {
1057
- "file": "agents/examples/page-hero.tsx",
1067
+ "file": "agents/examples/page-header.tsx",
1058
1068
  "components": [
1059
1069
  "Button",
1060
- "PageHero"
1070
+ "PageHeader"
1061
1071
  ]
1062
1072
  },
1063
1073
  {
@@ -1208,6 +1218,7 @@
1208
1218
  "SelectContent",
1209
1219
  "SelectGroup",
1210
1220
  "SelectItem",
1221
+ "SelectLabel",
1211
1222
  "SelectTrigger",
1212
1223
  "SelectValue"
1213
1224
  ]
@@ -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]);
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { Alert, AlertDescription, AlertTitle } from "../../../ui/alert.js";
3
2
  import { Button } from "../../../ui/button.js";
3
+ import { Alert, AlertDescription, AlertTitle } from "../../../ui/alert.js";
4
4
  import { AlertCircle } from "lucide-react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import React from "react";
@@ -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", {
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { Badge } from "../../../ui/badge.js";
3
2
  import { Button } from "../../../ui/button.js";
4
- import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "../../../ui/command.js";
3
+ import { Badge } from "../../../ui/badge.js";
5
4
  import { Separator } from "../../../ui/separator.js";
5
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "../../../ui/command.js";
6
6
  import { Popover, PopoverContent, PopoverTrigger } from "../../../ui/popover.js";
7
7
  import { cn } from "../../../../lib/utils.js";
8
8
  import { FILTER_OPERATORS, FILTER_VARIANTS, JOIN_OPERATORS } from "../lib/constants.js";
@@ -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
  });