@nocoo/basalt 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -15
- package/ai/COMPATIBILITY.md +180 -0
- package/ai/INTEGRATION.md +1760 -0
- package/ai/RECIPES.md +161 -0
- package/ai/USAGE.md +99 -0
- package/ai/registry.json +38099 -0
- package/ai/sources.json +10 -0
- package/dist/assets/brand-mark.d.ts +1 -0
- package/dist/assets/brand-mark.js +7 -0
- package/dist/assets/brand-mark.js.map +1 -0
- package/dist/charts/area.d.ts +58 -5
- package/dist/charts/area.js +20 -12
- package/dist/charts/area.js.map +1 -1
- package/dist/charts/bar.d.ts +54 -5
- package/dist/charts/bar.js +16 -10
- package/dist/charts/bar.js.map +1 -1
- package/dist/charts/bullet.d.ts +18 -1
- package/dist/charts/bullet.js +6 -3
- package/dist/charts/bullet.js.map +1 -1
- package/dist/charts/charts.d.ts +58 -5
- package/dist/charts/charts.js +13 -2
- package/dist/charts/charts.js.map +1 -1
- package/dist/charts/config.d.ts +7 -0
- package/dist/charts/config.js +5 -1
- package/dist/charts/config.js.map +1 -1
- package/dist/charts/custom-chart.d.ts +58 -5
- package/dist/charts/custom-chart.js +13 -2
- package/dist/charts/custom-chart.js.map +1 -1
- package/dist/charts/donut.d.ts +18 -1
- package/dist/charts/donut.js +6 -3
- package/dist/charts/donut.js.map +1 -1
- package/dist/charts/frame.d.ts +40 -3
- package/dist/charts/frame.js +55 -28
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/funnel.d.ts +18 -1
- package/dist/charts/funnel.js +5 -1
- package/dist/charts/funnel.js.map +1 -1
- package/dist/charts/gauge.d.ts +18 -1
- package/dist/charts/gauge.js +38 -20
- package/dist/charts/gauge.js.map +1 -1
- package/dist/charts/grouped-bar.d.ts +54 -5
- package/dist/charts/grouped-bar.js +16 -10
- package/dist/charts/grouped-bar.js.map +1 -1
- package/dist/charts/heatmap-calendar.d.ts +61 -0
- package/dist/charts/heatmap-calendar.js +287 -96
- package/dist/charts/heatmap-calendar.js.map +1 -1
- package/dist/charts/heatmap-matrix.d.ts +99 -0
- package/dist/charts/heatmap-matrix.js +249 -0
- package/dist/charts/heatmap-matrix.js.map +1 -0
- package/dist/charts/line.d.ts +66 -5
- package/dist/charts/line.js +37 -30
- package/dist/charts/line.js.map +1 -1
- package/dist/charts/palette.d.ts +1 -0
- package/dist/charts/palette.js +7 -1
- package/dist/charts/palette.js.map +1 -1
- package/dist/charts/radar.d.ts +18 -1
- package/dist/charts/radar.js +26 -19
- package/dist/charts/radar.js.map +1 -1
- package/dist/charts/sankey.d.ts +18 -1
- package/dist/charts/sankey.js +4 -1
- package/dist/charts/sankey.js.map +1 -1
- package/dist/charts/series.d.ts +5 -7
- package/dist/charts/series.js.map +1 -1
- package/dist/charts/slot-bar.d.ts +38 -6
- package/dist/charts/slot-bar.js +5 -2
- package/dist/charts/slot-bar.js.map +1 -1
- package/dist/charts/sparkline.d.ts +35 -5
- package/dist/charts/sparkline.js +22 -18
- package/dist/charts/sparkline.js.map +1 -1
- package/dist/charts/stacked-bar.d.ts +58 -5
- package/dist/charts/stacked-bar.js +19 -12
- package/dist/charts/stacked-bar.js.map +1 -1
- package/dist/charts/stat-card.d.ts +51 -1
- package/dist/charts/stat-card.js +66 -39
- package/dist/charts/stat-card.js.map +1 -1
- package/dist/charts/timeline.d.ts +3 -0
- package/dist/charts/timeline.js +4 -3
- package/dist/charts/timeline.js.map +1 -1
- package/dist/charts/timeseries.d.ts +58 -5
- package/dist/charts/timeseries.js +13 -2
- package/dist/charts/timeseries.js.map +1 -1
- package/dist/charts/tooltip.d.ts +57 -0
- package/dist/charts/tooltip.js +119 -2
- package/dist/charts/tooltip.js.map +1 -1
- package/dist/components/accordion.d.ts +117 -2
- package/dist/components/accordion.js +20 -13
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/alert-dialog.d.ts +131 -13
- package/dist/components/alert-dialog.js +13 -10
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/app-header.js +18 -17
- package/dist/components/app-header.js.map +1 -1
- package/dist/components/app-shell.js +15 -14
- package/dist/components/app-shell.js.map +1 -1
- package/dist/components/autocomplete.d.ts +4 -0
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/avatar.d.ts +76 -3
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/badge.d.ts +15 -1
- package/dist/components/badge.js +17 -16
- package/dist/components/badge.js.map +1 -1
- package/dist/components/banner.d.ts +88 -2
- package/dist/components/banner.js +41 -40
- package/dist/components/banner.js.map +1 -1
- package/dist/components/basalt-mark.js +14 -8
- package/dist/components/basalt-mark.js.map +1 -1
- package/dist/components/battery-meter.d.ts +10 -0
- package/dist/components/battery-meter.js +56 -0
- package/dist/components/battery-meter.js.map +1 -0
- package/dist/components/breadcrumbs.d.ts +27 -7
- package/dist/components/breadcrumbs.js +21 -20
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/button.d.ts +48 -2
- package/dist/components/button.js +87 -36
- package/dist/components/button.js.map +1 -1
- package/dist/components/chat-bubble.d.ts +24 -0
- package/dist/components/chat-bubble.js +26 -0
- package/dist/components/chat-bubble.js.map +1 -0
- package/dist/components/chat-composer.d.ts +45 -0
- package/dist/components/chat-composer.js +74 -0
- package/dist/components/chat-composer.js.map +1 -0
- package/dist/components/chat-header.d.ts +25 -0
- package/dist/components/chat-header.js +34 -0
- package/dist/components/chat-header.js.map +1 -0
- package/dist/components/chat-inbox.d.ts +33 -0
- package/dist/components/chat-inbox.js +44 -0
- package/dist/components/chat-inbox.js.map +1 -0
- package/dist/components/checkbox.js +84 -53
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/clipboard-text.d.ts +13 -2
- package/dist/components/clipboard-text.js +4 -4
- package/dist/components/clipboard-text.js.map +1 -1
- package/dist/components/collapsible.d.ts +58 -15
- package/dist/components/collapsible.js.map +1 -1
- package/dist/components/command-palette.d.ts +151 -61
- package/dist/components/command-palette.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +1 -1
- package/dist/components/confirm-dialog.js +6 -4
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/context-menu.d.ts +210 -2
- package/dist/components/context-menu.js +7 -4
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/data-table.d.ts +40 -2
- package/dist/components/data-table.js +168 -120
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +53 -2
- package/dist/components/date-picker.js +387 -219
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/delete-resource.d.ts +7 -1
- package/dist/components/delete-resource.js +22 -18
- package/dist/components/delete-resource.js.map +1 -1
- package/dist/components/description-list.js +16 -15
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog.d.ts +141 -12
- package/dist/components/dialog.js +43 -39
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/dock.d.ts +39 -0
- package/dist/components/dock.js +97 -0
- package/dist/components/dock.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +229 -15
- package/dist/components/dropdown-menu.js +9 -6
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/editable-nav-item.d.ts +33 -0
- package/dist/components/editable-nav-item.js +90 -0
- package/dist/components/editable-nav-item.js.map +1 -0
- package/dist/components/empty.d.ts +22 -2
- package/dist/components/empty.js +22 -13
- package/dist/components/empty.js.map +1 -1
- package/dist/components/fab.d.ts +23 -0
- package/dist/components/fab.js +25 -0
- package/dist/components/fab.js.map +1 -0
- package/dist/components/field.js +31 -30
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +37 -0
- package/dist/components/file-dropzone.js +103 -0
- package/dist/components/file-dropzone.js.map +1 -0
- package/dist/components/filter-bar.d.ts +34 -0
- package/dist/components/filter-bar.js +52 -0
- package/dist/components/filter-bar.js.map +1 -0
- package/dist/components/flow.js +19 -18
- package/dist/components/flow.js.map +1 -1
- package/dist/components/grid.d.ts +3 -1
- package/dist/components/grid.js.map +1 -1
- package/dist/components/hover-card.d.ts +111 -1
- package/dist/components/hover-card.js +9 -6
- package/dist/components/hover-card.js.map +1 -1
- package/dist/components/icon-picker.d.ts +34 -0
- package/dist/components/icon-picker.js +77 -0
- package/dist/components/icon-picker.js.map +1 -0
- package/dist/components/inline-editable.d.ts +46 -0
- package/dist/components/inline-editable.js +124 -0
- package/dist/components/inline-editable.js.map +1 -0
- package/dist/components/input-area.js +3 -3
- package/dist/components/input-group.js +7 -7
- package/dist/components/input.js +3 -3
- package/dist/components/label.js +18 -17
- package/dist/components/label.js.map +1 -1
- package/dist/components/layer-card.d.ts +10 -2
- package/dist/components/layer-card.js +71 -68
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/loader.d.ts +10 -2
- package/dist/components/loader.js.map +1 -1
- package/dist/components/menu-bar.d.ts +174 -6
- package/dist/components/menu-bar.js +33 -29
- package/dist/components/menu-bar.js.map +1 -1
- package/dist/components/meter.d.ts +27 -2
- package/dist/components/meter.js.map +1 -1
- package/dist/components/multi-select.d.ts +64 -0
- package/dist/components/multi-select.js +218 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/navigation-menu.d.ts +88 -5
- package/dist/components/navigation-menu.js.map +1 -1
- package/dist/components/overlay.js +6 -5
- package/dist/components/overlay.js.map +1 -1
- package/dist/components/page-header.js +23 -21
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/pagination.js +7 -7
- package/dist/components/popover.d.ts +136 -16
- package/dist/components/popover.js +32 -28
- package/dist/components/popover.js.map +1 -1
- package/dist/components/radio.js +38 -37
- package/dist/components/radio.js.map +1 -1
- package/dist/components/resource-list.d.ts +26 -1
- package/dist/components/resource-list.js +28 -15
- package/dist/components/resource-list.js.map +1 -1
- package/dist/components/responsive-master-detail.d.ts +27 -0
- package/dist/components/responsive-master-detail.js +85 -0
- package/dist/components/responsive-master-detail.js.map +1 -0
- package/dist/components/section-rule.js +23 -22
- package/dist/components/section-rule.js.map +1 -1
- package/dist/components/select.d.ts +27 -3
- package/dist/components/select.js +11 -11
- package/dist/components/select.js.map +1 -1
- package/dist/components/sheet.d.ts +115 -11
- package/dist/components/sheet.js +37 -30
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/sidebar.d.ts +109 -17
- package/dist/components/sidebar.js +109 -108
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/skeleton-line.d.ts +22 -2
- package/dist/components/skeleton-line.js.map +1 -1
- package/dist/components/slider.d.ts +61 -1
- package/dist/components/slider.js +31 -15
- package/dist/components/slider.js.map +1 -1
- package/dist/components/stat-strip.js +16 -15
- package/dist/components/stat-strip.js.map +1 -1
- package/dist/components/switch.js +78 -47
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table-of-contents.js +18 -17
- package/dist/components/table-of-contents.js.map +1 -1
- package/dist/components/table-pager.js +20 -19
- package/dist/components/table-pager.js.map +1 -1
- package/dist/components/table.d.ts +9 -3
- package/dist/components/table.js +19 -18
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +29 -22
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag-badge.d.ts +58 -0
- package/dist/components/tag-badge.js +72 -0
- package/dist/components/tag-badge.js.map +1 -0
- package/dist/components/tag-color-picker.d.ts +20 -0
- package/dist/components/tag-color-picker.js +42 -0
- package/dist/components/tag-color-picker.js.map +1 -0
- package/dist/components/text.js +17 -16
- package/dist/components/text.js.map +1 -1
- package/dist/components/toast.d.ts +173 -3
- package/dist/components/toast.js +1 -1
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.d.ts +88 -2
- package/dist/components/toggle-group.js +32 -31
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.d.ts +35 -2
- package/dist/components/toggle.js +12 -11
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.d.ts +144 -6
- package/dist/components/tooltip.js +9 -6
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/typeahead-field.js +193 -132
- package/dist/components/typeahead-field.js.map +1 -1
- package/dist/components/upload-queue.d.ts +51 -0
- package/dist/components/upload-queue.js +116 -0
- package/dist/components/upload-queue.js.map +1 -0
- package/dist/providers/accent.d.ts +46 -2
- package/dist/providers/accent.js +358 -172
- package/dist/providers/accent.js.map +1 -1
- package/dist/providers/link.d.ts +14 -4
- package/dist/providers/link.js.map +1 -1
- package/dist/providers/theme.d.ts +38 -2
- package/dist/providers/theme.js +160 -27
- package/dist/providers/theme.js.map +1 -1
- package/dist/styles/base.css +83 -0
- package/dist/styles/standalone.css +820 -120
- package/dist/styles/tailwind.css +21 -7
- package/dist/styles/tokens.css +146 -91
- package/dist/utils/control-surface.d.ts +2 -1
- package/dist/utils/control-surface.js +4 -4
- package/dist/utils/control-surface.js.map +1 -1
- package/dist/utils/selection-indicator.js +2 -2
- package/dist/utils/selection-indicator.js.map +1 -1
- package/package.json +8 -4
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../utils/cn.js";
|
|
3
3
|
import { Tooltip as t, TooltipContent as n, TooltipProvider as r, TooltipTrigger as i } from "../components/tooltip.js";
|
|
4
|
-
import {
|
|
5
|
-
import { jsx as
|
|
4
|
+
import { useEffect as a, useId as o, useMemo as s, useRef as c, useState as l } from "react";
|
|
5
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
6
|
//#region src/charts/heatmap-calendar.tsx
|
|
7
|
-
var
|
|
7
|
+
var f = {
|
|
8
8
|
green: [
|
|
9
9
|
"hsl(var(--basalt-muted))",
|
|
10
10
|
"hsl(var(--basalt-heatmap-green-1))",
|
|
@@ -34,165 +34,356 @@ var c = {
|
|
|
34
34
|
"hsl(var(--basalt-heatmap-orange-4))"
|
|
35
35
|
]
|
|
36
36
|
};
|
|
37
|
-
function
|
|
37
|
+
function p(e) {
|
|
38
38
|
return Array.from({ length: 7 }, (t, n) => new Intl.DateTimeFormat(e, { weekday: "short" }).format(new Date(2023, 0, 1 + n)));
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function m(e) {
|
|
41
41
|
return Array.from({ length: 12 }, (t, n) => new Intl.DateTimeFormat(e, { month: "short" }).format(new Date(2023, n, 1)));
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function h(e) {
|
|
44
44
|
let t = [], n = new Date(e, 0, 1), r = new Date(e, 11, 31), i = new Date(n);
|
|
45
45
|
i.setDate(i.getDate() - i.getDay());
|
|
46
46
|
let a = new Date(i), o = [];
|
|
47
47
|
for (; (a <= r || o.length > 0) && (o.length === 7 && (t.push(o), o = []), !(a > r));) o.push(new Date(a)), a = new Date(a), a.setDate(a.getDate() + 1);
|
|
48
48
|
return o.length > 0 && t.push(o), t;
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function g(e) {
|
|
51
51
|
return `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
|
|
52
52
|
}
|
|
53
|
-
function
|
|
53
|
+
function _(e, t, n) {
|
|
54
54
|
if (e === 0) return 0;
|
|
55
55
|
let r = n.length - 1, i = Math.min(e / t, 1);
|
|
56
56
|
return Math.ceil(i * r);
|
|
57
57
|
}
|
|
58
|
-
function
|
|
59
|
-
if ("data" in
|
|
60
|
-
let { colorScale:
|
|
61
|
-
return /* @__PURE__ */
|
|
62
|
-
data:
|
|
63
|
-
year:
|
|
64
|
-
colorScale:
|
|
58
|
+
function v(e) {
|
|
59
|
+
if ("data" in e) {
|
|
60
|
+
let { colorScale: t = f.green, valueFormatter: n = (e) => e.toLocaleString(), metricLabel: r = "Value", cellSize: i = 12, cellGap: a = 2, locale: o = "en-US", weekdayLabels: s, monthLabels: c, lessLabel: l = "Less", moreLabel: d = "More", ariaLabel: p = "Heatmap calendar", className: m } = e;
|
|
61
|
+
return /* @__PURE__ */ u(b, {
|
|
62
|
+
data: e.data,
|
|
63
|
+
year: e.year,
|
|
64
|
+
colorScale: t,
|
|
65
65
|
valueFormatter: n,
|
|
66
66
|
metricLabel: r,
|
|
67
67
|
cellSize: i,
|
|
68
68
|
cellGap: a,
|
|
69
|
-
locale:
|
|
70
|
-
weekdayLabels:
|
|
71
|
-
monthLabels:
|
|
72
|
-
lessLabel:
|
|
73
|
-
moreLabel:
|
|
69
|
+
locale: o,
|
|
70
|
+
weekdayLabels: s,
|
|
71
|
+
monthLabels: c,
|
|
72
|
+
lessLabel: l,
|
|
73
|
+
moreLabel: d,
|
|
74
74
|
ariaLabel: p,
|
|
75
75
|
className: m
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
let { ariaLabel:
|
|
79
|
-
return /* @__PURE__ */
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
children: t.values.map((e, t) => /* @__PURE__ */ o("span", {
|
|
84
|
-
className: "h-3 w-3 rounded-sm bg-basalt-primary",
|
|
85
|
-
style: { opacity: .2 + Math.min(4, Math.max(0, e)) * .15 }
|
|
86
|
-
}, t))
|
|
78
|
+
let { ariaLabel: t = "Heatmap calendar", className: n } = e;
|
|
79
|
+
return /* @__PURE__ */ u(y, {
|
|
80
|
+
values: e.values,
|
|
81
|
+
ariaLabel: t,
|
|
82
|
+
className: n
|
|
87
83
|
});
|
|
88
84
|
}
|
|
89
|
-
function
|
|
90
|
-
let
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
function y({ values: o, ariaLabel: s, className: f }) {
|
|
86
|
+
let [p, m] = l(0), [h, g] = l(null), _ = c(null), v = c([]), y = c(!1);
|
|
87
|
+
a(() => {
|
|
88
|
+
let e = y.current;
|
|
89
|
+
if (o.length === 0) m(0), g(null), e && _.current?.focus();
|
|
90
|
+
else if (p >= o.length) {
|
|
91
|
+
let t = o.length - 1;
|
|
92
|
+
m(t), e && v.current[t]?.focus();
|
|
93
|
+
} else e && v.current[p]?.focus();
|
|
94
|
+
}, [o.length, p]);
|
|
95
|
+
let b = (e, t) => {
|
|
96
|
+
if (o.length === 0) return;
|
|
97
|
+
if (e.key === "Escape") {
|
|
98
|
+
g(null);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let n = t;
|
|
102
|
+
if (e.key === "ArrowRight") n = Math.min(o.length - 1, t + 1);
|
|
103
|
+
else if (e.key === "ArrowLeft") n = Math.max(0, t - 1);
|
|
104
|
+
else if (e.key === "ArrowDown") n = Math.min(o.length - 1, t + 7);
|
|
105
|
+
else if (e.key === "ArrowUp") n = Math.max(0, t - 7);
|
|
106
|
+
else if (e.key === "Home") n = 0;
|
|
107
|
+
else if (e.key === "End") n = o.length - 1;
|
|
108
|
+
else return;
|
|
109
|
+
e.preventDefault(), m(n), g(n), v.current[n]?.focus();
|
|
110
|
+
};
|
|
111
|
+
return o.length === 0 ? /* @__PURE__ */ u("div", {
|
|
112
|
+
ref: _,
|
|
113
|
+
tabIndex: -1,
|
|
114
|
+
role: "region",
|
|
115
|
+
"aria-label": s,
|
|
116
|
+
onFocus: () => {
|
|
117
|
+
y.current = !0;
|
|
118
|
+
},
|
|
119
|
+
onBlur: (e) => {
|
|
120
|
+
e.currentTarget.contains(e.relatedTarget) || (y.current = !1);
|
|
121
|
+
},
|
|
122
|
+
className: e("grid grid-cols-7 gap-1 p-0.5 outline-none", f)
|
|
123
|
+
}) : /* @__PURE__ */ u(r, { children: /* @__PURE__ */ u("div", {
|
|
124
|
+
ref: _,
|
|
125
|
+
tabIndex: -1,
|
|
126
|
+
role: "region",
|
|
127
|
+
"aria-label": s,
|
|
128
|
+
onFocus: () => {
|
|
129
|
+
y.current = !0;
|
|
130
|
+
},
|
|
131
|
+
onBlur: (e) => {
|
|
132
|
+
e.currentTarget.contains(e.relatedTarget) || (y.current = !1);
|
|
133
|
+
},
|
|
134
|
+
className: e("grid grid-cols-7 gap-1 p-0.5 outline-none", f),
|
|
135
|
+
children: o.map((e, r) => /* @__PURE__ */ d(t, {
|
|
136
|
+
open: h === r,
|
|
137
|
+
onOpenChange: (e) => {
|
|
138
|
+
g(e ? r : (e) => e === r ? v.current[r] !== null && document.activeElement === v.current[r] ? e : null : e);
|
|
139
|
+
},
|
|
140
|
+
children: [/* @__PURE__ */ u(i, {
|
|
141
|
+
asChild: !0,
|
|
142
|
+
children: /* @__PURE__ */ u("button", {
|
|
143
|
+
ref: (e) => {
|
|
144
|
+
v.current[r] = e;
|
|
145
|
+
},
|
|
146
|
+
type: "button",
|
|
147
|
+
tabIndex: r === p ? 0 : -1,
|
|
148
|
+
onFocus: () => {
|
|
149
|
+
m(r), g(r);
|
|
150
|
+
},
|
|
151
|
+
onBlur: () => {
|
|
152
|
+
g((e) => e === r ? null : e);
|
|
153
|
+
},
|
|
154
|
+
onKeyDown: (e) => b(e, r),
|
|
155
|
+
"aria-label": `Position ${r + 1}: ${e}`,
|
|
156
|
+
className: "box-border m-0 h-3 w-3 cursor-pointer rounded-sm border-0 p-0 transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-basalt-ring",
|
|
157
|
+
style: { backgroundColor: `hsl(var(--basalt-chart-5) / ${.2 + Math.min(4, Math.max(0, e)) * .15})` }
|
|
158
|
+
})
|
|
159
|
+
}), /* @__PURE__ */ u(n, { children: /* @__PURE__ */ d("div", {
|
|
160
|
+
className: "text-xs",
|
|
161
|
+
children: [
|
|
162
|
+
"Position ",
|
|
163
|
+
r + 1,
|
|
164
|
+
": ",
|
|
165
|
+
e
|
|
166
|
+
]
|
|
167
|
+
}) })]
|
|
168
|
+
}, r))
|
|
169
|
+
}) });
|
|
170
|
+
}
|
|
171
|
+
function b({ data: f, year: v, colorScale: y, valueFormatter: b, metricLabel: x, cellSize: S, cellGap: C, locale: w, weekdayLabels: T, monthLabels: E, lessLabel: D, moreLabel: O, ariaLabel: k, className: A }) {
|
|
172
|
+
let j = T ?? p(w), M = E ?? m(w), N = o(), P = c(null), { weeks: F, dataMap: I, maxValue: L, labels: R, validDays: z, dateToValidIndex: B } = s(() => {
|
|
173
|
+
let e = h(v), t = /* @__PURE__ */ new Map(), n = 0;
|
|
174
|
+
for (let e of f) t.set(e.date, e.value), e.value > n && (n = e.value);
|
|
93
175
|
let r = [], i = -1;
|
|
94
|
-
|
|
95
|
-
let n = e.find((e) => e.getFullYear() ===
|
|
176
|
+
e.forEach((e, t) => {
|
|
177
|
+
let n = e.find((e) => e.getFullYear() === v);
|
|
96
178
|
if (n) {
|
|
97
179
|
let e = n.getMonth();
|
|
98
180
|
e !== i && (r.push({
|
|
99
|
-
month:
|
|
181
|
+
month: M[e],
|
|
100
182
|
weekIndex: t
|
|
101
183
|
}), i = e);
|
|
102
184
|
}
|
|
185
|
+
});
|
|
186
|
+
let a = [], o = /* @__PURE__ */ new Map();
|
|
187
|
+
return e.forEach((e, r) => {
|
|
188
|
+
e.forEach((e, i) => {
|
|
189
|
+
if (e.getFullYear() === v) {
|
|
190
|
+
let s = g(e), c = t.get(s) ?? 0, l = _(c, n, y);
|
|
191
|
+
o.set(s, a.length), a.push({
|
|
192
|
+
dateStr: s,
|
|
193
|
+
value: c,
|
|
194
|
+
weekIndex: r,
|
|
195
|
+
dayIndex: i,
|
|
196
|
+
colorIndex: l
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
});
|
|
103
200
|
}), {
|
|
104
201
|
weeks: e,
|
|
105
202
|
dataMap: t,
|
|
106
203
|
maxValue: n,
|
|
107
|
-
labels: r
|
|
204
|
+
labels: r,
|
|
205
|
+
validDays: a,
|
|
206
|
+
dateToValidIndex: o
|
|
108
207
|
};
|
|
109
208
|
}, [
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
209
|
+
f,
|
|
210
|
+
M,
|
|
211
|
+
v,
|
|
212
|
+
y
|
|
213
|
+
]), [V, H] = l(() => z[0]?.dateStr ?? `${v}-01-01`), [U, W] = l(null), G = c(/* @__PURE__ */ new Map()), K = c(!1);
|
|
214
|
+
a(() => {
|
|
215
|
+
let e = K.current;
|
|
216
|
+
if (z.length === 0) H(""), W(null), e && P.current?.focus();
|
|
217
|
+
else if (!B.has(V)) {
|
|
218
|
+
let t = z[0]?.dateStr ?? "";
|
|
219
|
+
H(t), e && G.current.get(t)?.focus();
|
|
220
|
+
}
|
|
221
|
+
}, [
|
|
222
|
+
z,
|
|
223
|
+
B,
|
|
224
|
+
V
|
|
113
225
|
]);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
226
|
+
let q = s(() => {
|
|
227
|
+
let e = B.get(V);
|
|
228
|
+
return e === void 0 ? z[0] : z[e];
|
|
229
|
+
}, [
|
|
230
|
+
V,
|
|
231
|
+
B,
|
|
232
|
+
z
|
|
233
|
+
]), J = (e) => {
|
|
234
|
+
e && (H(e.dateStr), W(e.dateStr), G.current.get(e.dateStr)?.focus());
|
|
235
|
+
}, Y = (e, t) => {
|
|
236
|
+
if (z.length === 0) return;
|
|
237
|
+
let n = B.get(t.dateStr) ?? 0;
|
|
238
|
+
if (e.key === "Escape") {
|
|
239
|
+
W(null);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (e.key === "ArrowDown") {
|
|
243
|
+
e.preventDefault();
|
|
244
|
+
let t = z[n + 1];
|
|
245
|
+
t && J(t);
|
|
246
|
+
} else if (e.key === "ArrowUp") {
|
|
247
|
+
e.preventDefault();
|
|
248
|
+
let t = z[n - 1];
|
|
249
|
+
t && J(t);
|
|
250
|
+
} else if (e.key === "ArrowRight") {
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
let t = n + 7;
|
|
253
|
+
t < z.length ? J(z[t]) : J(z[z.length - 1]);
|
|
254
|
+
} else if (e.key === "ArrowLeft") {
|
|
255
|
+
e.preventDefault();
|
|
256
|
+
let t = n - 7;
|
|
257
|
+
J(t >= 0 ? z[t] : z[0]);
|
|
258
|
+
} else e.key === "Home" ? (e.preventDefault(), J(z[0])) : e.key === "End" && (e.preventDefault(), J(z[z.length - 1]));
|
|
259
|
+
};
|
|
260
|
+
return /* @__PURE__ */ u("div", {
|
|
261
|
+
ref: P,
|
|
262
|
+
tabIndex: -1,
|
|
263
|
+
role: "region",
|
|
264
|
+
"aria-label": `${k} scrollable view`,
|
|
265
|
+
onFocus: () => {
|
|
266
|
+
K.current = !0;
|
|
267
|
+
},
|
|
268
|
+
onBlur: (e) => {
|
|
269
|
+
e.currentTarget.contains(e.relatedTarget) || (K.current = !1);
|
|
270
|
+
},
|
|
271
|
+
className: e("overflow-x-auto rounded-md outline-none focus-visible:ring-1 focus-visible:ring-basalt-ring", A),
|
|
272
|
+
children: /* @__PURE__ */ u(r, { children: /* @__PURE__ */ d("div", {
|
|
273
|
+
className: "inline-block p-1",
|
|
274
|
+
role: "group",
|
|
275
|
+
"aria-label": k,
|
|
120
276
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ u("div", {
|
|
122
278
|
className: "relative mb-1 h-4 text-xs text-basalt-muted-foreground",
|
|
123
279
|
style: { marginLeft: 30 },
|
|
124
|
-
children:
|
|
280
|
+
children: R.map((e) => /* @__PURE__ */ u("div", {
|
|
125
281
|
className: "absolute",
|
|
126
|
-
style: { left: e.weekIndex * (
|
|
282
|
+
style: { left: e.weekIndex * (S + C) },
|
|
127
283
|
children: e.month
|
|
128
284
|
}, `${e.month}-${e.weekIndex}`))
|
|
129
285
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ d("div", {
|
|
131
287
|
className: "flex",
|
|
132
|
-
children: [/* @__PURE__ */
|
|
133
|
-
className: "mr-1 flex flex-col text-xs text-basalt-muted-foreground",
|
|
288
|
+
children: [/* @__PURE__ */ u("div", {
|
|
289
|
+
className: "mr-1 flex flex-col text-xs text-basalt-muted-foreground select-none",
|
|
134
290
|
style: { width: 30 },
|
|
135
|
-
|
|
291
|
+
"aria-hidden": "true",
|
|
292
|
+
children: j.map((e, t) => /* @__PURE__ */ u("div", {
|
|
136
293
|
style: {
|
|
137
|
-
height:
|
|
138
|
-
lineHeight: `${
|
|
294
|
+
height: S + C,
|
|
295
|
+
lineHeight: `${S + C}px`,
|
|
139
296
|
visibility: t % 2 == 1 ? "visible" : "hidden"
|
|
140
297
|
},
|
|
141
298
|
children: e
|
|
142
299
|
}, `${e}-${t}`))
|
|
143
|
-
}), /* @__PURE__ */
|
|
300
|
+
}), /* @__PURE__ */ u("div", {
|
|
144
301
|
className: "flex",
|
|
145
|
-
style: { gap:
|
|
146
|
-
children:
|
|
302
|
+
style: { gap: C },
|
|
303
|
+
children: F.map((e, r) => /* @__PURE__ */ u("div", {
|
|
147
304
|
className: "flex flex-col",
|
|
148
|
-
style: { gap:
|
|
149
|
-
children: e.map((e,
|
|
150
|
-
let
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
305
|
+
style: { gap: C },
|
|
306
|
+
children: e.map((e, a) => {
|
|
307
|
+
let o = g(e);
|
|
308
|
+
if (e.getFullYear() !== v) return /* @__PURE__ */ u("div", {
|
|
309
|
+
style: {
|
|
310
|
+
width: S,
|
|
311
|
+
height: S,
|
|
312
|
+
visibility: "hidden"
|
|
313
|
+
},
|
|
314
|
+
"aria-hidden": "true"
|
|
315
|
+
}, a);
|
|
316
|
+
let s = I.get(o) ?? 0, c = _(s, L, y), l = q?.dateStr === o, f = b(s, o), p = `${o}, ${x}: ${f}`, m = U === o, h = {
|
|
317
|
+
dateStr: o,
|
|
318
|
+
value: s,
|
|
319
|
+
weekIndex: r,
|
|
320
|
+
dayIndex: a,
|
|
321
|
+
colorIndex: c
|
|
322
|
+
};
|
|
323
|
+
return /* @__PURE__ */ d(t, {
|
|
324
|
+
open: m,
|
|
325
|
+
onOpenChange: (e) => {
|
|
326
|
+
W(e ? o : (e) => e === o ? document.activeElement === G.current.get(o) ? e : null : e);
|
|
327
|
+
},
|
|
328
|
+
children: [/* @__PURE__ */ u(i, {
|
|
329
|
+
asChild: !0,
|
|
330
|
+
children: /* @__PURE__ */ u("button", {
|
|
331
|
+
ref: (e) => {
|
|
332
|
+
e ? G.current.set(o, e) : G.current.delete(o);
|
|
333
|
+
},
|
|
334
|
+
type: "button",
|
|
335
|
+
"aria-label": p,
|
|
336
|
+
tabIndex: l ? 0 : -1,
|
|
337
|
+
onFocus: () => {
|
|
338
|
+
H(o), W(o);
|
|
339
|
+
},
|
|
340
|
+
onBlur: () => {
|
|
341
|
+
W((e) => e === o ? null : e);
|
|
342
|
+
},
|
|
343
|
+
onKeyDown: (e) => Y(e, h),
|
|
344
|
+
className: "box-border m-0 cursor-pointer rounded-sm border-0 p-0 transition-colors hover:ring-1 hover:ring-basalt-foreground focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-basalt-ring",
|
|
345
|
+
style: {
|
|
346
|
+
width: S,
|
|
347
|
+
height: S,
|
|
348
|
+
backgroundColor: y[c]
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
}), /* @__PURE__ */ u(n, {
|
|
352
|
+
id: `${N}-${o}`,
|
|
353
|
+
children: /* @__PURE__ */ d("div", {
|
|
354
|
+
className: "text-sm",
|
|
355
|
+
children: [/* @__PURE__ */ u("div", {
|
|
356
|
+
className: "font-medium",
|
|
357
|
+
children: o
|
|
358
|
+
}), /* @__PURE__ */ d("div", {
|
|
359
|
+
className: "text-basalt-muted-foreground",
|
|
360
|
+
children: [
|
|
361
|
+
x,
|
|
362
|
+
": ",
|
|
363
|
+
f
|
|
364
|
+
]
|
|
365
|
+
})]
|
|
366
|
+
})
|
|
173
367
|
})]
|
|
174
|
-
}
|
|
175
|
-
width: v,
|
|
176
|
-
height: v,
|
|
177
|
-
visibility: "hidden"
|
|
178
|
-
} }, r);
|
|
368
|
+
}, a);
|
|
179
369
|
})
|
|
180
370
|
}, r))
|
|
181
371
|
})]
|
|
182
372
|
}),
|
|
183
|
-
/* @__PURE__ */
|
|
184
|
-
className: "mt-2 flex items-center justify-end gap-1 text-xs text-basalt-muted-foreground",
|
|
373
|
+
/* @__PURE__ */ d("div", {
|
|
374
|
+
className: "mt-2 flex items-center justify-end gap-1 text-xs text-basalt-muted-foreground select-none",
|
|
375
|
+
"aria-hidden": "true",
|
|
185
376
|
children: [
|
|
186
|
-
/* @__PURE__ */
|
|
187
|
-
|
|
377
|
+
/* @__PURE__ */ u("span", { children: D }),
|
|
378
|
+
y.map((e) => /* @__PURE__ */ u("div", {
|
|
188
379
|
className: "rounded-sm",
|
|
189
380
|
style: {
|
|
190
|
-
width:
|
|
191
|
-
height:
|
|
381
|
+
width: S,
|
|
382
|
+
height: S,
|
|
192
383
|
backgroundColor: e
|
|
193
384
|
}
|
|
194
385
|
}, e)),
|
|
195
|
-
/* @__PURE__ */
|
|
386
|
+
/* @__PURE__ */ u("span", { children: O })
|
|
196
387
|
]
|
|
197
388
|
})
|
|
198
389
|
]
|
|
@@ -200,6 +391,6 @@ function h({ data: c, year: m, colorScale: h, valueFormatter: g, metricLabel: _,
|
|
|
200
391
|
});
|
|
201
392
|
}
|
|
202
393
|
//#endregion
|
|
203
|
-
export {
|
|
394
|
+
export { v as HeatmapCalendar, f as heatmapColorScales };
|
|
204
395
|
|
|
205
396
|
//# sourceMappingURL=heatmap-calendar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heatmap-calendar.js","names":[],"sources":["../../src/charts/heatmap-calendar.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../components/tooltip\";\nimport { cn } from \"../utils/cn\";\n\nexport type HeatmapDataPoint = { date: string; value: number };\n\nexport const heatmapColorScales = {\n\tgreen: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-green-1))\",\n\t\t\"hsl(var(--basalt-heatmap-green-2))\",\n\t\t\"hsl(var(--basalt-heatmap-green-3))\",\n\t\t\"hsl(var(--basalt-heatmap-green-4))\",\n\t],\n\tred: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-red-1))\",\n\t\t\"hsl(var(--basalt-heatmap-red-2))\",\n\t\t\"hsl(var(--basalt-heatmap-red-3))\",\n\t\t\"hsl(var(--basalt-heatmap-red-4))\",\n\t],\n\tblue: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-1))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-2))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-3))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-4))\",\n\t],\n\torange: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-1))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-2))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-3))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-4))\",\n\t],\n} as const;\n\nfunction weekdayNames(locale: string) {\n\treturn Array.from({ length: 7 }, (_, index) =>\n\t\tnew Intl.DateTimeFormat(locale, { weekday: \"short\" }).format(new Date(2023, 0, 1 + index)),\n\t);\n}\n\nfunction monthNames(locale: string) {\n\treturn Array.from({ length: 12 }, (_, index) =>\n\t\tnew Intl.DateTimeFormat(locale, { month: \"short\" }).format(new Date(2023, index, 1)),\n\t);\n}\n\nfunction getYearWeeks(year: number): Date[][] {\n\tconst weeks: Date[][] = [];\n\tconst startDate = new Date(year, 0, 1);\n\tconst endDate = new Date(year, 11, 31);\n\tconst firstDay = new Date(startDate);\n\tfirstDay.setDate(firstDay.getDate() - firstDay.getDay());\n\tlet currentDate = new Date(firstDay);\n\tlet currentWeek: Date[] = [];\n\twhile (currentDate <= endDate || currentWeek.length > 0) {\n\t\tif (currentWeek.length === 7) {\n\t\t\tweeks.push(currentWeek);\n\t\t\tcurrentWeek = [];\n\t\t}\n\t\tif (currentDate > endDate) {\n\t\t\tbreak;\n\t\t}\n\t\tcurrentWeek.push(new Date(currentDate));\n\t\tcurrentDate = new Date(currentDate);\n\t\tcurrentDate.setDate(currentDate.getDate() + 1);\n\t}\n\tif (currentWeek.length > 0) {\n\t\tweeks.push(currentWeek);\n\t}\n\treturn weeks;\n}\n\nfunction formatDate(date: Date): string {\n\tconst year = date.getFullYear();\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${year}-${month}-${day}`;\n}\n\nfunction getColorIndex(value: number, maxValue: number, colorScale: readonly string[]): number {\n\tif (value === 0) {\n\t\treturn 0;\n\t}\n\tconst levels = colorScale.length - 1;\n\tconst normalized = Math.min(value / maxValue, 1);\n\treturn Math.ceil(normalized * levels);\n}\n\nexport type HeatmapCalendarValuesProps = {\n\tvalues: number[];\n\tariaLabel?: string;\n\tclassName?: string;\n};\n\nexport type HeatmapCalendarYearProps = {\n\tdata: HeatmapDataPoint[];\n\tyear: number;\n\tcolorScale?: readonly string[];\n\tvalueFormatter?: (value: number, date: string) => string;\n\tmetricLabel?: string;\n\tcellSize?: number;\n\tcellGap?: number;\n\tlocale?: string;\n\tweekdayLabels?: string[];\n\tmonthLabels?: string[];\n\tlessLabel?: string;\n\tmoreLabel?: string;\n\tariaLabel?: string;\n\tclassName?: string;\n};\n\nexport type HeatmapCalendarProps = HeatmapCalendarValuesProps | HeatmapCalendarYearProps;\n\nexport function HeatmapCalendar(props: HeatmapCalendarProps) {\n\tif (\"data\" in props) {\n\t\tconst {\n\t\t\tcolorScale = heatmapColorScales.green,\n\t\t\tvalueFormatter = (value) => value.toLocaleString(),\n\t\t\tmetricLabel = \"Value\",\n\t\t\tcellSize = 12,\n\t\t\tcellGap = 2,\n\t\t\tlocale = \"en-US\",\n\t\t\tweekdayLabels,\n\t\t\tmonthLabels,\n\t\t\tlessLabel = \"Less\",\n\t\t\tmoreLabel = \"More\",\n\t\t\tariaLabel = \"Heatmap calendar\",\n\t\t\tclassName,\n\t\t} = props;\n\t\treturn (\n\t\t\t<YearHeatmap\n\t\t\t\tdata={props.data}\n\t\t\t\tyear={props.year}\n\t\t\t\tcolorScale={colorScale}\n\t\t\t\tvalueFormatter={valueFormatter}\n\t\t\t\tmetricLabel={metricLabel}\n\t\t\t\tcellSize={cellSize}\n\t\t\t\tcellGap={cellGap}\n\t\t\t\tlocale={locale}\n\t\t\t\tweekdayLabels={weekdayLabels}\n\t\t\t\tmonthLabels={monthLabels}\n\t\t\t\tlessLabel={lessLabel}\n\t\t\t\tmoreLabel={moreLabel}\n\t\t\t\tariaLabel={ariaLabel}\n\t\t\t\tclassName={className}\n\t\t\t/>\n\t\t);\n\t}\n\tconst { ariaLabel = \"Heatmap calendar\", className } = props;\n\treturn (\n\t\t<div className={cn(\"grid grid-cols-7 gap-1\", className)} role=\"img\" aria-label={ariaLabel}>\n\t\t\t{props.values.map((value, index) => (\n\t\t\t\t<span\n\t\t\t\t\tkey={index}\n\t\t\t\t\tclassName=\"h-3 w-3 rounded-sm bg-basalt-primary\"\n\t\t\t\t\tstyle={{ opacity: 0.2 + Math.min(4, Math.max(0, value)) * 0.15 }}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\nfunction YearHeatmap({\n\tdata,\n\tyear,\n\tcolorScale,\n\tvalueFormatter,\n\tmetricLabel,\n\tcellSize,\n\tcellGap,\n\tlocale,\n\tweekdayLabels,\n\tmonthLabels,\n\tlessLabel,\n\tmoreLabel,\n\tariaLabel,\n\tclassName,\n}: {\n\tdata: HeatmapDataPoint[];\n\tyear: number;\n\tcolorScale: readonly string[];\n\tvalueFormatter: (value: number, date: string) => string;\n\tmetricLabel: string;\n\tcellSize: number;\n\tcellGap: number;\n\tlocale: string;\n\tweekdayLabels?: string[];\n\tmonthLabels?: string[];\n\tlessLabel: string;\n\tmoreLabel: string;\n\tariaLabel: string;\n\tclassName?: string;\n}) {\n\tconst weekdays = weekdayLabels ?? weekdayNames(locale);\n\tconst months = monthLabels ?? monthNames(locale);\n\tconst { weeks, dataMap, maxValue, labels } = useMemo(() => {\n\t\tconst weeks = getYearWeeks(year);\n\t\tconst dataMap = new Map<string, number>();\n\t\tlet maxValue = 0;\n\t\tfor (const point of data) {\n\t\t\tdataMap.set(point.date, point.value);\n\t\t\tif (point.value > maxValue) {\n\t\t\t\tmaxValue = point.value;\n\t\t\t}\n\t\t}\n\t\tconst labels: { month: string; weekIndex: number }[] = [];\n\t\tlet lastMonth = -1;\n\t\tweeks.forEach((week, weekIndex) => {\n\t\t\tconst firstDayOfWeek = week.find((date) => date.getFullYear() === year);\n\t\t\tif (firstDayOfWeek) {\n\t\t\t\tconst month = firstDayOfWeek.getMonth();\n\t\t\t\tif (month !== lastMonth) {\n\t\t\t\t\tlabels.push({ month: months[month], weekIndex });\n\t\t\t\t\tlastMonth = month;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { weeks, dataMap, maxValue, labels };\n\t}, [data, months, year]);\n\tconst labelWidth = 30;\n\treturn (\n\t\t<div className={cn(\"overflow-x-auto\", className)} role=\"img\" aria-label={ariaLabel}>\n\t\t\t<TooltipProvider>\n\t\t\t\t<div className=\"inline-block\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"relative mb-1 h-4 text-xs text-basalt-muted-foreground\"\n\t\t\t\t\t\tstyle={{ marginLeft: labelWidth }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{labels.map((label) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={`${label.month}-${label.weekIndex}`}\n\t\t\t\t\t\t\t\tclassName=\"absolute\"\n\t\t\t\t\t\t\t\tstyle={{ left: label.weekIndex * (cellSize + cellGap) }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{label.month}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"mr-1 flex flex-col text-xs text-basalt-muted-foreground\"\n\t\t\t\t\t\t\tstyle={{ width: labelWidth }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{weekdays.map((day, index) => (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={`${day}-${index}`}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\theight: cellSize + cellGap,\n\t\t\t\t\t\t\t\t\t\tlineHeight: `${cellSize + cellGap}px`,\n\t\t\t\t\t\t\t\t\t\tvisibility: index % 2 === 1 ? \"visible\" : \"hidden\",\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{day}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex\" style={{ gap: cellGap }}>\n\t\t\t\t\t\t\t{weeks.map((week, weekIndex) => (\n\t\t\t\t\t\t\t\t<div key={weekIndex} className=\"flex flex-col\" style={{ gap: cellGap }}>\n\t\t\t\t\t\t\t\t\t{week.map((date, dayIndex) => {\n\t\t\t\t\t\t\t\t\t\tconst dateStr = formatDate(date);\n\t\t\t\t\t\t\t\t\t\tconst value = dataMap.get(dateStr) ?? 0;\n\t\t\t\t\t\t\t\t\t\tconst isCurrentYear = date.getFullYear() === year;\n\t\t\t\t\t\t\t\t\t\tconst colorIndex = getColorIndex(value, maxValue, colorScale);\n\t\t\t\t\t\t\t\t\t\tif (!isCurrentYear) {\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={dayIndex}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvisibility: \"hidden\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<Tooltip key={dayIndex}>\n\t\t\t\t\t\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"cursor-pointer rounded-sm transition-colors hover:ring-1 hover:ring-basalt-foreground\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: colorScale[colorIndex],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"text-sm\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"font-medium\">{dateStr}</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{metricLabel}: {valueFormatter(value, dateStr)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"mt-2 flex items-center justify-end gap-1 text-xs text-basalt-muted-foreground\">\n\t\t\t\t\t\t<span>{lessLabel}</span>\n\t\t\t\t\t\t{colorScale.map((color) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={color}\n\t\t\t\t\t\t\t\tclassName=\"rounded-sm\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\tbackgroundColor: color,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<span>{moreLabel}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</TooltipProvider>\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"heatmap-calendar.js","names":[],"sources":["../../src/charts/heatmap-calendar.tsx"],"sourcesContent":["import { type KeyboardEvent, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../components/tooltip\";\nimport { cn } from \"../utils/cn\";\n\nexport type HeatmapDataPoint = { date: string; value: number };\n\nexport const heatmapColorScales = {\n\tgreen: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-green-1))\",\n\t\t\"hsl(var(--basalt-heatmap-green-2))\",\n\t\t\"hsl(var(--basalt-heatmap-green-3))\",\n\t\t\"hsl(var(--basalt-heatmap-green-4))\",\n\t],\n\tred: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-red-1))\",\n\t\t\"hsl(var(--basalt-heatmap-red-2))\",\n\t\t\"hsl(var(--basalt-heatmap-red-3))\",\n\t\t\"hsl(var(--basalt-heatmap-red-4))\",\n\t],\n\tblue: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-1))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-2))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-3))\",\n\t\t\"hsl(var(--basalt-heatmap-blue-4))\",\n\t],\n\torange: [\n\t\t\"hsl(var(--basalt-muted))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-1))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-2))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-3))\",\n\t\t\"hsl(var(--basalt-heatmap-orange-4))\",\n\t],\n} as const;\n\nfunction weekdayNames(locale: string) {\n\treturn Array.from({ length: 7 }, (_, index) =>\n\t\tnew Intl.DateTimeFormat(locale, { weekday: \"short\" }).format(new Date(2023, 0, 1 + index)),\n\t);\n}\n\nfunction monthNames(locale: string) {\n\treturn Array.from({ length: 12 }, (_, index) =>\n\t\tnew Intl.DateTimeFormat(locale, { month: \"short\" }).format(new Date(2023, index, 1)),\n\t);\n}\n\nfunction getYearWeeks(year: number): Date[][] {\n\tconst weeks: Date[][] = [];\n\tconst startDate = new Date(year, 0, 1);\n\tconst endDate = new Date(year, 11, 31);\n\tconst firstDay = new Date(startDate);\n\tfirstDay.setDate(firstDay.getDate() - firstDay.getDay());\n\tlet currentDate = new Date(firstDay);\n\tlet currentWeek: Date[] = [];\n\twhile (currentDate <= endDate || currentWeek.length > 0) {\n\t\tif (currentWeek.length === 7) {\n\t\t\tweeks.push(currentWeek);\n\t\t\tcurrentWeek = [];\n\t\t}\n\t\tif (currentDate > endDate) {\n\t\t\tbreak;\n\t\t}\n\t\tcurrentWeek.push(new Date(currentDate));\n\t\tcurrentDate = new Date(currentDate);\n\t\tcurrentDate.setDate(currentDate.getDate() + 1);\n\t}\n\tif (currentWeek.length > 0) {\n\t\tweeks.push(currentWeek);\n\t}\n\treturn weeks;\n}\n\nfunction formatDate(date: Date): string {\n\tconst year = date.getFullYear();\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${year}-${month}-${day}`;\n}\n\nfunction getColorIndex(value: number, maxValue: number, colorScale: readonly string[]): number {\n\tif (value === 0) {\n\t\treturn 0;\n\t}\n\tconst levels = colorScale.length - 1;\n\tconst normalized = Math.min(value / maxValue, 1);\n\treturn Math.ceil(normalized * levels);\n}\n\nexport type HeatmapCalendarValuesProps = {\n\t/**\n\t * Numeric values sequence to display in a compact 7-column grid.\n\t */\n\tvalues: number[];\n\t/**\n\t * Accessible name describing the heatmap purpose or data.\n\t * @default \"Heatmap calendar\"\n\t */\n\tariaLabel?: string;\n\t/**\n\t * Additional CSS class names for the outer container.\n\t */\n\tclassName?: string;\n};\n\nexport type HeatmapCalendarYearProps = {\n\t/**\n\t * Dataset of daily metrics with ISO date strings (\"YYYY-MM-DD\") and numeric values.\n\t */\n\tdata: HeatmapDataPoint[];\n\t/**\n\t * Calendar year to render.\n\t */\n\tyear: number;\n\t/**\n\t * Array of color values forming the intensity gradient from lowest to highest.\n\t * @default heatmapColorScales.green\n\t */\n\tcolorScale?: readonly string[];\n\t/**\n\t * Formatter for tooltip value display and accessible label.\n\t * @default (value) => value.toLocaleString()\n\t */\n\tvalueFormatter?: (value: number, date: string) => string;\n\t/**\n\t * Name of the metric for accessible labeling and tooltips.\n\t * @default \"Value\"\n\t */\n\tmetricLabel?: string;\n\t/**\n\t * Pixel width and height of each day cell.\n\t * @default 12\n\t */\n\tcellSize?: number;\n\t/**\n\t * Pixel gap between adjacent cells.\n\t * @default 2\n\t */\n\tcellGap?: number;\n\t/**\n\t * BCP 47 locale tag used for weekday and month label formatting.\n\t * @default \"en-US\"\n\t */\n\tlocale?: string;\n\t/**\n\t * Explicit custom weekday labels override.\n\t */\n\tweekdayLabels?: string[];\n\t/**\n\t * Explicit custom month labels override.\n\t */\n\tmonthLabels?: string[];\n\t/**\n\t * Label text for the lower end of the color scale legend.\n\t * @default \"Less\"\n\t */\n\tlessLabel?: string;\n\t/**\n\t * Label text for the upper end of the color scale legend.\n\t * @default \"More\"\n\t */\n\tmoreLabel?: string;\n\t/**\n\t * Accessible name describing the yearly heatmap dataset.\n\t * @default \"Heatmap calendar\"\n\t */\n\tariaLabel?: string;\n\t/**\n\t * Additional CSS class names for the outer scrollable container.\n\t */\n\tclassName?: string;\n};\n\nexport type HeatmapCalendarProps = HeatmapCalendarValuesProps | HeatmapCalendarYearProps;\n\nexport function HeatmapCalendar(props: HeatmapCalendarProps) {\n\tif (\"data\" in props) {\n\t\tconst {\n\t\t\tcolorScale = heatmapColorScales.green,\n\t\t\tvalueFormatter = (value) => value.toLocaleString(),\n\t\t\tmetricLabel = \"Value\",\n\t\t\tcellSize = 12,\n\t\t\tcellGap = 2,\n\t\t\tlocale = \"en-US\",\n\t\t\tweekdayLabels,\n\t\t\tmonthLabels,\n\t\t\tlessLabel = \"Less\",\n\t\t\tmoreLabel = \"More\",\n\t\t\tariaLabel = \"Heatmap calendar\",\n\t\t\tclassName,\n\t\t} = props;\n\t\treturn (\n\t\t\t<YearHeatmap\n\t\t\t\tdata={props.data}\n\t\t\t\tyear={props.year}\n\t\t\t\tcolorScale={colorScale}\n\t\t\t\tvalueFormatter={valueFormatter}\n\t\t\t\tmetricLabel={metricLabel}\n\t\t\t\tcellSize={cellSize}\n\t\t\t\tcellGap={cellGap}\n\t\t\t\tlocale={locale}\n\t\t\t\tweekdayLabels={weekdayLabels}\n\t\t\t\tmonthLabels={monthLabels}\n\t\t\t\tlessLabel={lessLabel}\n\t\t\t\tmoreLabel={moreLabel}\n\t\t\t\tariaLabel={ariaLabel}\n\t\t\t\tclassName={className}\n\t\t\t/>\n\t\t);\n\t}\n\tconst { ariaLabel = \"Heatmap calendar\", className } = props;\n\treturn <ValuesHeatmap values={props.values} ariaLabel={ariaLabel} className={className} />;\n}\n\nfunction ValuesHeatmap({\n\tvalues,\n\tariaLabel,\n\tclassName,\n}: {\n\tvalues: number[];\n\tariaLabel: string;\n\tclassName?: string;\n}) {\n\tconst [activeIdx, setActiveIdx] = useState(0);\n\tconst [openTooltipIdx, setOpenTooltipIdx] = useState<number | null>(null);\n\tconst containerRef = useRef<HTMLDivElement | null>(null);\n\tconst cellRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\tconst isFocusedInsideRef = useRef(false);\n\n\t// When values array shrinks, empties, or restores: if an item or container currently held focus,\n\t// restore focus to the new valid index or empty container without stealing focus from outside.\n\tuseEffect(() => {\n\t\tconst hadFocus = isFocusedInsideRef.current;\n\t\tif (values.length === 0) {\n\t\t\tsetActiveIdx(0);\n\t\t\tsetOpenTooltipIdx(null);\n\t\t\tif (hadFocus) {\n\t\t\t\tcontainerRef.current?.focus();\n\t\t\t}\n\t\t} else if (activeIdx >= values.length) {\n\t\t\tconst next = values.length - 1;\n\t\t\tsetActiveIdx(next);\n\t\t\tif (hadFocus) {\n\t\t\t\tcellRefs.current[next]?.focus();\n\t\t\t}\n\t\t} else if (hadFocus) {\n\t\t\tcellRefs.current[activeIdx]?.focus();\n\t\t}\n\t}, [values.length, activeIdx]);\n\n\tconst handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>, currentIndex: number) => {\n\t\tif (values.length === 0) return;\n\n\t\tif (e.key === \"Escape\") {\n\t\t\tsetOpenTooltipIdx(null);\n\t\t\treturn;\n\t\t}\n\n\t\tlet nextIdx = currentIndex;\n\t\tif (e.key === \"ArrowRight\") {\n\t\t\tnextIdx = Math.min(values.length - 1, currentIndex + 1);\n\t\t} else if (e.key === \"ArrowLeft\") {\n\t\t\tnextIdx = Math.max(0, currentIndex - 1);\n\t\t} else if (e.key === \"ArrowDown\") {\n\t\t\tnextIdx = Math.min(values.length - 1, currentIndex + 7);\n\t\t} else if (e.key === \"ArrowUp\") {\n\t\t\tnextIdx = Math.max(0, currentIndex - 7);\n\t\t} else if (e.key === \"Home\") {\n\t\t\tnextIdx = 0;\n\t\t} else if (e.key === \"End\") {\n\t\t\tnextIdx = values.length - 1;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\t\tsetActiveIdx(nextIdx);\n\t\tsetOpenTooltipIdx(nextIdx);\n\t\tcellRefs.current[nextIdx]?.focus();\n\t};\n\n\tif (values.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={containerRef}\n\t\t\t\ttabIndex={-1}\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\tonFocus={() => {\n\t\t\t\t\tisFocusedInsideRef.current = true;\n\t\t\t\t}}\n\t\t\t\tonBlur={(e) => {\n\t\t\t\t\tif (!e.currentTarget.contains(e.relatedTarget)) {\n\t\t\t\t\t\tisFocusedInsideRef.current = false;\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\"grid grid-cols-7 gap-1 p-0.5 outline-none\", className)}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<TooltipProvider>\n\t\t\t<div\n\t\t\t\tref={containerRef}\n\t\t\t\ttabIndex={-1}\n\t\t\t\trole=\"region\"\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\tonFocus={() => {\n\t\t\t\t\tisFocusedInsideRef.current = true;\n\t\t\t\t}}\n\t\t\t\tonBlur={(e) => {\n\t\t\t\t\tif (!e.currentTarget.contains(e.relatedTarget)) {\n\t\t\t\t\t\tisFocusedInsideRef.current = false;\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\"grid grid-cols-7 gap-1 p-0.5 outline-none\", className)}\n\t\t\t>\n\t\t\t\t{values.map((value, index) => {\n\t\t\t\t\tconst isCurrent = index === activeIdx;\n\t\t\t\t\tconst isOpen = openTooltipIdx === index;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Tooltip\n\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\topen={isOpen}\n\t\t\t\t\t\t\tonOpenChange={(next) => {\n\t\t\t\t\t\t\t\tif (next) {\n\t\t\t\t\t\t\t\t\tsetOpenTooltipIdx(index);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tsetOpenTooltipIdx((curr) => {\n\t\t\t\t\t\t\t\t\t\tif (curr !== index) return curr;\n\t\t\t\t\t\t\t\t\t\t// If this cell currently holds document focus, ignore scroll dismiss\n\t\t\t\t\t\t\t\t\t\tconst isCellFocused =\n\t\t\t\t\t\t\t\t\t\t\tcellRefs.current[index] !== null &&\n\t\t\t\t\t\t\t\t\t\t\tdocument.activeElement === cellRefs.current[index];\n\t\t\t\t\t\t\t\t\t\treturn isCellFocused ? curr : null;\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tref={(el) => {\n\t\t\t\t\t\t\t\t\t\tcellRefs.current[index] = el;\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\ttabIndex={isCurrent ? 0 : -1}\n\t\t\t\t\t\t\t\t\tonFocus={() => {\n\t\t\t\t\t\t\t\t\t\tsetActiveIdx(index);\n\t\t\t\t\t\t\t\t\t\tsetOpenTooltipIdx(index);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tonBlur={() => {\n\t\t\t\t\t\t\t\t\t\tsetOpenTooltipIdx((curr) => (curr === index ? null : curr));\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tonKeyDown={(e) => handleKeyDown(e, index)}\n\t\t\t\t\t\t\t\t\taria-label={`Position ${index + 1}: ${value}`}\n\t\t\t\t\t\t\t\t\tclassName=\"box-border m-0 h-3 w-3 cursor-pointer rounded-sm border-0 p-0 transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-basalt-ring\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tbackgroundColor: `hsl(var(--basalt-chart-5) / ${0.2 + Math.min(4, Math.max(0, value)) * 0.15})`,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t<div className=\"text-xs\">\n\t\t\t\t\t\t\t\t\tPosition {index + 1}: {value}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</TooltipProvider>\n\t);\n}\n\ninterface YearDayCell {\n\tdateStr: string;\n\tvalue: number;\n\tweekIndex: number;\n\tdayIndex: number;\n\tcolorIndex: number;\n}\n\nfunction YearHeatmap({\n\tdata,\n\tyear,\n\tcolorScale,\n\tvalueFormatter,\n\tmetricLabel,\n\tcellSize,\n\tcellGap,\n\tlocale,\n\tweekdayLabels,\n\tmonthLabels,\n\tlessLabel,\n\tmoreLabel,\n\tariaLabel,\n\tclassName,\n}: {\n\tdata: HeatmapDataPoint[];\n\tyear: number;\n\tcolorScale: readonly string[];\n\tvalueFormatter: (value: number, date: string) => string;\n\tmetricLabel: string;\n\tcellSize: number;\n\tcellGap: number;\n\tlocale: string;\n\tweekdayLabels?: string[];\n\tmonthLabels?: string[];\n\tlessLabel: string;\n\tmoreLabel: string;\n\tariaLabel: string;\n\tclassName?: string;\n}) {\n\tconst weekdays = weekdayLabels ?? weekdayNames(locale);\n\tconst months = monthLabels ?? monthNames(locale);\n\tconst calendarId = useId();\n\tconst scrollRegionRef = useRef<HTMLDivElement | null>(null);\n\n\tconst { weeks, dataMap, maxValue, labels, validDays, dateToValidIndex } = useMemo(() => {\n\t\tconst weeks = getYearWeeks(year);\n\t\tconst dataMap = new Map<string, number>();\n\t\tlet maxValue = 0;\n\t\tfor (const point of data) {\n\t\t\tdataMap.set(point.date, point.value);\n\t\t\tif (point.value > maxValue) {\n\t\t\t\tmaxValue = point.value;\n\t\t\t}\n\t\t}\n\n\t\tconst labels: { month: string; weekIndex: number }[] = [];\n\t\tlet lastMonth = -1;\n\t\tweeks.forEach((week, weekIndex) => {\n\t\t\tconst firstDayOfWeek = week.find((date) => date.getFullYear() === year);\n\t\t\tif (firstDayOfWeek) {\n\t\t\t\tconst month = firstDayOfWeek.getMonth();\n\t\t\t\tif (month !== lastMonth) {\n\t\t\t\t\tlabels.push({ month: months[month], weekIndex });\n\t\t\t\t\tlastMonth = month;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst validDays: YearDayCell[] = [];\n\t\tconst dateToValidIndex = new Map<string, number>();\n\n\t\tweeks.forEach((week, weekIndex) => {\n\t\t\tweek.forEach((date, dayIndex) => {\n\t\t\t\tif (date.getFullYear() === year) {\n\t\t\t\t\tconst dateStr = formatDate(date);\n\t\t\t\t\tconst value = dataMap.get(dateStr) ?? 0;\n\t\t\t\t\tconst colorIndex = getColorIndex(value, maxValue, colorScale);\n\t\t\t\t\tdateToValidIndex.set(dateStr, validDays.length);\n\t\t\t\t\tvalidDays.push({\n\t\t\t\t\t\tdateStr,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tweekIndex,\n\t\t\t\t\t\tdayIndex,\n\t\t\t\t\t\tcolorIndex,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn { weeks, dataMap, maxValue, labels, validDays, dateToValidIndex };\n\t}, [data, months, year, colorScale]);\n\n\tconst [activeDate, setActiveDate] = useState<string>(() => {\n\t\treturn validDays[0]?.dateStr ?? `${year}-01-01`;\n\t});\n\tconst [openTooltipDate, setOpenTooltipDate] = useState<string | null>(null);\n\n\tconst cellRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n\tconst isYearFocusedInsideRef = useRef(false);\n\n\t// If year or validDays change: if a cell held focus, restore focus to the clamped\n\t// active date or scroll container; if focus was outside, do NOT steal focus.\n\tuseEffect(() => {\n\t\tconst hadFocus = isYearFocusedInsideRef.current;\n\t\tif (validDays.length === 0) {\n\t\t\tsetActiveDate(\"\");\n\t\t\tsetOpenTooltipDate(null);\n\t\t\tif (hadFocus) {\n\t\t\t\tscrollRegionRef.current?.focus();\n\t\t\t}\n\t\t} else if (!dateToValidIndex.has(activeDate)) {\n\t\t\tconst nextDate = validDays[0]?.dateStr ?? \"\";\n\t\t\tsetActiveDate(nextDate);\n\t\t\tif (hadFocus) {\n\t\t\t\tcellRefs.current.get(nextDate)?.focus();\n\t\t\t}\n\t\t}\n\t}, [validDays, dateToValidIndex, activeDate]);\n\n\tconst activeDay = useMemo(() => {\n\t\tconst idx = dateToValidIndex.get(activeDate);\n\t\treturn idx !== undefined ? validDays[idx] : validDays[0];\n\t}, [activeDate, dateToValidIndex, validDays]);\n\n\tconst navigateToDay = (targetDay: YearDayCell | undefined) => {\n\t\tif (!targetDay) return;\n\t\tsetActiveDate(targetDay.dateStr);\n\t\tsetOpenTooltipDate(targetDay.dateStr);\n\t\tconst btn = cellRefs.current.get(targetDay.dateStr);\n\t\tbtn?.focus();\n\t};\n\n\tconst handleCellKeyDown = (e: KeyboardEvent<HTMLButtonElement>, cell: YearDayCell) => {\n\t\tif (validDays.length === 0) return;\n\n\t\tconst currentIdx = dateToValidIndex.get(cell.dateStr) ?? 0;\n\n\t\tif (e.key === \"Escape\") {\n\t\t\tsetOpenTooltipDate(null);\n\t\t\treturn;\n\t\t}\n\n\t\tif (e.key === \"ArrowDown\") {\n\t\t\te.preventDefault();\n\t\t\t// Visually next day (down in the column)\n\t\t\tconst nextDay = validDays[currentIdx + 1];\n\t\t\tif (nextDay) {\n\t\t\t\tnavigateToDay(nextDay);\n\t\t\t}\n\t\t} else if (e.key === \"ArrowUp\") {\n\t\t\te.preventDefault();\n\t\t\t// Visually previous day (up in the column)\n\t\t\tconst prevDay = validDays[currentIdx - 1];\n\t\t\tif (prevDay) {\n\t\t\t\tnavigateToDay(prevDay);\n\t\t\t}\n\t\t} else if (e.key === \"ArrowRight\") {\n\t\t\te.preventDefault();\n\t\t\t// Visually next week (right in the row: +7 days by index)\n\t\t\tconst targetIdx = currentIdx + 7;\n\t\t\tif (targetIdx < validDays.length) {\n\t\t\t\tnavigateToDay(validDays[targetIdx]);\n\t\t\t} else {\n\t\t\t\tnavigateToDay(validDays[validDays.length - 1]);\n\t\t\t}\n\t\t} else if (e.key === \"ArrowLeft\") {\n\t\t\te.preventDefault();\n\t\t\t// Visually previous week (left in the row: -7 days by index)\n\t\t\tconst targetIdx = currentIdx - 7;\n\t\t\tif (targetIdx >= 0) {\n\t\t\t\tnavigateToDay(validDays[targetIdx]);\n\t\t\t} else {\n\t\t\t\tnavigateToDay(validDays[0]);\n\t\t\t}\n\t\t} else if (e.key === \"Home\") {\n\t\t\te.preventDefault();\n\t\t\tnavigateToDay(validDays[0]);\n\t\t} else if (e.key === \"End\") {\n\t\t\te.preventDefault();\n\t\t\tnavigateToDay(validDays[validDays.length - 1]);\n\t\t}\n\t};\n\n\tconst labelWidth = 30;\n\n\treturn (\n\t\t<div\n\t\t\tref={scrollRegionRef}\n\t\t\ttabIndex={-1}\n\t\t\trole=\"region\"\n\t\t\taria-label={`${ariaLabel} scrollable view`}\n\t\t\tonFocus={() => {\n\t\t\t\tisYearFocusedInsideRef.current = true;\n\t\t\t}}\n\t\t\tonBlur={(e) => {\n\t\t\t\tif (!e.currentTarget.contains(e.relatedTarget)) {\n\t\t\t\t\tisYearFocusedInsideRef.current = false;\n\t\t\t\t}\n\t\t\t}}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-x-auto rounded-md outline-none focus-visible:ring-1 focus-visible:ring-basalt-ring\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<TooltipProvider>\n\t\t\t\t<div className=\"inline-block p-1\" role=\"group\" aria-label={ariaLabel}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"relative mb-1 h-4 text-xs text-basalt-muted-foreground\"\n\t\t\t\t\t\tstyle={{ marginLeft: labelWidth }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{labels.map((label) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={`${label.month}-${label.weekIndex}`}\n\t\t\t\t\t\t\t\tclassName=\"absolute\"\n\t\t\t\t\t\t\t\tstyle={{ left: label.weekIndex * (cellSize + cellGap) }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{label.month}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"mr-1 flex flex-col text-xs text-basalt-muted-foreground select-none\"\n\t\t\t\t\t\t\tstyle={{ width: labelWidth }}\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{weekdays.map((day, index) => (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={`${day}-${index}`}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\theight: cellSize + cellGap,\n\t\t\t\t\t\t\t\t\t\tlineHeight: `${cellSize + cellGap}px`,\n\t\t\t\t\t\t\t\t\t\tvisibility: index % 2 === 1 ? \"visible\" : \"hidden\",\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{day}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex\" style={{ gap: cellGap }}>\n\t\t\t\t\t\t\t{weeks.map((week, weekIndex) => (\n\t\t\t\t\t\t\t\t<div key={weekIndex} className=\"flex flex-col\" style={{ gap: cellGap }}>\n\t\t\t\t\t\t\t\t\t{week.map((date, dayIndex) => {\n\t\t\t\t\t\t\t\t\t\tconst dateStr = formatDate(date);\n\t\t\t\t\t\t\t\t\t\tconst isCurrentYear = date.getFullYear() === year;\n\t\t\t\t\t\t\t\t\t\tif (!isCurrentYear) {\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={dayIndex}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvisibility: \"hidden\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tconst value = dataMap.get(dateStr) ?? 0;\n\t\t\t\t\t\t\t\t\t\tconst colorIndex = getColorIndex(value, maxValue, colorScale);\n\t\t\t\t\t\t\t\t\t\tconst isSelected = activeDay?.dateStr === dateStr;\n\t\t\t\t\t\t\t\t\t\tconst formattedValue = valueFormatter(value, dateStr);\n\t\t\t\t\t\t\t\t\t\tconst labelText = `${dateStr}, ${metricLabel}: ${formattedValue}`;\n\t\t\t\t\t\t\t\t\t\tconst isOpen = openTooltipDate === dateStr;\n\t\t\t\t\t\t\t\t\t\tconst currentCell: YearDayCell = {\n\t\t\t\t\t\t\t\t\t\t\tdateStr,\n\t\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\t\tweekIndex,\n\t\t\t\t\t\t\t\t\t\t\tdayIndex,\n\t\t\t\t\t\t\t\t\t\t\tcolorIndex,\n\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<Tooltip\n\t\t\t\t\t\t\t\t\t\t\t\tkey={dayIndex}\n\t\t\t\t\t\t\t\t\t\t\t\topen={isOpen}\n\t\t\t\t\t\t\t\t\t\t\t\tonOpenChange={(next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (next) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenTooltipDate(dateStr);\n\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenTooltipDate((curr) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (curr !== dateStr) return curr;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// If this cell currently holds document focus, ignore scroll dismiss\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isCellFocused =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdocument.activeElement === cellRefs.current.get(dateStr);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn isCellFocused ? curr : null;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tref={(el) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (el) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcellRefs.current.set(dateStr, el);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcellRefs.current.delete(dateStr);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={labelText}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttabIndex={isSelected ? 0 : -1}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonFocus={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetActiveDate(dateStr);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenTooltipDate(dateStr);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonBlur={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenTooltipDate((curr) => (curr === dateStr ? null : curr));\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(e) => handleCellKeyDown(e, currentCell)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"box-border m-0 cursor-pointer rounded-sm border-0 p-0 transition-colors hover:ring-1 hover:ring-basalt-foreground focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-basalt-ring\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: colorScale[colorIndex],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<TooltipContent id={`${calendarId}-${dateStr}`}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"text-sm\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"font-medium\">{dateStr}</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{metricLabel}: {formattedValue}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"mt-2 flex items-center justify-end gap-1 text-xs text-basalt-muted-foreground select-none\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span>{lessLabel}</span>\n\t\t\t\t\t\t{colorScale.map((color) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={color}\n\t\t\t\t\t\t\t\tclassName=\"rounded-sm\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\twidth: cellSize,\n\t\t\t\t\t\t\t\t\theight: cellSize,\n\t\t\t\t\t\t\t\t\tbackgroundColor: color,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<span>{moreLabel}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</TooltipProvider>\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|