react-beautiful-heatmap
Version:
A calendar heatmap component built on SVG
208 lines (207 loc) • 6.37 kB
JavaScript
import { jsx as i, jsxs as G } from "react/jsx-runtime";
function w(t, r) {
const n = new Date(t);
return n.setDate(n.getDate() + r), n;
}
function V(t) {
return new Date(t.getFullYear(), t.getMonth(), t.getDate());
}
function B(t) {
return t instanceof Date ? t : new Date(t);
}
function tt(t) {
return w(/* @__PURE__ */ new Date(), -t);
}
function R(t) {
const r = [];
for (let n = 0; n < t; n += 1)
r.push(n);
return r;
}
const x = 24 * 60 * 60 * 1e3, A = 7, et = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], nt = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], f = 10, W = 4, E = "react-heatmap-", rt = -2, ot = {
horizontal: 30,
vertical: f * 1.5
}, st = {
horizontal: f + W,
vertical: 2 * (f + W)
}, at = ({
startDateWithEmptyDays: t,
weekCount: r,
monthLabels: n,
monthLabelCoordinates: h,
layout: o
}) => R(r - 1).map((c) => {
const l = w(t, (c + 1) * A), [m, $] = h, g = {
horizontal: {
x: m * c,
y: $
},
vertical: {
x: m,
y: $ * (c + 1)
}
};
return l.getDate() >= 1 && l.getDate() <= A ? /* @__PURE__ */ i(
"text",
{
x: g[o].x,
y: g[o].y,
className: `${E}month-label`,
children: n[l.getMonth()]
},
c
) : null;
}), ct = ({ weekdayLabels: t, layout: r, gutterSize: n }) => {
const h = {
horizontal: `${E}weekday-label`,
vertical: `${E}small-text} ${E}weekday-label`
}, o = (a) => r === "horizontal" ? [0, (a + 1) * f + a * n - f / 4] : [a * f + a * n, f];
return t.map((a, c) => {
const [l, m] = o(c);
return /* @__PURE__ */ i("text", { x: l, y: m, className: h[r], children: a }, `${l}${m}`);
});
}, lt = ({
index: t,
numEmptyDaysAtStart: r,
dateDifferenceInDays: n,
showOutOfRangeDays: h,
value: o,
squareCoordinates: a,
handleClick: c,
handleMouseOver: l,
handleMouseLeave: m,
getTooltipDataAttrsForIndex: $,
getTitleForIndex: g,
getClassNameForIndex: e,
transformDayElement: D
}) => {
if ((t < r || t >= r + n) && !h)
return null;
const [p, M] = a, b = /* @__PURE__ */ i(
"rect",
{
width: f,
height: f,
x: p,
y: M,
className: e(t),
onClick: () => c(o),
onMouseOver: (u) => l(u, o),
onMouseLeave: (u) => m(u, o),
...$(t),
children: /* @__PURE__ */ i("title", { children: g(t) })
}
);
return D ? D(b, o, t) : b;
}, it = lt, mt = ({ weeks: t, valueCache: r, squareSizeWithGutter: n, layout: h, classForValue: o, ...a }) => {
const c = R(A), l = (e) => h === "horizontal" ? `translate(${e * n}, 0)` : `translate(0, ${e * n})`, m = (e) => h === "horizontal" ? [0, e * n] : [e * n, 0], $ = (e) => r[e] ? r[e].value : null, g = (e) => r[e] ? r[e].className : o();
return t.map((e) => /* @__PURE__ */ i("g", { transform: l(e), className: `${E}week`, children: c.map((D) => {
const N = m(D);
return /* @__PURE__ */ i(
it,
{
index: e * A + D,
value: $(D),
squareCoordinates: N,
getClassNameForIndex: g,
...a
},
D
);
}) }, e));
}, ft = mt;
function gt({
layout: t = "horizontal",
values: r = [],
startDate: n = tt(200),
endDate: h = /* @__PURE__ */ new Date(),
gutterSize: o = 1,
showMonthLabels: a = !0,
showWeekdayLabels: c = !0,
showOutOfRangeDays: l = !1,
monthLabels: m = et,
weekdayLabels: $ = nt,
tooltipDataAttrs: g,
titleForValue: e,
classForValue: D = (u) => u ? "color-filled" : "color-empty",
onClick: N,
onMouseOver: p,
onMouseLeave: M,
transformDayElement: b
}) {
const u = V(B(h)), J = u.getTime() - B(n).getTime(), F = Math.ceil(J / x), v = w(u, -F + 1), O = v.getDay(), U = A - 1 - u.getDay(), C = Math.ceil((F + O + U) / A), d = f + o, y = A * d, _ = c ? ot[t] : 0, S = a ? st[t] : 0, z = C * d - (o - _), Y = y + (S - o), T = {
horizontal: {
viewBox: `0 0 ${z} ${Y}`,
transformForMonthLabels: `translate(${_}, 0)`,
transformForAllWeeks: `translate(${_}, ${S})`,
transformForWeekdayLabels: `translate(${f}, ${S})`,
monthLabelCoordinates: [d, S - W]
},
vertical: {
viewBox: `0 0 ${Y} ${z}`,
transformForMonthLabels: `translate(${y + W}, ${_})`,
transformForAllWeeks: `translate(0, ${_})`,
transformForWeekdayLabels: void 0,
monthLabelCoordinates: [0, d + rt]
}
}, H = w(v, -O), Z = (s) => typeof g == "function" ? g(s) : g, k = r.reduce((s, L) => {
const j = B(L.date).getTime(), X = Math.floor((j - H.getTime()) / x);
return s[X] = {
value: L,
className: D(L),
title: e == null ? void 0 : e(L),
tooltipDataAttrs: Z(L)
}, s;
}, {}), q = (s) => {
N && N(s);
}, I = (s, L) => {
p && p(s, L);
}, K = (s, L) => {
M && M(s, L);
}, P = (s) => k[s] ? k[s].tooltipDataAttrs : Z(), Q = (s) => k[s] ? k[s].title : e ? e() : null;
return /* @__PURE__ */ G("svg", { className: "react-heatmap", viewBox: T[t].viewBox, children: [
a && /* @__PURE__ */ i("g", { transform: T[t].transformForMonthLabels, className: `${E}month-labels`, children: /* @__PURE__ */ i(
at,
{
startDateWithEmptyDays: H,
weekCount: C,
monthLabels: m,
layout: t,
monthLabelCoordinates: T[t].monthLabelCoordinates
}
) }),
/* @__PURE__ */ i("g", { transform: T[t].transformForAllWeeks, className: `${E}all-weeks`, children: /* @__PURE__ */ i(
ft,
{
weeks: R(C),
valueCache: k,
squareSizeWithGutter: d,
layout: t,
numEmptyDaysAtStart: O,
dateDifferenceInDays: F,
showOutOfRangeDays: l,
classForValue: D,
handleClick: q,
handleMouseLeave: K,
handleMouseOver: I,
getTooltipDataAttrsForIndex: P,
getTitleForIndex: Q,
transformDayElement: b
}
) }),
c && /* @__PURE__ */ i("g", { transform: T[t].transformForWeekdayLabels, className: `${E}weekday-labels`, children: /* @__PURE__ */ i(ct, { weekdayLabels: $, layout: t, gutterSize: o }) })
] });
}
export {
E as CSS_PSEDUO_NAMESPACE,
A as DAYS_IN_WEEK,
nt as DAY_LABELS,
x as MILLISECONDS_IN_ONE_DAY,
et as MONTH_LABELS,
W as MONTH_LABEL_GUTTER_SIZE,
st as MONTH_LABEL_SIZE,
gt as ReactHeatmap,
f as SQUARE_SIZE,
rt as VERTICAL_OFFSET,
ot as WEEK_DAY_LABEL_SIZE
};