@siyahi/ui 0.1.9-next.3 → 0.1.9-next.31

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 (254) hide show
  1. package/DESIGN.md +251 -0
  2. package/README.md +94 -177
  3. package/THIRD_PARTY_NOTICES.md +11 -11
  4. package/agents/examples/accordion.tsx +39 -0
  5. package/agents/examples/alert.tsx +24 -0
  6. package/agents/examples/app-sidebar.tsx +40 -0
  7. package/agents/examples/avatar.tsx +24 -0
  8. package/agents/examples/badge.tsx +26 -0
  9. package/agents/examples/bar-list-labels.tsx +22 -0
  10. package/agents/examples/bar-list-sides.tsx +40 -0
  11. package/agents/examples/bar-list.tsx +24 -0
  12. package/agents/examples/breadcrumb.tsx +28 -0
  13. package/agents/examples/button-states.tsx +23 -0
  14. package/agents/examples/button.tsx +21 -0
  15. package/agents/examples/calendar.tsx +11 -0
  16. package/agents/examples/callout.tsx +33 -0
  17. package/agents/examples/card.tsx +36 -0
  18. package/agents/examples/change-bar.tsx +104 -0
  19. package/agents/examples/change-grid-money.tsx +36 -0
  20. package/agents/examples/change-grid.tsx +43 -0
  21. package/agents/examples/chart-area-log.tsx +45 -0
  22. package/agents/examples/chart-area.tsx +39 -0
  23. package/agents/examples/chart-bar-flows.tsx +32 -0
  24. package/agents/examples/chart-bar-hourly.tsx +28 -0
  25. package/agents/examples/chart-bar-losses.tsx +29 -0
  26. package/agents/examples/chart-bar-teams.tsx +72 -0
  27. package/agents/examples/chart-bar-years.tsx +42 -0
  28. package/agents/examples/chart-bar.tsx +56 -0
  29. package/agents/examples/chart-category-ticks.tsx +50 -0
  30. package/agents/examples/chart-line-events.tsx +47 -0
  31. package/agents/examples/chart-line-forecast.tsx +36 -0
  32. package/agents/examples/chart-line-log.tsx +39 -0
  33. package/agents/examples/chart-line-quiet.tsx +114 -0
  34. package/agents/examples/chart-line-timeline.tsx +41 -0
  35. package/agents/examples/chart-line.tsx +57 -0
  36. package/agents/examples/chart-panels.tsx +94 -0
  37. package/agents/examples/code-block.tsx +40 -0
  38. package/agents/examples/collapsible.tsx +18 -0
  39. package/agents/examples/command.tsx +29 -0
  40. package/agents/examples/context-menu.tsx +17 -0
  41. package/agents/examples/copy-button.tsx +8 -0
  42. package/agents/examples/data-bar.tsx +114 -0
  43. package/agents/examples/data-table-compact.tsx +93 -0
  44. package/agents/examples/data-table-filters.tsx +103 -0
  45. package/agents/examples/data-table.tsx +96 -0
  46. package/agents/examples/delta.tsx +18 -0
  47. package/agents/examples/dialog.tsx +28 -0
  48. package/agents/examples/distribution-bar-budget.tsx +30 -0
  49. package/agents/examples/distribution-bar-tug.tsx +74 -0
  50. package/agents/examples/drawdown-chart.tsx +35 -0
  51. package/agents/examples/dropdown-menu.tsx +31 -0
  52. package/agents/examples/field.tsx +108 -0
  53. package/agents/examples/formatters.tsx +42 -0
  54. package/agents/examples/heatmap-calendar-signed.tsx +67 -0
  55. package/agents/examples/heatmap-calendar.tsx +62 -0
  56. package/agents/examples/heatmap-status.tsx +61 -0
  57. package/agents/examples/heatmap-weekday.tsx +72 -0
  58. package/agents/examples/histogram-chart.tsx +28 -0
  59. package/agents/examples/input-states.tsx +23 -0
  60. package/agents/examples/input.tsx +17 -0
  61. package/agents/examples/local-time.tsx +14 -0
  62. package/agents/examples/metric-strip.tsx +46 -0
  63. package/agents/examples/overview-dashboard.tsx +180 -0
  64. package/agents/examples/page-hero.tsx +38 -0
  65. package/agents/examples/page-section.tsx +52 -0
  66. package/agents/examples/popover.tsx +23 -0
  67. package/agents/examples/price-chart.tsx +32 -0
  68. package/agents/examples/progress-tone.tsx +29 -0
  69. package/agents/examples/progress.tsx +10 -0
  70. package/agents/examples/range-position-table.tsx +113 -0
  71. package/agents/examples/range-position.tsx +55 -0
  72. package/agents/examples/scatter-chart-quadrants.tsx +63 -0
  73. package/agents/examples/scatter-chart-scales.tsx +46 -0
  74. package/agents/examples/scatter-chart.tsx +78 -0
  75. package/agents/examples/scroll-area.tsx +22 -0
  76. package/agents/examples/section-cards-select.tsx +28 -0
  77. package/agents/examples/section-cards-trend.tsx +32 -0
  78. package/agents/examples/section-cards.tsx +48 -0
  79. package/agents/examples/select.tsx +27 -0
  80. package/agents/examples/separator.tsx +13 -0
  81. package/agents/examples/sheet.tsx +15 -0
  82. package/agents/examples/skeleton.tsx +11 -0
  83. package/agents/examples/slider.tsx +5 -0
  84. package/agents/examples/slope-chart-market.tsx +33 -0
  85. package/agents/examples/slope-chart.tsx +26 -0
  86. package/agents/examples/stale-blocks.tsx +56 -0
  87. package/agents/examples/surfaces.tsx +116 -0
  88. package/agents/examples/table.tsx +60 -0
  89. package/agents/examples/tabs.tsx +16 -0
  90. package/agents/examples/target-rows.tsx +74 -0
  91. package/agents/examples/toggle-group.tsx +12 -0
  92. package/agents/examples/toggle.tsx +11 -0
  93. package/agents/examples/tooltip.tsx +13 -0
  94. package/agents/examples/treemap.tsx +93 -0
  95. package/agents/examples/waterfall-chart-stores.tsx +27 -0
  96. package/agents/examples/waterfall-chart.tsx +37 -0
  97. package/agents/manifest.json +1391 -0
  98. package/agents/report-rules.json +7 -0
  99. package/dist/components/registry/charts/area-chart-card.d.ts +7 -3
  100. package/dist/components/registry/charts/area-chart-card.js +56 -10
  101. package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
  102. package/dist/components/registry/charts/bar-chart-card.js +20 -22
  103. package/dist/components/registry/charts/line-chart-card.d.ts +3 -3
  104. package/dist/components/registry/charts/line-chart-card.js +44 -9
  105. package/dist/components/registry/dashboard-01/section-cards.d.ts +6 -0
  106. package/dist/components/registry/dashboard-01/section-cards.js +51 -35
  107. package/dist/components/registry/dashboardcn/bar-list.js +17 -10
  108. package/dist/components/registry/dashboardcn/distribution-bar.js +6 -4
  109. package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
  110. package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
  111. package/dist/components/registry/dashboardcn/sparkline.d.ts +22 -0
  112. package/dist/components/registry/dashboardcn/sparkline.js +117 -0
  113. package/dist/components/registry/heatmap/calendar-heatmap.d.ts +11 -3
  114. package/dist/components/registry/heatmap/calendar-heatmap.js +164 -45
  115. package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
  116. package/dist/components/registry/heatmap/status-heatmap.js +115 -54
  117. package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
  118. package/dist/components/registry/heatmap/weekday-heatmap.js +83 -53
  119. package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
  120. package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
  121. package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
  122. package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
  123. package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
  124. package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
  125. package/dist/components/registry/niko-table/core/data-table.js +5 -1
  126. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +5 -5
  127. package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
  128. package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
  129. package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
  130. package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
  131. package/dist/components/registry/niko-table/lib/styles.js +3 -3
  132. package/dist/components/registry/niko-table/types/index.d.ts +9 -0
  133. package/dist/components/registry/niko-table/ui/table.js +2 -2
  134. package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
  135. package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
  136. package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
  137. package/dist/components/registry/sidebar-07/nav-main.js +16 -3
  138. package/dist/components/siyahi/callout.d.ts +17 -0
  139. package/dist/components/siyahi/callout.js +34 -0
  140. package/dist/components/siyahi/change-bar.d.ts +21 -0
  141. package/dist/components/siyahi/change-bar.js +35 -0
  142. package/dist/components/siyahi/change-grid.d.ts +31 -0
  143. package/dist/components/siyahi/change-grid.js +74 -0
  144. package/dist/components/siyahi/data-bar.d.ts +19 -0
  145. package/dist/components/siyahi/data-bar.js +29 -0
  146. package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
  147. package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
  148. package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
  149. package/dist/components/siyahi/data-table-footnote.js +35 -0
  150. package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
  151. package/dist/components/siyahi/default-sidebar-open.js +13 -0
  152. package/dist/components/siyahi/delta.d.ts +5 -1
  153. package/dist/components/siyahi/delta.js +14 -9
  154. package/dist/components/siyahi/drawdown-chart.d.ts +34 -0
  155. package/dist/components/siyahi/drawdown-chart.js +102 -0
  156. package/dist/components/siyahi/histogram-chart.d.ts +57 -0
  157. package/dist/components/siyahi/histogram-chart.js +134 -0
  158. package/dist/components/siyahi/page-hero.d.ts +23 -0
  159. package/dist/components/siyahi/page-hero.js +43 -0
  160. package/dist/components/siyahi/page-section.d.ts +4 -1
  161. package/dist/components/siyahi/page-section.js +6 -3
  162. package/dist/components/siyahi/page-toc.d.ts +20 -0
  163. package/dist/components/siyahi/page-toc.js +76 -0
  164. package/dist/components/siyahi/panel-grid.d.ts +24 -0
  165. package/dist/components/siyahi/panel-grid.js +37 -0
  166. package/dist/components/siyahi/quote.d.ts +12 -0
  167. package/dist/components/siyahi/quote.js +23 -0
  168. package/dist/components/siyahi/range-position.d.ts +24 -0
  169. package/dist/components/siyahi/range-position.js +105 -0
  170. package/dist/components/siyahi/scale-toggle.d.ts +32 -0
  171. package/dist/components/siyahi/scale-toggle.js +61 -0
  172. package/dist/components/siyahi/scatter-chart.d.ts +69 -0
  173. package/dist/components/siyahi/scatter-chart.js +395 -0
  174. package/dist/components/siyahi/siyahi-provider.d.ts +15 -2
  175. package/dist/components/siyahi/siyahi-provider.js +17 -4
  176. package/dist/components/siyahi/slope-chart.d.ts +35 -0
  177. package/dist/components/siyahi/slope-chart.js +159 -0
  178. package/dist/components/siyahi/stale-note.d.ts +9 -0
  179. package/dist/components/siyahi/stale-note.js +12 -0
  180. package/dist/components/siyahi/status-alert.d.ts +15 -0
  181. package/dist/components/siyahi/status-alert.js +29 -0
  182. package/dist/components/siyahi/status-badge.d.ts +15 -0
  183. package/dist/components/siyahi/status-badge.js +24 -0
  184. package/dist/components/siyahi/target-rows.d.ts +34 -0
  185. package/dist/components/siyahi/target-rows.js +97 -0
  186. package/dist/components/siyahi/tone-progress.d.ts +1 -1
  187. package/dist/components/siyahi/tone-progress.js +1 -1
  188. package/dist/components/siyahi/treemap.d.ts +8 -5
  189. package/dist/components/siyahi/treemap.js +80 -34
  190. package/dist/components/siyahi/waterfall-chart.d.ts +51 -0
  191. package/dist/components/siyahi/waterfall-chart.js +147 -0
  192. package/dist/components/ui/accordion.js +5 -5
  193. package/dist/components/ui/alert.js +2 -2
  194. package/dist/components/ui/badge.js +1 -1
  195. package/dist/components/ui/breadcrumb.js +2 -2
  196. package/dist/components/ui/button.js +10 -10
  197. package/dist/components/ui/calendar.js +1 -1
  198. package/dist/components/ui/card.js +4 -4
  199. package/dist/components/ui/chart.js +1 -1
  200. package/dist/components/ui/code-block.js +13 -12
  201. package/dist/components/ui/command.js +7 -6
  202. package/dist/components/ui/context-menu.js +7 -7
  203. package/dist/components/ui/dialog.js +5 -5
  204. package/dist/components/ui/dropdown-menu.js +8 -8
  205. package/dist/components/ui/field.d.ts +26 -0
  206. package/dist/components/ui/field.js +109 -0
  207. package/dist/components/ui/input-group.js +11 -11
  208. package/dist/components/ui/input.js +1 -1
  209. package/dist/components/ui/label.d.ts +5 -0
  210. package/dist/components/ui/label.js +13 -0
  211. package/dist/components/ui/popover.js +3 -3
  212. package/dist/components/ui/progress.js +1 -1
  213. package/dist/components/ui/select.js +6 -6
  214. package/dist/components/ui/sheet.js +5 -5
  215. package/dist/components/ui/sidebar.js +17 -18
  216. package/dist/components/ui/skeleton.js +1 -1
  217. package/dist/components/ui/slider.js +2 -2
  218. package/dist/components/ui/table.js +2 -2
  219. package/dist/components/ui/tabs.js +2 -2
  220. package/dist/components/ui/textarea.js +1 -1
  221. package/dist/components/ui/toggle-group.js +2 -2
  222. package/dist/components/ui/toggle.js +4 -4
  223. package/dist/components/ui/tooltip.js +2 -2
  224. package/dist/index.d.ts +35 -8
  225. package/dist/index.js +30 -4
  226. package/dist/lib/chart-frame.d.ts +51 -7
  227. package/dist/lib/chart-frame.js +390 -133
  228. package/dist/lib/chart-marks.d.ts +83 -0
  229. package/dist/lib/chart-marks.js +216 -0
  230. package/dist/lib/chart-series.d.ts +42 -10
  231. package/dist/lib/compact-columns.d.ts +19 -0
  232. package/dist/lib/compact-columns.js +55 -0
  233. package/dist/lib/fit-text.d.ts +6 -0
  234. package/dist/lib/fit-text.js +11 -0
  235. package/dist/lib/format.d.ts +8 -3
  236. package/dist/lib/format.js +55 -17
  237. package/dist/lib/heat.d.ts +7 -0
  238. package/dist/lib/heat.js +14 -0
  239. package/dist/lib/heatmap-navigation.d.ts +8 -0
  240. package/dist/lib/heatmap-navigation.js +49 -0
  241. package/dist/lib/scatter.d.ts +88 -0
  242. package/dist/lib/scatter.js +179 -0
  243. package/dist/lib/ticks.d.ts +27 -0
  244. package/dist/lib/ticks.js +67 -0
  245. package/dist/lib/tone.d.ts +36 -0
  246. package/dist/lib/tone.js +35 -0
  247. package/dist/lib/treemap.d.ts +0 -5
  248. package/dist/lib/treemap.js +1 -11
  249. package/dist/lib/use-element-width.d.ts +5 -0
  250. package/dist/lib/use-element-width.js +15 -0
  251. package/package.json +5 -1
  252. package/registry.lock.json +16 -0
  253. package/report.css +63 -47
  254. package/styles/siyahi.css +708 -55
@@ -0,0 +1,117 @@
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React$1 from "react";
4
+ import { Area, AreaChart, Line, LineChart, ResponsiveContainer, YAxis } from "recharts";
5
+ //#region src/components/registry/dashboardcn/sparkline.tsx
6
+ const reducedMotionQuery = "(prefers-reduced-motion: reduce)";
7
+ function subscribeToReducedMotion(onChange) {
8
+ const query = window.matchMedia(reducedMotionQuery);
9
+ query.addEventListener("change", onChange);
10
+ return () => query.removeEventListener("change", onChange);
11
+ }
12
+ function getReducedMotionSnapshot() {
13
+ return window.matchMedia(reducedMotionQuery).matches;
14
+ }
15
+ function getReducedMotionServerSnapshot() {
16
+ return true;
17
+ }
18
+ function Sparkline({ data, variant = "area", color = "var(--chart-1)", curve = "linear", strokeWidth = 1.25, animate = true, animationDuration = 500, className, ...props }) {
19
+ const id = React$1.useId();
20
+ const reducedMotion = React$1.useSyncExternalStore(subscribeToReducedMotion, getReducedMotionSnapshot, getReducedMotionServerSnapshot);
21
+ const animationActive = animate && !reducedMotion;
22
+ const points = React$1.useMemo(() => data.map((y, i) => ({
23
+ i,
24
+ y,
25
+ now: i >= data.length - 2 ? y : void 0
26
+ })), [data]);
27
+ const margin = {
28
+ top: 3,
29
+ right: 3,
30
+ bottom: 3,
31
+ left: 0
32
+ };
33
+ const axis = /* @__PURE__ */ jsx(YAxis, {
34
+ hide: true,
35
+ domain: ["dataMin", "dataMax"]
36
+ });
37
+ const now = /* @__PURE__ */ jsx(Line, {
38
+ className: "sparkline-now",
39
+ type: curve,
40
+ dataKey: "now",
41
+ stroke: color,
42
+ strokeWidth: 2,
43
+ dot: (dot) => dot.index === data.length - 1 ? /* @__PURE__ */ jsx("circle", {
44
+ cx: dot.cx,
45
+ cy: dot.cy,
46
+ r: 3,
47
+ fill: color
48
+ }, "now") : /* @__PURE__ */ jsx("g", {}, dot.index),
49
+ isAnimationActive: animationActive,
50
+ animationBegin: animationDuration,
51
+ animationDuration: 150
52
+ });
53
+ return /* @__PURE__ */ jsx("div", {
54
+ "data-slot": "sparkline",
55
+ "aria-hidden": "true",
56
+ className: cn("h-10 w-full", className),
57
+ ...props,
58
+ children: /* @__PURE__ */ jsx(ResponsiveContainer, {
59
+ width: "100%",
60
+ height: "100%",
61
+ children: variant === "line" ? /* @__PURE__ */ jsxs(LineChart, {
62
+ data: points,
63
+ margin,
64
+ children: [
65
+ axis,
66
+ /* @__PURE__ */ jsx(Line, {
67
+ type: curve,
68
+ dataKey: "y",
69
+ stroke: "var(--muted-foreground)",
70
+ strokeWidth,
71
+ dot: false,
72
+ isAnimationActive: animationActive,
73
+ animationDuration,
74
+ animationEasing: "ease-out"
75
+ }),
76
+ now
77
+ ]
78
+ }) : /* @__PURE__ */ jsxs(AreaChart, {
79
+ data: points,
80
+ margin,
81
+ children: [
82
+ axis,
83
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
84
+ id,
85
+ x1: "0",
86
+ y1: "0",
87
+ x2: "0",
88
+ y2: "1",
89
+ children: [/* @__PURE__ */ jsx("stop", {
90
+ offset: "0%",
91
+ stopColor: color,
92
+ stopOpacity: .18
93
+ }), /* @__PURE__ */ jsx("stop", {
94
+ offset: "100%",
95
+ stopColor: color,
96
+ stopOpacity: 0
97
+ })]
98
+ }) }),
99
+ /* @__PURE__ */ jsx(Area, {
100
+ type: curve,
101
+ dataKey: "y",
102
+ stroke: "var(--muted-foreground)",
103
+ strokeWidth,
104
+ fill: `url(#${id})`,
105
+ dot: false,
106
+ isAnimationActive: animationActive,
107
+ animationDuration,
108
+ animationEasing: "ease-out"
109
+ }),
110
+ now
111
+ ]
112
+ })
113
+ })
114
+ });
115
+ }
116
+ //#endregion
117
+ export { Sparkline };
@@ -32,6 +32,10 @@ export type CalendarHeatmapProps = HTMLAttributes<HTMLDivElement> & {
32
32
  blockAspectRatio?: number;
33
33
  levels?: number;
34
34
  isNormalized?: boolean;
35
+ /** Colour each day green or red by its sign, deeper the larger it is, for a daily gain or loss. */
36
+ signed?: boolean;
37
+ /** With signed: the size that takes the deepest step. Defaults to the largest day's. */
38
+ range?: number;
35
39
  colors?: ColorConfig;
36
40
  locale?: Locale;
37
41
  labels?: Labels;
@@ -75,8 +79,10 @@ export type CalendarHeatmapProps = HTMLAttributes<HTMLDivElement> & {
75
79
  * @param levels - Total number of legend cells (including empty when not normalized). Default: 5
76
80
  * @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.
77
81
  */
78
- export declare const CalendarHeatmap: ({ data, weekStart, continuousMonths, hasEmptyColumn, blockSize, blockMargin, blockRadius, blockAspectRatio, levels: levelsProp, isNormalized, colors, locale, labels: labelsProp, fontSize, emptyState, totalCount: totalCountProp, style, className, children, ...props }: CalendarHeatmapProps) => string | number | bigint | true | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
82
+ export declare const CalendarHeatmap: ({ data, weekStart, continuousMonths, hasEmptyColumn, blockSize: blockSizeProp, blockMargin, blockRadius, blockAspectRatio, levels: levelsProp, isNormalized, signed, range, colors, locale, labels: labelsProp, fontSize, emptyState, totalCount: totalCountProp, style, className, children, ...props }: CalendarHeatmapProps) => string | number | bigint | true | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
79
83
  export type CalendarHeatmapBlockProps = HTMLAttributes<SVGRectElement> & {
84
+ /** The cell the page has picked: drawn with a ring and announced as pressed. */
85
+ selected?: boolean;
80
86
  activity: ActivityWithLevel;
81
87
  dayIndex: number;
82
88
  weekIndex: number;
@@ -84,7 +90,7 @@ export type CalendarHeatmapBlockProps = HTMLAttributes<SVGRectElement> & {
84
90
  onCellClick?: (activity: ActivityWithLevel) => void;
85
91
  onCellHover?: (activity: ActivityWithLevel | null) => void;
86
92
  };
87
- export declare function CalendarHeatmapBlock({ ref, activity, dayIndex, weekIndex, highlighted, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }: CalendarHeatmapBlockProps & {
93
+ export declare function CalendarHeatmapBlock({ ref, activity, dayIndex, weekIndex, highlighted, selected, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }: CalendarHeatmapBlockProps & {
88
94
  ref?: React.RefObject<SVGRectElement | null>;
89
95
  }): import("react").JSX.Element;
90
96
  export declare namespace CalendarHeatmapBlock {
@@ -125,10 +131,12 @@ export type CalendarHeatmapLegendProps = Omit<HTMLAttributes<HTMLFieldSetElement
125
131
  less?: string;
126
132
  more?: string;
127
133
  };
134
+ /** A signed heatmap's figures in the legend's scale line, such as useFormat().money. */
135
+ valueFormatter?: (value: number) => string;
128
136
  children?: (props: {
129
137
  level: number;
130
138
  }) => ReactNode;
131
139
  };
132
- export declare const CalendarHeatmapLegend: ({ labels: labelsProp, className, children, ...props }: CalendarHeatmapLegendProps) => import("react").JSX.Element;
140
+ export declare const CalendarHeatmapLegend: ({ labels: labelsProp, valueFormatter, className, children, ...props }: CalendarHeatmapLegendProps) => import("react").JSX.Element;
133
141
  //#endregion
134
142
  export {};
@@ -1,16 +1,18 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
+ import { useElementWidth } from "../../../lib/use-element-width.js";
3
+ import { useHeatmapNavigation } from "../../../lib/heatmap-navigation.js";
4
+ import { heat, heatFill } from "../../../lib/heat.js";
2
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { Fragment as Fragment$1, createContext, use, useMemo } from "react";
6
+ import { Fragment as Fragment$1, createContext, use, useLayoutEffect, useMemo } from "react";
4
7
  import { differenceInCalendarDays, eachDayOfInterval, format, formatISO, getDay, getMonth, getYear, nextDay, parseISO, subWeeks } from "date-fns";
5
8
  //#region src/components/registry/heatmap/calendar-heatmap.tsx
6
9
  const colorStepCount = (levels, isNormalized) => Math.max(1, isNormalized ? levels : levels - 1);
7
- const getLevelFill = (level, levels, isNormalized, highlighted = false, colors) => {
10
+ const getLevelFill = (level, levels, isNormalized, colors) => {
8
11
  const emptyColor = colors?.empty ?? "var(--color-secondary)";
9
12
  const scaleColor = colors?.scale ?? "var(--color-chart-1)";
10
13
  if (level === 0) return emptyColor;
11
14
  const steps = colorStepCount(levels, isNormalized);
12
- const opacity = steps === 1 ? 100 : Math.round(20 + (level - 1) * 80 / (steps - 1));
13
- return `color-mix(in oklch, ${scaleColor} ${highlighted ? Math.round(opacity * .6) : opacity}%, transparent)`;
15
+ return `color-mix(in oklch, ${scaleColor} ${steps === 1 ? 100 : Math.round(20 + (level - 1) * 80 / (steps - 1))}%, transparent)`;
14
16
  };
15
17
  const calculateLevel = (value, minValue, maxValue, levels, isNormalized) => {
16
18
  const steps = colorStepCount(levels, isNormalized);
@@ -38,8 +40,22 @@ const generateWeekdayLabels = (locale) => {
38
40
  return date.toLocaleString("en-US", { weekday: "short" });
39
41
  });
40
42
  };
43
+ /** How a signed day is drawn: its heat tint, the edge that carries its sign's colour, and whether it is round. */
44
+ const signedMark = (value) => {
45
+ const known = Number.isFinite(value) ? value : 0;
46
+ return {
47
+ stroke: known > 0 ? "var(--positive)" : known < 0 ? "var(--negative)" : "var(--input)",
48
+ round: known < 0
49
+ };
50
+ };
41
51
  const EMPTY_STYLE = {};
42
52
  const LABEL_MARGIN = 8;
53
+ const WEEKDAY_LABEL_WIDTH = 40;
54
+ const STROKE_PADDING = 3;
55
+ const LEGEND_SWATCH = 12;
56
+ const MIN_FITTED_BLOCK = 10;
57
+ const MAX_FITTED_BLOCK = 20;
58
+ const DEFAULT_BLOCK = 12;
43
59
  const CalendarHeatmapContext = createContext(null);
44
60
  const useCalendarHeatmap = () => {
45
61
  const context = use(CalendarHeatmapContext);
@@ -131,26 +147,18 @@ const groupContinuous = (activities, weekStart = 0) => {
131
147
  const padded = [...new Array(leadingPad).fill(void 0), ...normalizedActivities];
132
148
  const numberOfWeeks = Math.ceil(padded.length / 7);
133
149
  const allWeeks = new Array(numberOfWeeks).fill(void 0).map((_, i) => padded.slice(i * 7, i * 7 + 7));
134
- const yearMap = /* @__PURE__ */ new Map();
135
- for (const week of allWeeks) {
136
- const firstActivity = week.find((a) => a !== void 0);
137
- const year = firstActivity ? getYear(parseISO(firstActivity.date)) : void 0;
138
- if (year !== void 0) {
139
- if (!yearMap.has(year)) yearMap.set(year, []);
140
- yearMap.get(year)?.push(week);
141
- }
142
- }
143
- return Array.from(yearMap.entries()).sort(([a], [b]) => a - b).map(([year, weeks]) => ({
144
- year,
150
+ return [{
151
+ year: getYear(firstDate),
145
152
  startMonth: 0,
146
- weeks
147
- }));
153
+ weeks: allWeeks
154
+ }];
148
155
  };
149
- const getMonthLabels = (weeks, monthNames = generateMonthLabels()) => {
150
- return weeks.reduce((labels, week, weekIndex) => {
156
+ const getMonthLabels = (weeks, monthNames = generateMonthLabels(), yearTicks = false) => {
157
+ const ticks = weeks.reduce((labels, week, weekIndex) => {
151
158
  const firstActivity = week.find((activity) => activity !== void 0);
152
159
  if (!firstActivity) return labels;
153
- const month = monthNames[getMonth(parseISO(firstActivity.date))];
160
+ const date = parseISO(firstActivity.date);
161
+ const month = monthNames[getMonth(date)];
154
162
  if (!month) {
155
163
  const monthName = new Date(firstActivity.date).toLocaleString("en-US", { month: "short" });
156
164
  throw new Error(`Unexpected error: undefined month label for ${monthName}.`);
@@ -158,7 +166,8 @@ const getMonthLabels = (weeks, monthNames = generateMonthLabels()) => {
158
166
  const prevLabel = labels.at(-1);
159
167
  if (weekIndex === 0 || !prevLabel || prevLabel.label !== month) return labels.concat({
160
168
  weekIndex,
161
- label: month
169
+ label: month,
170
+ year: getMonth(date) === 0 ? getYear(date) : void 0
162
171
  });
163
172
  return labels;
164
173
  }, []).filter(({ weekIndex }, index, labels) => {
@@ -167,6 +176,22 @@ const getMonthLabels = (weeks, monthNames = generateMonthLabels()) => {
167
176
  if (index === labels.length - 1) return weeks.slice(weekIndex).length >= minWeeks;
168
177
  return true;
169
178
  });
179
+ if (!yearTicks) return ticks;
180
+ const hasJanuary = ticks.some(({ year }) => year !== void 0);
181
+ return ticks.map((tick, index) => {
182
+ if (tick.year !== void 0) return {
183
+ ...tick,
184
+ label: String(tick.year)
185
+ };
186
+ if (index === 0 && !hasJanuary) {
187
+ const week = weeks[tick.weekIndex]?.find((activity) => activity !== void 0);
188
+ return week ? {
189
+ ...tick,
190
+ label: `${tick.label} ${getYear(parseISO(week.date))}`
191
+ } : tick;
192
+ }
193
+ return tick;
194
+ });
170
195
  };
171
196
  /**
172
197
  * Calendar Heatmap
@@ -201,8 +226,9 @@ const getMonthLabels = (weeks, monthNames = generateMonthLabels()) => {
201
226
  * @param levels - Total number of legend cells (including empty when not normalized). Default: 5
202
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.
203
228
  */
204
- const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmptyColumn = false, blockSize = 12, blockMargin = 4, blockRadius = 2, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, 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 = 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 }) => {
205
230
  const levels = Math.max(1, levelsProp);
231
+ const [rootRef, rootWidth] = useElementWidth();
206
232
  const dataWithLevels = useMemo(() => {
207
233
  if (data.length === 0) return [];
208
234
  const maxCount = data.reduce((max, d) => Math.max(max, d.value), 1);
@@ -223,6 +249,15 @@ const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmpt
223
249
  continuousMonths
224
250
  ]);
225
251
  const weeks = useMemo(() => yearRows.flatMap((r) => r.weeks), [yearRows]);
252
+ const signedRange = useMemo(() => {
253
+ if (!signed) return null;
254
+ if (range !== void 0 && Number.isFinite(range) && range > 0) return range;
255
+ return Math.max(0, ...data.map((d) => Number.isFinite(d.value) ? Math.abs(d.value) : 0));
256
+ }, [
257
+ signed,
258
+ range,
259
+ data
260
+ ]);
226
261
  const labels = useMemo(() => ({
227
262
  months: generateMonthLabels(locale),
228
263
  weekdays: generateWeekdayLabels(locale),
@@ -235,6 +270,8 @@ const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmpt
235
270
  const labelHeight = fontSize + LABEL_MARGIN;
236
271
  const year = data.length > 0 ? getYear(parseISO(data[0].date)) : (/* @__PURE__ */ new Date()).getFullYear();
237
272
  const totalCount = typeof totalCountProp === "number" ? totalCountProp : dataWithLevels.reduce((sum, activity) => sum + activity.value, 0);
273
+ const fitted = (rootWidth - WEEKDAY_LABEL_WIDTH - 6 + blockMargin) / Math.max(weeks.length, 1) - blockMargin;
274
+ const blockSize = blockSizeProp ?? (rootWidth > 0 ? Math.min(MAX_FITTED_BLOCK, Math.max(MIN_FITTED_BLOCK, fitted)) / blockAspectRatio : DEFAULT_BLOCK);
238
275
  const blockWidth = blockSize * blockAspectRatio;
239
276
  const width = weeks.length * (blockWidth + blockMargin) - blockMargin;
240
277
  const height = labelHeight + (blockSize + blockMargin) * 7 - blockMargin;
@@ -260,7 +297,8 @@ const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmpt
260
297
  hasEmptyColumn,
261
298
  continuousMonths,
262
299
  locale,
263
- colors
300
+ colors,
301
+ signedRange
264
302
  }), [
265
303
  dataWithLevels,
266
304
  weeks,
@@ -283,14 +321,16 @@ const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmpt
283
321
  hasEmptyColumn,
284
322
  continuousMonths,
285
323
  locale,
286
- colors
324
+ colors,
325
+ signedRange
287
326
  ]);
288
327
  if (data.length === 0) return emptyState ? emptyState : null;
289
328
  return /* @__PURE__ */ jsx(CalendarHeatmapContext, {
290
329
  value: contextValue,
291
330
  children: /* @__PURE__ */ jsx("div", {
331
+ ref: rootRef,
292
332
  "data-slot": "calendar-heatmap",
293
- className: cn("flex w-max max-w-full flex-col gap-2 p-4", className),
333
+ className: cn("flex flex-col gap-2", blockSizeProp === void 0 ? "w-full" : "w-max max-w-full", className),
294
334
  style: {
295
335
  fontSize,
296
336
  ...style
@@ -300,29 +340,34 @@ const CalendarHeatmap = ({ data, weekStart = 0, continuousMonths = true, hasEmpt
300
340
  })
301
341
  });
302
342
  };
303
- const CalendarHeatmapBlock = ({ ref, activity, dayIndex, weekIndex, highlighted = false, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }) => {
304
- const { blockSize, blockWidth, blockMargin, blockRadius, labelHeight, labels, levels, isNormalized, colors } = useCalendarHeatmap();
343
+ const CalendarHeatmapBlock = ({ ref, activity, dayIndex, weekIndex, highlighted = false, selected = false, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }) => {
344
+ const { blockSize, blockWidth, blockMargin, blockRadius, labelHeight, labels, levels, isNormalized, colors, signedRange } = useCalendarHeatmap();
305
345
  const level = Math.max(0, Math.min(colorStepCount(levels, isNormalized), activity.level));
346
+ const mark = signedRange === null ? null : signedMark(activity.value);
306
347
  const ariaLabel = (labels.cellLabel ?? "{{date}}: {{value}} contributions").replace("{{date}}", activity.date).replace("{{value}}", String(activity.value));
307
348
  return /* @__PURE__ */ jsx("rect", {
308
349
  ref,
309
350
  "data-slot": "calendar-heatmap-block",
310
351
  role: onCellClick ? "button" : "img",
352
+ "aria-pressed": onCellClick ? selected : void 0,
311
353
  tabIndex: onCellClick ? 0 : -1,
312
354
  "aria-label": ariaLabel,
313
- className: cn("motion-safe:transition-opacity motion-safe:hover:opacity-70", onCellClick && "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className),
355
+ className: cn("hover:stroke-foreground hover:stroke-1", highlighted && "stroke-foreground stroke-1", selected && "stroke-foreground stroke-2 hover:stroke-2", onCellClick && "cursor-pointer", className),
314
356
  "data-value": activity.value,
315
357
  "data-date": activity.date,
316
358
  "data-level": level,
317
359
  "data-highlighted": highlighted || void 0,
360
+ "data-selected": selected || void 0,
318
361
  height: blockSize,
319
- rx: blockRadius,
320
- ry: blockRadius,
362
+ rx: mark?.round ? blockSize / 2 : blockRadius,
363
+ ry: mark?.round ? blockSize / 2 : blockRadius,
321
364
  width: blockWidth,
365
+ stroke: mark?.stroke,
366
+ strokeWidth: mark ? 1 : void 0,
322
367
  x: (blockWidth + blockMargin) * weekIndex,
323
368
  y: labelHeight + (blockSize + blockMargin) * dayIndex,
324
369
  style: {
325
- fill: getLevelFill(level, levels, isNormalized, highlighted, colors),
370
+ fill: signedRange === null ? getLevelFill(level, levels, isNormalized, colors) : heat(activity.value, signedRange),
326
371
  ...styleProp
327
372
  },
328
373
  onClick: (event) => {
@@ -349,17 +394,18 @@ const CalendarHeatmapBlock = ({ ref, activity, dayIndex, weekIndex, highlighted
349
394
  };
350
395
  CalendarHeatmapBlock.displayName = "CalendarHeatmapBlock";
351
396
  const CalendarHeatmapBody = ({ hideMonthLabels = false, hideWeekdayLabels = false, hideYearLabels = false, className, labelClassName, yearClassName, children, renderYearFooter, ...props }) => {
352
- const { yearRows, blockSize, blockWidth, blockMargin, labels, labelHeight, fontSize, weekStart, data } = useCalendarHeatmap();
353
- const weekdayLabelWidth = hideWeekdayLabels ? 0 : 40;
354
- const strokePadding = 3;
397
+ const navigation = useHeatmapNavigation();
398
+ const { yearRows, blockSize, blockWidth, blockMargin, labels, labelHeight, fontSize, weekStart, continuousMonths } = useCalendarHeatmap();
399
+ const weekdayLabelWidth = hideWeekdayLabels ? 0 : WEEKDAY_LABEL_WIDTH;
400
+ const strokePadding = STROKE_PADDING;
355
401
  const rowData = useMemo(() => {
356
402
  return yearRows.map((yearRow) => {
357
403
  return {
358
404
  yearRow,
359
405
  width: yearRow.weeks.length * (blockWidth + blockMargin) - blockMargin,
360
406
  height: labelHeight + (blockSize + blockMargin) * 7 - blockMargin,
361
- monthLabels: getMonthLabels(yearRow.weeks, labels.months),
362
- yearTotalCount: data.filter((activity) => getYear(parseISO(activity.date)) === yearRow.year).reduce((sum, activity) => sum + activity.value, 0)
407
+ monthLabels: getMonthLabels(yearRow.weeks, labels.months, continuousMonths),
408
+ yearTotalCount: yearRow.weeks.flat().reduce((sum, activity) => sum + (activity?.value ?? 0), 0)
363
409
  };
364
410
  });
365
411
  }, [
@@ -369,15 +415,28 @@ const CalendarHeatmapBody = ({ hideMonthLabels = false, hideWeekdayLabels = fals
369
415
  blockMargin,
370
416
  labelHeight,
371
417
  labels.months,
372
- data
418
+ continuousMonths
373
419
  ]);
374
420
  const totalWidth = weekdayLabelWidth + Math.max(...rowData.map((r) => r.width)) + 6;
421
+ const scroller = navigation.ref;
422
+ useLayoutEffect(() => {
423
+ if (continuousMonths && scroller.current) scroller.current.scrollLeft = scroller.current.scrollWidth;
424
+ }, [
425
+ continuousMonths,
426
+ scroller,
427
+ totalWidth
428
+ ]);
375
429
  return /* @__PURE__ */ jsx("div", {
376
430
  "data-slot": "calendar-heatmap-body",
431
+ ref: navigation.ref,
377
432
  className: cn("flex max-w-full flex-col gap-6 overflow-x-auto overflow-y-hidden py-4", className),
378
433
  ...props,
434
+ onKeyDown: (event) => {
435
+ props.onKeyDown?.(event);
436
+ if (!event.defaultPrevented) navigation.onKeyDown(event);
437
+ },
379
438
  children: rowData.map(({ yearRow, height, monthLabels, yearTotalCount }) => /* @__PURE__ */ jsxs("div", { children: [
380
- !hideYearLabels && /* @__PURE__ */ jsx("div", {
439
+ !hideYearLabels && !continuousMonths && /* @__PURE__ */ jsx("div", {
381
440
  className: cn("mb-2 text-muted-foreground", yearClassName),
382
441
  children: yearRow.year
383
442
  }),
@@ -457,8 +516,14 @@ const CalendarHeatmapStat = ({ compute, label, className, children, ...props })
457
516
  children: template.replace("{{value}}", String(value)).replace("{{year}}", String(year))
458
517
  });
459
518
  };
460
- const CalendarHeatmapLegend = ({ labels: labelsProp, className, children, ...props }) => {
461
- const { levels, isNormalized, blockSize, blockWidth, blockRadius, colors, labels } = useCalendarHeatmap();
519
+ const CalendarHeatmapLegend = ({ labels: labelsProp, valueFormatter, className, children, ...props }) => {
520
+ const { levels, isNormalized, blockRadius, colors, labels, signedRange } = useCalendarHeatmap();
521
+ if (signedRange !== null) return /* @__PURE__ */ jsx(SignedLegend, {
522
+ labels: labelsProp,
523
+ valueFormatter,
524
+ className,
525
+ ...props
526
+ });
462
527
  const lessLabel = labelsProp?.less ?? "Less";
463
528
  const moreLabel = labelsProp?.more ?? "More";
464
529
  const legendLevels = Array.from({ length: levels }, (_, i) => isNormalized ? i + 1 : i);
@@ -475,15 +540,15 @@ const CalendarHeatmapLegend = ({ labels: labelsProp, className, children, ...pro
475
540
  legendLevels.map((level) => children ? /* @__PURE__ */ jsx(Fragment$1, { children: children({ level }) }, `legend-level-${level}`) : /* @__PURE__ */ jsx("svg", {
476
541
  role: "img",
477
542
  "aria-label": (labels.legendLevelLabel ?? "{{level}} contributions").replace("{{level}}", String(level)),
478
- height: blockSize,
479
- width: blockWidth,
543
+ height: LEGEND_SWATCH,
544
+ width: LEGEND_SWATCH,
480
545
  children: /* @__PURE__ */ jsx("rect", {
481
546
  "data-level": level,
482
- height: blockSize,
547
+ height: LEGEND_SWATCH,
483
548
  rx: blockRadius,
484
549
  ry: blockRadius,
485
- width: blockWidth,
486
- style: { fill: getLevelFill(level, levels, isNormalized, false, colors) }
550
+ width: LEGEND_SWATCH,
551
+ style: { fill: getLevelFill(level, levels, isNormalized, colors) }
487
552
  })
488
553
  }, `legend-level-${level}`)),
489
554
  /* @__PURE__ */ jsx("span", {
@@ -493,5 +558,59 @@ const CalendarHeatmapLegend = ({ labels: labelsProp, className, children, ...pro
493
558
  ]
494
559
  });
495
560
  };
561
+ /** A signed heatmap's scale: round loss steps deepest first, no change, square gain steps, and what they span. */
562
+ const SignedLegend = ({ labels: labelsProp, valueFormatter = String, className, ...props }) => {
563
+ const { blockRadius, labels, signedRange } = useCalendarHeatmap();
564
+ const steps = Array.from({ length: 5 }, (_, i) => i + 1);
565
+ const swatch = (key, fill, value) => {
566
+ const { stroke, round } = signedMark(value);
567
+ const corner = round ? 11 / 2 : blockRadius;
568
+ return /* @__PURE__ */ jsx("svg", {
569
+ "aria-hidden": "true",
570
+ height: LEGEND_SWATCH,
571
+ width: LEGEND_SWATCH,
572
+ children: /* @__PURE__ */ jsx("rect", {
573
+ x: .5,
574
+ y: .5,
575
+ height: 11,
576
+ width: 11,
577
+ rx: corner,
578
+ ry: corner,
579
+ stroke,
580
+ style: { fill }
581
+ })
582
+ }, key);
583
+ };
584
+ return /* @__PURE__ */ jsxs("fieldset", {
585
+ "data-slot": "calendar-heatmap-legend",
586
+ "aria-label": labels.legendLabel ?? "Activity intensity legend",
587
+ className: cn("ml-auto flex flex-col items-end gap-1 text-muted-foreground", className),
588
+ ...props,
589
+ children: [/* @__PURE__ */ jsxs("div", {
590
+ className: "flex items-center gap-1",
591
+ children: [
592
+ /* @__PURE__ */ jsx("span", {
593
+ className: "mr-1 font-medium text-xs",
594
+ children: labelsProp?.less ?? "Loss"
595
+ }),
596
+ steps.toReversed().map((step) => swatch(`loss-${step}`, heatFill("negative", step), -1)),
597
+ swatch("none", heat(null), 0),
598
+ steps.map((step) => swatch(`gain-${step}`, heatFill("positive", step), 1)),
599
+ /* @__PURE__ */ jsx("span", {
600
+ className: "ml-1 font-medium text-xs",
601
+ children: labelsProp?.more ?? "Gain"
602
+ })
603
+ ]
604
+ }), /* @__PURE__ */ jsxs("p", {
605
+ "data-slot": "calendar-heatmap-legend-scale",
606
+ className: "text-xs",
607
+ children: [
608
+ "Deepest at ±",
609
+ valueFormatter(signedRange ?? 0),
610
+ ". Round days lost, square days gained; grey days had no change."
611
+ ]
612
+ })]
613
+ });
614
+ };
496
615
  //#endregion
497
616
  export { CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBody, CalendarHeatmapFooter, CalendarHeatmapLegend, CalendarHeatmapStat };
@@ -69,11 +69,13 @@ export type StatusHeatmapProps = HTMLAttributes<HTMLDivElement> & {
69
69
  *
70
70
  * @param data - Array of activities with date (YYYY-MM-DD) and status value (0-3)
71
71
  * @param dateFormat - Date format string for tooltips. Default: "MMM d"
72
- * @param blockAspectRatio - Width/height ratio of blocks. Default: 0.2 (narrow vertical bars)
72
+ * @param blockAspectRatio - Width/height ratio of blocks. Default: bars share the full width
73
73
  * @param colors - Custom colors for critical, degraded, and healthy states
74
74
  */
75
- export declare const StatusHeatmap: ({ data, dateFormat, blockSize, blockMargin, blockRadius, blockAspectRatio, colors, locale, labels: labelsProp, fontSize, emptyState, statusValues, healthyValue, style, className, children, ...props }: StatusHeatmapProps) => string | number | bigint | true | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
75
+ export declare const StatusHeatmap: ({ data, dateFormat, blockSize, blockMargin, blockRadius, blockAspectRatio: blockAspectRatioProp, colors, locale, labels: labelsProp, fontSize, emptyState, statusValues, healthyValue, style, className, children, ...props }: StatusHeatmapProps) => string | number | bigint | true | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
76
76
  export type StatusHeatmapBlockProps = HTMLAttributes<SVGRectElement> & {
77
+ /** The cell the page has picked: drawn with a ring and announced as pressed. */
78
+ selected?: boolean;
77
79
  activity: StatusActivity;
78
80
  dayIndex: number;
79
81
  highlighted?: boolean;
@@ -81,7 +83,7 @@ export type StatusHeatmapBlockProps = HTMLAttributes<SVGRectElement> & {
81
83
  onCellHover?: (activity: StatusActivity | null) => void;
82
84
  className?: string;
83
85
  };
84
- export declare function StatusHeatmapBlock({ ref, activity, dayIndex, highlighted, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }: StatusHeatmapBlockProps & {
86
+ export declare function StatusHeatmapBlock({ ref, activity, dayIndex, highlighted, selected, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }: StatusHeatmapBlockProps & {
85
87
  ref?: React.RefObject<SVGRectElement | null>;
86
88
  }): import("react").JSX.Element;
87
89
  export declare namespace StatusHeatmapBlock {