@sckyzo/cosmos-charts 0.4.0 → 0.4.1
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/CHANGELOG.md +9 -0
- package/README.md +19 -115
- package/dist/BarChart.cjs +2 -2
- package/dist/BarChart.js +1 -1
- package/dist/BoxPlotChart.cjs +2 -2
- package/dist/BoxPlotChart.js +1 -1
- package/dist/CalendarChart.cjs +2 -2
- package/dist/CalendarChart.js +1 -1
- package/dist/HeatmapChart.cjs +2 -2
- package/dist/HeatmapChart.js +1 -1
- package/dist/LineAreaChart.cjs +2 -2
- package/dist/LineAreaChart.js +1 -1
- package/dist/MixedChart.cjs +2 -2
- package/dist/MixedChart.js +1 -1
- package/dist/RangeBarChart.cjs +2 -2
- package/dist/RangeBarChart.js +1 -1
- package/dist/RealtimeChart.cjs +1 -1
- package/dist/RealtimeChart.cjs.map +1 -1
- package/dist/RealtimeChart.js +1 -1
- package/dist/RealtimeChart.js.map +1 -1
- package/dist/ScatterChart.cjs +2 -2
- package/dist/ScatterChart.js +1 -1
- package/dist/{chunk-ZWHCUYIN.cjs → chunk-GBJPNJWM.cjs} +69 -9
- package/dist/chunk-GBJPNJWM.cjs.map +1 -0
- package/dist/{chunk-XUGQ6VXO.cjs → chunk-RGDENOKY.cjs} +3 -3
- package/dist/chunk-RGDENOKY.cjs.map +1 -0
- package/dist/{chunk-ESVGCUJN.js → chunk-RXCGQ5QQ.js} +3 -3
- package/dist/chunk-RXCGQ5QQ.js.map +1 -0
- package/dist/{chunk-UL3SNXQR.js → chunk-V56L4SNY.js} +70 -10
- package/dist/chunk-V56L4SNY.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-ESVGCUJN.js.map +0 -1
- package/dist/chunk-UL3SNXQR.js.map +0 -1
- package/dist/chunk-XUGQ6VXO.cjs.map +0 -1
- package/dist/chunk-ZWHCUYIN.cjs.map +0 -1
|
@@ -8,28 +8,56 @@ var chunkLT3UC65O_cjs = require('./chunk-LT3UC65O.cjs');
|
|
|
8
8
|
var react = require('react');
|
|
9
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
10
|
|
|
11
|
+
var EDGE = "1.5rem";
|
|
12
|
+
var useEndFade = () => {
|
|
13
|
+
const [element, ref] = react.useState(null);
|
|
14
|
+
const [more, setMore] = react.useState(false);
|
|
15
|
+
react.useEffect(() => {
|
|
16
|
+
if (!element) return;
|
|
17
|
+
const measure = () => setMore(element.scrollLeft + element.clientWidth < element.scrollWidth - 1);
|
|
18
|
+
measure();
|
|
19
|
+
element.addEventListener("scroll", measure, { passive: true });
|
|
20
|
+
const observer = new ResizeObserver(measure);
|
|
21
|
+
observer.observe(element);
|
|
22
|
+
for (const child of element.children) observer.observe(child);
|
|
23
|
+
return () => {
|
|
24
|
+
element.removeEventListener("scroll", measure);
|
|
25
|
+
observer.disconnect();
|
|
26
|
+
};
|
|
27
|
+
}, [element]);
|
|
28
|
+
const mask = `linear-gradient(to right, #000 calc(100% - ${EDGE}), transparent)`;
|
|
29
|
+
const style = more ? { maskImage: mask, WebkitMaskImage: mask } : void 0;
|
|
30
|
+
return { ref, style };
|
|
31
|
+
};
|
|
11
32
|
var GAP = 3;
|
|
12
33
|
var RADIUS = 5;
|
|
13
34
|
var LABEL_GAP = 6;
|
|
35
|
+
var VALUE_PADDING = 4;
|
|
14
36
|
var TIP_GAP = 6;
|
|
15
37
|
var key = (row, column) => `${row}:${column}`;
|
|
16
|
-
var useLabelStride = (probe, gap) => {
|
|
38
|
+
var useLabelStride = (probe, valueProbe, gap) => {
|
|
17
39
|
const gridRef = react.useRef(null);
|
|
18
40
|
const probeRef = react.useRef(null);
|
|
41
|
+
const valueProbeRef = react.useRef(null);
|
|
19
42
|
const columnRef = react.useRef(null);
|
|
20
43
|
const [stride, setStride] = react.useState(1);
|
|
44
|
+
const [valuesFit, setValuesFit] = react.useState(true);
|
|
21
45
|
react.useLayoutEffect(() => {
|
|
22
46
|
const read = () => {
|
|
23
47
|
const label = probeRef.current?.offsetWidth ?? 0;
|
|
48
|
+
const value = valueProbeRef.current?.offsetWidth ?? 0;
|
|
24
49
|
const column = columnRef.current?.offsetWidth ?? 0;
|
|
25
50
|
setStride(column > 0 ? Math.max(1, Math.ceil((label + LABEL_GAP) / (column + gap))) : 1);
|
|
51
|
+
setValuesFit(column === 0 || value === 0 || value + VALUE_PADDING <= column);
|
|
26
52
|
};
|
|
27
53
|
read();
|
|
28
54
|
const observer = new ResizeObserver(read);
|
|
29
|
-
for (const el of [gridRef.current, probeRef.current])
|
|
55
|
+
for (const el of [gridRef.current, probeRef.current, valueProbeRef.current]) {
|
|
56
|
+
if (el) observer.observe(el);
|
|
57
|
+
}
|
|
30
58
|
return () => observer.disconnect();
|
|
31
|
-
}, [probe, gap]);
|
|
32
|
-
return { gridRef, probeRef, columnRef, stride };
|
|
59
|
+
}, [probe, valueProbe, gap]);
|
|
60
|
+
return { gridRef, probeRef, valueProbeRef, columnRef, stride, valuesFit };
|
|
33
61
|
};
|
|
34
62
|
var HeatGrid = ({
|
|
35
63
|
rows,
|
|
@@ -47,7 +75,16 @@ var HeatGrid = ({
|
|
|
47
75
|
}) => {
|
|
48
76
|
const frame = react.useRef(null);
|
|
49
77
|
const longest = columns.reduce((a, b) => b.length > a.length ? b : a, "");
|
|
50
|
-
const
|
|
78
|
+
const longestValue = cells.reduce((a, c) => (c.text ?? "").length > a.length ? c.text : a, "");
|
|
79
|
+
const {
|
|
80
|
+
gridRef,
|
|
81
|
+
probeRef,
|
|
82
|
+
valueProbeRef,
|
|
83
|
+
columnRef,
|
|
84
|
+
stride: measured,
|
|
85
|
+
valuesFit
|
|
86
|
+
} = useLabelStride(longest, longestValue, gap);
|
|
87
|
+
const fade = useEndFade();
|
|
51
88
|
const stride = thinLabels ? measured : 1;
|
|
52
89
|
const byPosition = new Map(cells.map((cell) => [key(cell.row, cell.column), cell]));
|
|
53
90
|
const cellsByRow = /* @__PURE__ */ new Map();
|
|
@@ -213,7 +250,7 @@ var HeatGrid = ({
|
|
|
213
250
|
outline: active ? `2px solid ${chunkLT3UC65O_cjs.TEXT}` : "none",
|
|
214
251
|
zIndex: active ? 1 : void 0
|
|
215
252
|
},
|
|
216
|
-
children: cell.text
|
|
253
|
+
children: valuesFit && cell.text
|
|
217
254
|
},
|
|
218
255
|
position
|
|
219
256
|
);
|
|
@@ -257,6 +294,21 @@ var HeatGrid = ({
|
|
|
257
294
|
style: { position: "absolute", visibility: "hidden", whiteSpace: "nowrap" },
|
|
258
295
|
children: longest
|
|
259
296
|
}
|
|
297
|
+
),
|
|
298
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
299
|
+
"span",
|
|
300
|
+
{
|
|
301
|
+
ref: valueProbeRef,
|
|
302
|
+
"aria-hidden": true,
|
|
303
|
+
style: {
|
|
304
|
+
position: "absolute",
|
|
305
|
+
visibility: "hidden",
|
|
306
|
+
whiteSpace: "nowrap",
|
|
307
|
+
fontSize: "var(--text-2xs, 0.6875rem)",
|
|
308
|
+
fontWeight: 500
|
|
309
|
+
},
|
|
310
|
+
children: longestValue
|
|
311
|
+
}
|
|
260
312
|
)
|
|
261
313
|
]
|
|
262
314
|
}
|
|
@@ -265,7 +317,15 @@ var HeatGrid = ({
|
|
|
265
317
|
columnWidth ? (
|
|
266
318
|
// The padding leaves room for the focus outline of the cells at the edges,
|
|
267
319
|
// which the scrolling box would cut.
|
|
268
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
320
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
321
|
+
"div",
|
|
322
|
+
{
|
|
323
|
+
ref: fade.ref,
|
|
324
|
+
"data-heat-scroll": "",
|
|
325
|
+
style: { overflowX: "auto", padding: 3, ...fade.style },
|
|
326
|
+
children: grid
|
|
327
|
+
}
|
|
328
|
+
)
|
|
269
329
|
) : grid,
|
|
270
330
|
tip && tipStyle && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-heat-tooltip": "", "aria-hidden": true, style: tipStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
271
331
|
chunkT3K6Q34U_cjs.TooltipCard,
|
|
@@ -278,5 +338,5 @@ var HeatGrid = ({
|
|
|
278
338
|
};
|
|
279
339
|
|
|
280
340
|
exports.HeatGrid = HeatGrid;
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
282
|
-
//# sourceMappingURL=chunk-
|
|
341
|
+
//# sourceMappingURL=chunk-GBJPNJWM.cjs.map
|
|
342
|
+
//# sourceMappingURL=chunk-GBJPNJWM.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/useEndFade.ts","../src/core/HeatGrid.tsx"],"names":["useState","useEffect","useRef","useLayoutEffect","cell","jsxs","TEXT_SIZE","MUTED","jsx","PANEL","textOn","TEXT","TooltipCard"],"mappings":"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","file":"chunk-GBJPNJWM.cjs","sourcesContent":["import { useEffect, useState, type CSSProperties } from 'react';\n\nconst EDGE = '1.5rem';\n\n/**\n * The style that fades the end of a box that scrolls sideways while there is more past it: a\n * hint that the content goes on, as the tables of cosmos-react give. Charts read left to right\n * whatever the page, so the end is the right edge. The start is left alone: it holds the row\n * labels, which stay in view. `undefined` while it all fits, and until the first measure. Attach\n * `ref` to the scrolling box.\n */\nexport const useEndFade = () => {\n const [element, ref] = useState<HTMLElement | null>(null);\n const [more, setMore] = useState(false);\n useEffect(() => {\n if (!element) return;\n const measure = () =>\n setMore(element.scrollLeft + element.clientWidth < element.scrollWidth - 1);\n measure();\n element.addEventListener('scroll', measure, { passive: true });\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n for (const child of element.children) observer.observe(child);\n return () => {\n element.removeEventListener('scroll', measure);\n observer.disconnect();\n };\n }, [element]);\n const mask = `linear-gradient(to right, #000 calc(100% - ${EDGE}), transparent)`;\n const style: CSSProperties | undefined = more\n ? { maskImage: mask, WebkitMaskImage: mask }\n : undefined;\n return { ref, style };\n};\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react';\nimport { TEXT_SIZE } from './axes';\nimport { TooltipCard } from './ChartTooltip';\nimport { MUTED, PANEL, TEXT } from './colors';\nimport { textOn } from './readable';\nimport { useEndFade } from './useEndFade';\n\n/** One cell of a `HeatGrid`. A slot with no cell stays empty. */\nexport type HeatCell = {\n /** Zero-based position: the index in `rows` and in `columns`. */\n row: number;\n column: number;\n /** Any CSS color. The text printed in the cell reads on it. */\n color: string;\n /** Heads the tooltip, such as the column's category. */\n title: string;\n /** Names the cell in the tooltip, such as the row. May be empty when the value says it all. */\n label: string;\n /** The value, formatted: the tooltip's value, and the end of the cell's accessible name. */\n value: string;\n /** Printed inside the cell. */\n text?: string;\n};\n\ntype HeatGridProps = {\n /** The label of each row, top to bottom. An empty string leaves the row unlabelled. */\n rows: readonly string[];\n /** The label of each column, left to right. Too many for the width: every n-th one is drawn. */\n columns: readonly string[];\n cells: readonly HeatCell[];\n /**\n * Height of a row in px. Without it the rows share the height of the\n * parent, which must then have one.\n */\n cellHeight?: number;\n /** Names the grid for screen readers. */\n ariaLabel: string;\n /** Title under the columns. Drawn as plain text. */\n xTitle?: string;\n /** Title beside the rows. Drawn as plain text. */\n yTitle?: string;\n /** Space between two cells in px. Default 3. */\n gap?: number;\n /** Corner radius of a cell in px. Default 5. */\n cellRadius?: number;\n /**\n * Width of a column in px. Without it the columns share the width of the\n * parent; with it they keep this width, and the grid scrolls sideways inside\n * its own box when it is wider than the parent. The row labels stay in view.\n */\n columnWidth?: number;\n /** Draw the column labels above the rows instead of under them. */\n labelsAbove?: boolean;\n /**\n * Draw every column label, as given. By default the labels are centered on\n * their column and every n-th one is drawn so that none touches the next.\n * Off, each starts at the left of its column and may run over the columns\n * after it, which an empty label leaves free: for labels such as the months\n * of a calendar, where the caller decides which columns carry one.\n */\n thinLabels?: boolean;\n};\n\nconst GAP = 3;\nconst RADIUS = 5;\n// Clear space kept between two column labels.\nconst LABEL_GAP = 6;\n// Clear space a value keeps inside its cell, both sides together.\nconst VALUE_PADDING = 4;\n// Room the tooltip card leaves the pointer or the cell.\nconst TIP_GAP = 6;\n\nconst key = (row: number, column: number) => `${row}:${column}`;\n\n/**\n * How many columns apart the labels are drawn so that none touches the next:\n * 1 when they all fit; and whether the longest value fits a cell, or the values\n * are left out rather than drawn cut. Measured on the page, since the text size,\n * the font and the width all change both.\n */\nconst useLabelStride = (probe: string, valueProbe: string, gap: number) => {\n const gridRef = useRef<HTMLDivElement>(null);\n const probeRef = useRef<HTMLSpanElement>(null);\n const valueProbeRef = useRef<HTMLSpanElement>(null);\n const columnRef = useRef<HTMLDivElement>(null);\n const [stride, setStride] = useState(1);\n const [valuesFit, setValuesFit] = useState(true);\n useLayoutEffect(() => {\n const read = () => {\n const label = probeRef.current?.offsetWidth ?? 0;\n const value = valueProbeRef.current?.offsetWidth ?? 0;\n const column = columnRef.current?.offsetWidth ?? 0;\n setStride(column > 0 ? Math.max(1, Math.ceil((label + LABEL_GAP) / (column + gap))) : 1);\n setValuesFit(column === 0 || value === 0 || value + VALUE_PADDING <= column);\n };\n read();\n const observer = new ResizeObserver(read);\n for (const el of [gridRef.current, probeRef.current, valueProbeRef.current]) {\n if (el) observer.observe(el);\n }\n return () => observer.disconnect();\n }, [probe, valueProbe, gap]);\n return { gridRef, probeRef, valueProbeRef, columnRef, stride, valuesFit };\n};\n\ntype Tip = {\n cell: HeatCell;\n /** Where the card is anchored, in px from the grid's corner, and on which side of the cell. */\n x: number;\n top: number;\n bottom: number;\n align: 'start' | 'center' | 'end';\n below: boolean;\n};\n\n/**\n * A grid of colored cells with row and column labels: the drawing of\n * `HeatmapChart`, and of any chart laid out as rows and columns. Recharts has\n * no such chart, so it is plain HTML in a CSS grid, which sizes the label\n * column to the text (it follows the text size) and the cells to the width.\n *\n * Keyboard: the grid is one tab stop (a roving tabindex), and the arrow keys\n * move between cells, skipping empty slots; Home and End go to the ends of the\n * row, Ctrl+Home and Ctrl+End to the first and last cell. The cell under the\n * pointer or the keyboard shows its tooltip. Each cell is named\n * `label, title: value`, so a screen reader reads what the tooltip says.\n */\nexport const HeatGrid = ({\n rows,\n columns,\n cells,\n cellHeight,\n ariaLabel,\n xTitle,\n yTitle,\n gap = GAP,\n cellRadius = RADIUS,\n columnWidth,\n labelsAbove = false,\n thinLabels = true,\n}: HeatGridProps) => {\n const frame = useRef<HTMLDivElement>(null);\n const longest = columns.reduce((a, b) => (b.length > a.length ? b : a), '');\n const longestValue = cells.reduce((a, c) => ((c.text ?? '').length > a.length ? c.text! : a), '');\n const {\n gridRef,\n probeRef,\n valueProbeRef,\n columnRef,\n stride: measured,\n valuesFit,\n } = useLabelStride(longest, longestValue, gap);\n const fade = useEndFade();\n const stride = thinLabels ? measured : 1;\n const byPosition = new Map(cells.map((cell) => [key(cell.row, cell.column), cell]));\n const cellsByRow = new Map<number, HeatCell[]>();\n for (const cell of cells) cellsByRow.set(cell.row, [...(cellsByRow.get(cell.row) ?? []), cell]);\n const inReadingOrder = [...cells].sort((a, b) => a.row - b.row || a.column - b.column);\n const [roving, setRoving] = useState<string>();\n // The cell that takes Tab: the last one focused, while it is still there.\n const first = inReadingOrder[0];\n const tabbable =\n roving && byPosition.has(roving) ? roving : first && key(first.row, first.column);\n const [hover, setHover] = useState<Tip>();\n const [focus, setFocus] = useState<Tip>();\n const tip = hover ?? focus;\n\n const tipFor = (cell: HeatCell, element: HTMLElement): Tip => {\n const host = (frame.current as HTMLElement).getBoundingClientRect();\n const box = element.getBoundingClientRect();\n const middle = box.left - host.left + box.width / 2;\n // The card hangs from the side of the cell nearest the middle of the grid,\n // so it never leaves the grid.\n const align =\n middle < host.width / 3 ? 'start' : middle > (2 * host.width) / 3 ? 'end' : 'center';\n return {\n cell,\n x: { start: box.left - host.left, center: middle, end: box.right - host.left }[align],\n top: box.top - host.top,\n bottom: box.bottom - host.top,\n align,\n // Not enough room above the cell for the card: it goes under.\n below: box.top - host.top < 90,\n };\n };\n\n const move = (event: KeyboardEvent<HTMLDivElement>) => {\n const origin = (event.target as HTMLElement).closest<HTMLElement>('[data-heat-cell]');\n if (!origin) return;\n const row = Number(origin.dataset.row);\n const column = Number(origin.dataset.column);\n // The next cell in a direction: empty slots are skipped, the edge stops.\n const step = (dRow: number, dColumn: number) => {\n for (\n let r = row + dRow, c = column + dColumn;\n r >= 0 && r < rows.length && c >= 0 && c < columns.length;\n r += dRow, c += dColumn\n ) {\n if (byPosition.has(key(r, c))) return key(r, c);\n }\n };\n const edge = (last: boolean) => {\n const pool = event.ctrlKey\n ? inReadingOrder\n : inReadingOrder.filter((cell) => cell.row === row);\n const cell = last ? pool.at(-1) : pool[0];\n return cell && key(cell.row, cell.column);\n };\n const targets: Record<string, () => string | undefined> = {\n ArrowRight: () => step(0, 1),\n ArrowLeft: () => step(0, -1),\n ArrowDown: () => step(1, 0),\n ArrowUp: () => step(-1, 0),\n Home: () => edge(false),\n End: () => edge(true),\n };\n const target = targets[event.key];\n if (!target) return;\n event.preventDefault();\n const next = target();\n if (next) gridRef.current?.querySelector<HTMLElement>(`[data-position=\"${next}\"]`)?.focus();\n };\n\n const focusIn = (cell: HeatCell, event: FocusEvent<HTMLElement>) => {\n setRoving(key(cell.row, cell.column));\n // A click focuses a cell too, and would leave its tooltip up: only the keyboard shows it.\n if (event.currentTarget.matches(':focus-visible')) {\n setFocus(tipFor(cell, event.currentTarget));\n }\n };\n const focusOut = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setFocus(undefined);\n };\n\n const rowOffset = yTitle ? 2 : 1;\n // The rows start under the labels when these sit above them.\n const top = labelsAbove ? 1 : 0;\n const labelsRow = labelsAbove ? 1 : rows.length + 1;\n const tipStyle: CSSProperties | undefined = tip && {\n position: 'absolute',\n left: tip.x,\n top: tip.below ? tip.bottom + TIP_GAP : tip.top - TIP_GAP,\n transform: `translate(${{ start: '0', center: '-50%', end: '-100%' }[tip.align]}, ${tip.below ? '0' : '-100%'})`,\n zIndex: 10,\n pointerEvents: 'none',\n };\n\n const grid = (\n <div\n ref={gridRef}\n role=\"grid\"\n aria-label={ariaLabel}\n onKeyDown={move}\n onBlur={focusOut}\n style={{\n display: 'grid',\n gridTemplateColumns: `${yTitle ? 'auto ' : ''}${columnWidth ? 'auto' : 'fit-content(40%)'} repeat(${columns.length}, ${columnWidth ? `${columnWidth}px` : 'minmax(0, 1fr)'})`,\n gridTemplateRows: `${labelsAbove ? 'auto ' : ''}repeat(${rows.length}, ${cellHeight ? `${cellHeight}px` : 'minmax(0, 1fr)'})${labelsAbove ? '' : ' auto'}${xTitle ? ' auto' : ''}`,\n gap,\n width: columnWidth ? 'max-content' : '100%',\n height: cellHeight ? undefined : '100%',\n fontSize: TEXT_SIZE,\n color: MUTED,\n }}\n >\n {yTitle && (\n <div\n aria-hidden\n style={{\n gridRow: `${1 + top} / ${rows.length + 1 + top}`,\n gridColumn: 1,\n writingMode: 'vertical-rl',\n transform: 'rotate(180deg)',\n textAlign: 'center',\n alignSelf: 'center',\n }}\n >\n {yTitle}\n </div>\n )}\n {rows.map((name, r) => (\n <div key={r} role=\"row\" style={{ display: 'contents' }}>\n <div\n aria-hidden\n data-heat-row=\"\"\n style={{\n gridRow: r + 1 + top,\n gridColumn: rowOffset,\n alignSelf: 'center',\n paddingRight: '0.5rem',\n // Stays in view when the grid scrolls sideways under it.\n ...(columnWidth ? { position: 'sticky', left: 0, zIndex: 2, background: PANEL } : {}),\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {name}\n </div>\n {(cellsByRow.get(r) ?? []).map((cell) => {\n const position = key(cell.row, cell.column);\n const active = tip?.cell === cell;\n return (\n <div\n key={position}\n role=\"gridcell\"\n data-heat-cell=\"\"\n data-position={position}\n data-row={cell.row}\n data-column={cell.column}\n tabIndex={position === tabbable ? 0 : -1}\n aria-label={`${cell.label ? `${cell.label}, ` : ''}${cell.title}: ${cell.value}`}\n onFocus={(event) => focusIn(cell, event)}\n onMouseEnter={(event) => setHover(tipFor(cell, event.currentTarget))}\n onMouseLeave={() => setHover(undefined)}\n style={{\n gridRow: r + 1 + top,\n gridColumn: cell.column + rowOffset + 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: 0,\n overflow: 'hidden',\n borderRadius: cellRadius,\n background: cell.color,\n color: textOn(cell.color),\n fontSize: 'var(--text-2xs, 0.6875rem)',\n fontWeight: 500,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n // The same ring for the pointer and the keyboard, in the text color\n // since an accent ring would vanish on the cells that are the accent.\n outline: active ? `2px solid ${TEXT}` : 'none',\n zIndex: active ? 1 : undefined,\n }}\n >\n {valuesFit && cell.text}\n </div>\n );\n })}\n </div>\n ))}\n {columns.map((name, c) => (\n <div\n key={c}\n ref={c === 0 ? columnRef : undefined}\n aria-hidden\n data-heat-column=\"\"\n style={{\n gridRow: labelsRow,\n gridColumn: c + rowOffset + 1,\n display: 'flex',\n justifyContent: thinLabels ? 'center' : 'flex-start',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n >\n {c % stride === 0 ? name : null}\n </div>\n ))}\n {xTitle && (\n <div\n aria-hidden\n style={{\n gridRow: (labelsAbove ? rows.length + 1 : labelsRow) + 1,\n gridColumn: `${rowOffset + 1} / -1`,\n textAlign: 'center',\n }}\n >\n {xTitle}\n </div>\n )}\n <span\n ref={probeRef}\n aria-hidden\n style={{ position: 'absolute', visibility: 'hidden', whiteSpace: 'nowrap' }}\n >\n {longest}\n </span>\n {/* In the font of a cell's value. */}\n <span\n ref={valueProbeRef}\n aria-hidden\n style={{\n position: 'absolute',\n visibility: 'hidden',\n whiteSpace: 'nowrap',\n fontSize: 'var(--text-2xs, 0.6875rem)',\n fontWeight: 500,\n }}\n >\n {longestValue}\n </span>\n </div>\n );\n\n return (\n <div ref={frame} style={{ position: 'relative', width: '100%', height: '100%', minWidth: 0 }}>\n {columnWidth ? (\n // The padding leaves room for the focus outline of the cells at the edges,\n // which the scrolling box would cut.\n <div\n ref={fade.ref}\n data-heat-scroll=\"\"\n style={{ overflowX: 'auto', padding: 3, ...fade.style }}\n >\n {grid}\n </div>\n ) : (\n grid\n )}\n {tip && tipStyle && (\n <div data-heat-tooltip=\"\" aria-hidden style={tipStyle}>\n <TooltipCard\n title={tip.cell.title}\n rows={[{ name: tip.cell.label, value: tip.cell.value, color: tip.cell.color }]}\n />\n </div>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -34,7 +34,7 @@ var referenceMarks = ({
|
|
|
34
34
|
fillOpacity: 0.14,
|
|
35
35
|
ifOverflow: "extendDomain",
|
|
36
36
|
zIndex: BAND_LAYER,
|
|
37
|
-
label: band.label ? labelOf(band.label, "
|
|
37
|
+
label: band.label ? labelOf(band.label, "insideBottomLeft") : void 0
|
|
38
38
|
},
|
|
39
39
|
`band-${i}`
|
|
40
40
|
);
|
|
@@ -56,5 +56,5 @@ var referenceMarks = ({
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
exports.referenceMarks = referenceMarks;
|
|
59
|
-
//# sourceMappingURL=chunk-
|
|
60
|
-
//# sourceMappingURL=chunk-
|
|
59
|
+
//# sourceMappingURL=chunk-RGDENOKY.cjs.map
|
|
60
|
+
//# sourceMappingURL=chunk-RGDENOKY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/reference.tsx"],"names":["MUTED","TEXT_SIZE","jsx","ReferenceArea","INTENT_COLORS","ReferenceLine"],"mappings":";;;;;;;;AAYA,IAAM,IAAA,GAAO,KAAA;AAEb,IAAM,UAAA,GAAa,EAAA;AAInB,IAAM,OAAA,GAAU,CAAC,KAAA,EAAe,QAAA,MAAqD;AAAA,EACnF,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,EAAW,0BAAA;AAAA,EACX,IAAA,EAAMA,uBAAA;AAAA,EACN,KAAA,EAAO,EAAE,QAAA,EAAUC,2BAAA;AACrB,CAAA,CAAA;AASO,IAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAiB,EAAC;AAAA,EAClB,iBAAiB,EAAC;AAAA,EAClB,IAAA,GAAO,GAAA;AAAA,EACP;AACF,CAAA,KAAwB;AACtB,EAAA,MAAM,MAAA,GAAS,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,GAAG,MAAA,EAAO;AACvE,EAAA,OAAO;AAAA,IACL,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACjC,MAAA,MAAM,CAAC,GAAA,EAAK,IAAI,IAAI,CAAC,IAAA,CAAK,IAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAC/E,MAAA,uBACEC,cAAA;AAAA,QAACC,sBAAA;AAAA,QAAA;AAAA,UAEE,GAAG,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,GAAA,EAAK,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,IAAA,EAAK;AAAA,UAC3C,GAAG,MAAA;AAAA,UACJ,IAAA,EAAMC,+BAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,UAC5C,WAAA,EAAa,IAAA;AAAA,UACb,UAAA,EAAW,cAAA;AAAA,UACX,MAAA,EAAQ,UAAA;AAAA,UAGR,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,kBAAkB,CAAA,GAAI;AAAA,SAAA;AAAA,QATzD,QAAQ,CAAC,CAAA;AAAA,OAUhB;AAAA,IAEJ,CAAC,CAAA;AAAA,IACD,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,qBAC3BF,cAAA;AAAA,MAACG,sBAAA;AAAA,MAAA;AAAA,QAEE,GAAG,EAAE,CAAC,IAAI,GAAG,KAAK,KAAA,EAAM;AAAA,QACxB,GAAG,MAAA;AAAA,QACJ,MAAA,EAAQD,+BAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,QAC9C,WAAA,EAAa,GAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,MAAA;AAAA,QACtC,UAAA,EAAW,cAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,gBAAgB,CAAA,GAAI;AAAA,OAAA;AAAA,MAPvD,QAAQ,CAAC,CAAA;AAAA,KASjB;AAAA,GACH;AACF","file":"chunk-RGDENOKY.cjs","sourcesContent":["import { ReferenceArea, ReferenceLine } from 'recharts';\nimport type { ChartReferenceProps } from '../types';\nimport { TEXT_SIZE } from './axes';\nimport { INTENT_COLORS, MUTED } from './colors';\n\ntype ReferenceOptions = ChartReferenceProps & {\n /** The axis the values are read on: `y` (default), or `x` on a chart of horizontal bars. */\n axis?: 'x' | 'y';\n /** The id of that axis, when the chart has several. */\n axisId?: string;\n};\n\nconst DASH = '6 4';\n// Behind the series (an area is at 100, a bar at 300) and above the grid.\nconst BAND_LAYER = 50;\n\n// Plain SVG text in the muted color: an amber or red label would not read on\n// the card in every theme, so the line and the band carry the intent.\nconst labelOf = (value: string, position: 'insideTopRight' | 'insideBottomLeft') => ({\n value,\n position,\n className: 'recharts-reference-label',\n fill: MUTED,\n style: { fontSize: TEXT_SIZE },\n});\n\n/**\n * The `ReferenceArea`s then the `ReferenceLine`s of a chart's `referenceBands`\n * and `referenceLines`, to render inside it, before `children`. A mark outside\n * the data makes the axis reach it (`ifOverflow=\"extendDomain\"`) instead of\n * vanishing. Colors come from `INTENT_COLORS`, so a theme switch repaints\n * them; labels are text, not markup.\n */\nexport const referenceMarks = ({\n referenceLines = [],\n referenceBands = [],\n axis = 'y',\n axisId,\n}: ReferenceOptions) => {\n const onAxis = axisId === undefined ? {} : { [`${axis}AxisId`]: axisId };\n return [\n ...referenceBands.map((band, i) => {\n const [low, high] = [Math.min(band.from, band.to), Math.max(band.from, band.to)];\n return (\n <ReferenceArea\n key={`band-${i}`}\n {...{ [`${axis}1`]: low, [`${axis}2`]: high }}\n {...onAxis}\n fill={INTENT_COLORS[band.intent ?? 'neutral']}\n fillOpacity={0.14}\n ifOverflow=\"extendDomain\"\n zIndex={BAND_LAYER}\n // At the bottom of the band, and a line's label at the top: a line in or by a band\n // never prints its label over the band's.\n label={band.label ? labelOf(band.label, 'insideBottomLeft') : undefined}\n />\n );\n }),\n ...referenceLines.map((line, i) => (\n <ReferenceLine\n key={`line-${i}`}\n {...{ [axis]: line.value }}\n {...onAxis}\n stroke={INTENT_COLORS[line.intent ?? 'neutral']}\n strokeWidth={1.5}\n strokeDasharray={line.dashed ? DASH : undefined}\n ifOverflow=\"extendDomain\"\n label={line.label ? labelOf(line.label, 'insideTopRight') : undefined}\n />\n )),\n ];\n};\n"]}
|
|
@@ -32,7 +32,7 @@ var referenceMarks = ({
|
|
|
32
32
|
fillOpacity: 0.14,
|
|
33
33
|
ifOverflow: "extendDomain",
|
|
34
34
|
zIndex: BAND_LAYER,
|
|
35
|
-
label: band.label ? labelOf(band.label, "
|
|
35
|
+
label: band.label ? labelOf(band.label, "insideBottomLeft") : void 0
|
|
36
36
|
},
|
|
37
37
|
`band-${i}`
|
|
38
38
|
);
|
|
@@ -54,5 +54,5 @@ var referenceMarks = ({
|
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
export { referenceMarks };
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
58
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-RXCGQ5QQ.js.map
|
|
58
|
+
//# sourceMappingURL=chunk-RXCGQ5QQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/reference.tsx"],"names":[],"mappings":";;;;;;AAYA,IAAM,IAAA,GAAO,KAAA;AAEb,IAAM,UAAA,GAAa,EAAA;AAInB,IAAM,OAAA,GAAU,CAAC,KAAA,EAAe,QAAA,MAAqD;AAAA,EACnF,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,EAAW,0BAAA;AAAA,EACX,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,EAAE,QAAA,EAAU,SAAA;AACrB,CAAA,CAAA;AASO,IAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAiB,EAAC;AAAA,EAClB,iBAAiB,EAAC;AAAA,EAClB,IAAA,GAAO,GAAA;AAAA,EACP;AACF,CAAA,KAAwB;AACtB,EAAA,MAAM,MAAA,GAAS,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,GAAG,MAAA,EAAO;AACvE,EAAA,OAAO;AAAA,IACL,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACjC,MAAA,MAAM,CAAC,GAAA,EAAK,IAAI,IAAI,CAAC,IAAA,CAAK,IAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAC/E,MAAA,uBACE,GAAA;AAAA,QAAC,aAAA;AAAA,QAAA;AAAA,UAEE,GAAG,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,GAAA,EAAK,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,IAAA,EAAK;AAAA,UAC3C,GAAG,MAAA;AAAA,UACJ,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,UAC5C,WAAA,EAAa,IAAA;AAAA,UACb,UAAA,EAAW,cAAA;AAAA,UACX,MAAA,EAAQ,UAAA;AAAA,UAGR,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,kBAAkB,CAAA,GAAI;AAAA,SAAA;AAAA,QATzD,QAAQ,CAAC,CAAA;AAAA,OAUhB;AAAA,IAEJ,CAAC,CAAA;AAAA,IACD,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,qBAC3B,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QAEE,GAAG,EAAE,CAAC,IAAI,GAAG,KAAK,KAAA,EAAM;AAAA,QACxB,GAAG,MAAA;AAAA,QACJ,MAAA,EAAQ,aAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,QAC9C,WAAA,EAAa,GAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,MAAA;AAAA,QACtC,UAAA,EAAW,cAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,gBAAgB,CAAA,GAAI;AAAA,OAAA;AAAA,MAPvD,QAAQ,CAAC,CAAA;AAAA,KASjB;AAAA,GACH;AACF","file":"chunk-RXCGQ5QQ.js","sourcesContent":["import { ReferenceArea, ReferenceLine } from 'recharts';\nimport type { ChartReferenceProps } from '../types';\nimport { TEXT_SIZE } from './axes';\nimport { INTENT_COLORS, MUTED } from './colors';\n\ntype ReferenceOptions = ChartReferenceProps & {\n /** The axis the values are read on: `y` (default), or `x` on a chart of horizontal bars. */\n axis?: 'x' | 'y';\n /** The id of that axis, when the chart has several. */\n axisId?: string;\n};\n\nconst DASH = '6 4';\n// Behind the series (an area is at 100, a bar at 300) and above the grid.\nconst BAND_LAYER = 50;\n\n// Plain SVG text in the muted color: an amber or red label would not read on\n// the card in every theme, so the line and the band carry the intent.\nconst labelOf = (value: string, position: 'insideTopRight' | 'insideBottomLeft') => ({\n value,\n position,\n className: 'recharts-reference-label',\n fill: MUTED,\n style: { fontSize: TEXT_SIZE },\n});\n\n/**\n * The `ReferenceArea`s then the `ReferenceLine`s of a chart's `referenceBands`\n * and `referenceLines`, to render inside it, before `children`. A mark outside\n * the data makes the axis reach it (`ifOverflow=\"extendDomain\"`) instead of\n * vanishing. Colors come from `INTENT_COLORS`, so a theme switch repaints\n * them; labels are text, not markup.\n */\nexport const referenceMarks = ({\n referenceLines = [],\n referenceBands = [],\n axis = 'y',\n axisId,\n}: ReferenceOptions) => {\n const onAxis = axisId === undefined ? {} : { [`${axis}AxisId`]: axisId };\n return [\n ...referenceBands.map((band, i) => {\n const [low, high] = [Math.min(band.from, band.to), Math.max(band.from, band.to)];\n return (\n <ReferenceArea\n key={`band-${i}`}\n {...{ [`${axis}1`]: low, [`${axis}2`]: high }}\n {...onAxis}\n fill={INTENT_COLORS[band.intent ?? 'neutral']}\n fillOpacity={0.14}\n ifOverflow=\"extendDomain\"\n zIndex={BAND_LAYER}\n // At the bottom of the band, and a line's label at the top: a line in or by a band\n // never prints its label over the band's.\n label={band.label ? labelOf(band.label, 'insideBottomLeft') : undefined}\n />\n );\n }),\n ...referenceLines.map((line, i) => (\n <ReferenceLine\n key={`line-${i}`}\n {...{ [axis]: line.value }}\n {...onAxis}\n stroke={INTENT_COLORS[line.intent ?? 'neutral']}\n strokeWidth={1.5}\n strokeDasharray={line.dashed ? DASH : undefined}\n ifOverflow=\"extendDomain\"\n label={line.label ? labelOf(line.label, 'insideTopRight') : undefined}\n />\n )),\n ];\n};\n"]}
|
|
@@ -3,31 +3,59 @@ import { textOn } from './chunk-BFEDLXVW.js';
|
|
|
3
3
|
import { TEXT_SIZE } from './chunk-DI2FBGKM.js';
|
|
4
4
|
import { TooltipCard } from './chunk-VIOSQN4Z.js';
|
|
5
5
|
import { MUTED, PANEL, TEXT } from './chunk-UATB2IRY.js';
|
|
6
|
-
import { useRef, useState, useLayoutEffect } from 'react';
|
|
6
|
+
import { useRef, useState, useLayoutEffect, useEffect } from 'react';
|
|
7
7
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
8
|
|
|
9
|
+
var EDGE = "1.5rem";
|
|
10
|
+
var useEndFade = () => {
|
|
11
|
+
const [element, ref] = useState(null);
|
|
12
|
+
const [more, setMore] = useState(false);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!element) return;
|
|
15
|
+
const measure = () => setMore(element.scrollLeft + element.clientWidth < element.scrollWidth - 1);
|
|
16
|
+
measure();
|
|
17
|
+
element.addEventListener("scroll", measure, { passive: true });
|
|
18
|
+
const observer = new ResizeObserver(measure);
|
|
19
|
+
observer.observe(element);
|
|
20
|
+
for (const child of element.children) observer.observe(child);
|
|
21
|
+
return () => {
|
|
22
|
+
element.removeEventListener("scroll", measure);
|
|
23
|
+
observer.disconnect();
|
|
24
|
+
};
|
|
25
|
+
}, [element]);
|
|
26
|
+
const mask = `linear-gradient(to right, #000 calc(100% - ${EDGE}), transparent)`;
|
|
27
|
+
const style = more ? { maskImage: mask, WebkitMaskImage: mask } : void 0;
|
|
28
|
+
return { ref, style };
|
|
29
|
+
};
|
|
9
30
|
var GAP = 3;
|
|
10
31
|
var RADIUS = 5;
|
|
11
32
|
var LABEL_GAP = 6;
|
|
33
|
+
var VALUE_PADDING = 4;
|
|
12
34
|
var TIP_GAP = 6;
|
|
13
35
|
var key = (row, column) => `${row}:${column}`;
|
|
14
|
-
var useLabelStride = (probe, gap) => {
|
|
36
|
+
var useLabelStride = (probe, valueProbe, gap) => {
|
|
15
37
|
const gridRef = useRef(null);
|
|
16
38
|
const probeRef = useRef(null);
|
|
39
|
+
const valueProbeRef = useRef(null);
|
|
17
40
|
const columnRef = useRef(null);
|
|
18
41
|
const [stride, setStride] = useState(1);
|
|
42
|
+
const [valuesFit, setValuesFit] = useState(true);
|
|
19
43
|
useLayoutEffect(() => {
|
|
20
44
|
const read = () => {
|
|
21
45
|
const label = probeRef.current?.offsetWidth ?? 0;
|
|
46
|
+
const value = valueProbeRef.current?.offsetWidth ?? 0;
|
|
22
47
|
const column = columnRef.current?.offsetWidth ?? 0;
|
|
23
48
|
setStride(column > 0 ? Math.max(1, Math.ceil((label + LABEL_GAP) / (column + gap))) : 1);
|
|
49
|
+
setValuesFit(column === 0 || value === 0 || value + VALUE_PADDING <= column);
|
|
24
50
|
};
|
|
25
51
|
read();
|
|
26
52
|
const observer = new ResizeObserver(read);
|
|
27
|
-
for (const el of [gridRef.current, probeRef.current])
|
|
53
|
+
for (const el of [gridRef.current, probeRef.current, valueProbeRef.current]) {
|
|
54
|
+
if (el) observer.observe(el);
|
|
55
|
+
}
|
|
28
56
|
return () => observer.disconnect();
|
|
29
|
-
}, [probe, gap]);
|
|
30
|
-
return { gridRef, probeRef, columnRef, stride };
|
|
57
|
+
}, [probe, valueProbe, gap]);
|
|
58
|
+
return { gridRef, probeRef, valueProbeRef, columnRef, stride, valuesFit };
|
|
31
59
|
};
|
|
32
60
|
var HeatGrid = ({
|
|
33
61
|
rows,
|
|
@@ -45,7 +73,16 @@ var HeatGrid = ({
|
|
|
45
73
|
}) => {
|
|
46
74
|
const frame = useRef(null);
|
|
47
75
|
const longest = columns.reduce((a, b) => b.length > a.length ? b : a, "");
|
|
48
|
-
const
|
|
76
|
+
const longestValue = cells.reduce((a, c) => (c.text ?? "").length > a.length ? c.text : a, "");
|
|
77
|
+
const {
|
|
78
|
+
gridRef,
|
|
79
|
+
probeRef,
|
|
80
|
+
valueProbeRef,
|
|
81
|
+
columnRef,
|
|
82
|
+
stride: measured,
|
|
83
|
+
valuesFit
|
|
84
|
+
} = useLabelStride(longest, longestValue, gap);
|
|
85
|
+
const fade = useEndFade();
|
|
49
86
|
const stride = thinLabels ? measured : 1;
|
|
50
87
|
const byPosition = new Map(cells.map((cell) => [key(cell.row, cell.column), cell]));
|
|
51
88
|
const cellsByRow = /* @__PURE__ */ new Map();
|
|
@@ -211,7 +248,7 @@ var HeatGrid = ({
|
|
|
211
248
|
outline: active ? `2px solid ${TEXT}` : "none",
|
|
212
249
|
zIndex: active ? 1 : void 0
|
|
213
250
|
},
|
|
214
|
-
children: cell.text
|
|
251
|
+
children: valuesFit && cell.text
|
|
215
252
|
},
|
|
216
253
|
position
|
|
217
254
|
);
|
|
@@ -255,6 +292,21 @@ var HeatGrid = ({
|
|
|
255
292
|
style: { position: "absolute", visibility: "hidden", whiteSpace: "nowrap" },
|
|
256
293
|
children: longest
|
|
257
294
|
}
|
|
295
|
+
),
|
|
296
|
+
/* @__PURE__ */ jsx(
|
|
297
|
+
"span",
|
|
298
|
+
{
|
|
299
|
+
ref: valueProbeRef,
|
|
300
|
+
"aria-hidden": true,
|
|
301
|
+
style: {
|
|
302
|
+
position: "absolute",
|
|
303
|
+
visibility: "hidden",
|
|
304
|
+
whiteSpace: "nowrap",
|
|
305
|
+
fontSize: "var(--text-2xs, 0.6875rem)",
|
|
306
|
+
fontWeight: 500
|
|
307
|
+
},
|
|
308
|
+
children: longestValue
|
|
309
|
+
}
|
|
258
310
|
)
|
|
259
311
|
]
|
|
260
312
|
}
|
|
@@ -263,7 +315,15 @@ var HeatGrid = ({
|
|
|
263
315
|
columnWidth ? (
|
|
264
316
|
// The padding leaves room for the focus outline of the cells at the edges,
|
|
265
317
|
// which the scrolling box would cut.
|
|
266
|
-
/* @__PURE__ */ jsx(
|
|
318
|
+
/* @__PURE__ */ jsx(
|
|
319
|
+
"div",
|
|
320
|
+
{
|
|
321
|
+
ref: fade.ref,
|
|
322
|
+
"data-heat-scroll": "",
|
|
323
|
+
style: { overflowX: "auto", padding: 3, ...fade.style },
|
|
324
|
+
children: grid
|
|
325
|
+
}
|
|
326
|
+
)
|
|
267
327
|
) : grid,
|
|
268
328
|
tip && tipStyle && /* @__PURE__ */ jsx("div", { "data-heat-tooltip": "", "aria-hidden": true, style: tipStyle, children: /* @__PURE__ */ jsx(
|
|
269
329
|
TooltipCard,
|
|
@@ -276,5 +336,5 @@ var HeatGrid = ({
|
|
|
276
336
|
};
|
|
277
337
|
|
|
278
338
|
export { HeatGrid };
|
|
279
|
-
//# sourceMappingURL=chunk-
|
|
280
|
-
//# sourceMappingURL=chunk-
|
|
339
|
+
//# sourceMappingURL=chunk-V56L4SNY.js.map
|
|
340
|
+
//# sourceMappingURL=chunk-V56L4SNY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/useEndFade.ts","../src/core/HeatGrid.tsx"],"names":["useState","cell"],"mappings":"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","file":"chunk-V56L4SNY.js","sourcesContent":["import { useEffect, useState, type CSSProperties } from 'react';\n\nconst EDGE = '1.5rem';\n\n/**\n * The style that fades the end of a box that scrolls sideways while there is more past it: a\n * hint that the content goes on, as the tables of cosmos-react give. Charts read left to right\n * whatever the page, so the end is the right edge. The start is left alone: it holds the row\n * labels, which stay in view. `undefined` while it all fits, and until the first measure. Attach\n * `ref` to the scrolling box.\n */\nexport const useEndFade = () => {\n const [element, ref] = useState<HTMLElement | null>(null);\n const [more, setMore] = useState(false);\n useEffect(() => {\n if (!element) return;\n const measure = () =>\n setMore(element.scrollLeft + element.clientWidth < element.scrollWidth - 1);\n measure();\n element.addEventListener('scroll', measure, { passive: true });\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n for (const child of element.children) observer.observe(child);\n return () => {\n element.removeEventListener('scroll', measure);\n observer.disconnect();\n };\n }, [element]);\n const mask = `linear-gradient(to right, #000 calc(100% - ${EDGE}), transparent)`;\n const style: CSSProperties | undefined = more\n ? { maskImage: mask, WebkitMaskImage: mask }\n : undefined;\n return { ref, style };\n};\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react';\nimport { TEXT_SIZE } from './axes';\nimport { TooltipCard } from './ChartTooltip';\nimport { MUTED, PANEL, TEXT } from './colors';\nimport { textOn } from './readable';\nimport { useEndFade } from './useEndFade';\n\n/** One cell of a `HeatGrid`. A slot with no cell stays empty. */\nexport type HeatCell = {\n /** Zero-based position: the index in `rows` and in `columns`. */\n row: number;\n column: number;\n /** Any CSS color. The text printed in the cell reads on it. */\n color: string;\n /** Heads the tooltip, such as the column's category. */\n title: string;\n /** Names the cell in the tooltip, such as the row. May be empty when the value says it all. */\n label: string;\n /** The value, formatted: the tooltip's value, and the end of the cell's accessible name. */\n value: string;\n /** Printed inside the cell. */\n text?: string;\n};\n\ntype HeatGridProps = {\n /** The label of each row, top to bottom. An empty string leaves the row unlabelled. */\n rows: readonly string[];\n /** The label of each column, left to right. Too many for the width: every n-th one is drawn. */\n columns: readonly string[];\n cells: readonly HeatCell[];\n /**\n * Height of a row in px. Without it the rows share the height of the\n * parent, which must then have one.\n */\n cellHeight?: number;\n /** Names the grid for screen readers. */\n ariaLabel: string;\n /** Title under the columns. Drawn as plain text. */\n xTitle?: string;\n /** Title beside the rows. Drawn as plain text. */\n yTitle?: string;\n /** Space between two cells in px. Default 3. */\n gap?: number;\n /** Corner radius of a cell in px. Default 5. */\n cellRadius?: number;\n /**\n * Width of a column in px. Without it the columns share the width of the\n * parent; with it they keep this width, and the grid scrolls sideways inside\n * its own box when it is wider than the parent. The row labels stay in view.\n */\n columnWidth?: number;\n /** Draw the column labels above the rows instead of under them. */\n labelsAbove?: boolean;\n /**\n * Draw every column label, as given. By default the labels are centered on\n * their column and every n-th one is drawn so that none touches the next.\n * Off, each starts at the left of its column and may run over the columns\n * after it, which an empty label leaves free: for labels such as the months\n * of a calendar, where the caller decides which columns carry one.\n */\n thinLabels?: boolean;\n};\n\nconst GAP = 3;\nconst RADIUS = 5;\n// Clear space kept between two column labels.\nconst LABEL_GAP = 6;\n// Clear space a value keeps inside its cell, both sides together.\nconst VALUE_PADDING = 4;\n// Room the tooltip card leaves the pointer or the cell.\nconst TIP_GAP = 6;\n\nconst key = (row: number, column: number) => `${row}:${column}`;\n\n/**\n * How many columns apart the labels are drawn so that none touches the next:\n * 1 when they all fit; and whether the longest value fits a cell, or the values\n * are left out rather than drawn cut. Measured on the page, since the text size,\n * the font and the width all change both.\n */\nconst useLabelStride = (probe: string, valueProbe: string, gap: number) => {\n const gridRef = useRef<HTMLDivElement>(null);\n const probeRef = useRef<HTMLSpanElement>(null);\n const valueProbeRef = useRef<HTMLSpanElement>(null);\n const columnRef = useRef<HTMLDivElement>(null);\n const [stride, setStride] = useState(1);\n const [valuesFit, setValuesFit] = useState(true);\n useLayoutEffect(() => {\n const read = () => {\n const label = probeRef.current?.offsetWidth ?? 0;\n const value = valueProbeRef.current?.offsetWidth ?? 0;\n const column = columnRef.current?.offsetWidth ?? 0;\n setStride(column > 0 ? Math.max(1, Math.ceil((label + LABEL_GAP) / (column + gap))) : 1);\n setValuesFit(column === 0 || value === 0 || value + VALUE_PADDING <= column);\n };\n read();\n const observer = new ResizeObserver(read);\n for (const el of [gridRef.current, probeRef.current, valueProbeRef.current]) {\n if (el) observer.observe(el);\n }\n return () => observer.disconnect();\n }, [probe, valueProbe, gap]);\n return { gridRef, probeRef, valueProbeRef, columnRef, stride, valuesFit };\n};\n\ntype Tip = {\n cell: HeatCell;\n /** Where the card is anchored, in px from the grid's corner, and on which side of the cell. */\n x: number;\n top: number;\n bottom: number;\n align: 'start' | 'center' | 'end';\n below: boolean;\n};\n\n/**\n * A grid of colored cells with row and column labels: the drawing of\n * `HeatmapChart`, and of any chart laid out as rows and columns. Recharts has\n * no such chart, so it is plain HTML in a CSS grid, which sizes the label\n * column to the text (it follows the text size) and the cells to the width.\n *\n * Keyboard: the grid is one tab stop (a roving tabindex), and the arrow keys\n * move between cells, skipping empty slots; Home and End go to the ends of the\n * row, Ctrl+Home and Ctrl+End to the first and last cell. The cell under the\n * pointer or the keyboard shows its tooltip. Each cell is named\n * `label, title: value`, so a screen reader reads what the tooltip says.\n */\nexport const HeatGrid = ({\n rows,\n columns,\n cells,\n cellHeight,\n ariaLabel,\n xTitle,\n yTitle,\n gap = GAP,\n cellRadius = RADIUS,\n columnWidth,\n labelsAbove = false,\n thinLabels = true,\n}: HeatGridProps) => {\n const frame = useRef<HTMLDivElement>(null);\n const longest = columns.reduce((a, b) => (b.length > a.length ? b : a), '');\n const longestValue = cells.reduce((a, c) => ((c.text ?? '').length > a.length ? c.text! : a), '');\n const {\n gridRef,\n probeRef,\n valueProbeRef,\n columnRef,\n stride: measured,\n valuesFit,\n } = useLabelStride(longest, longestValue, gap);\n const fade = useEndFade();\n const stride = thinLabels ? measured : 1;\n const byPosition = new Map(cells.map((cell) => [key(cell.row, cell.column), cell]));\n const cellsByRow = new Map<number, HeatCell[]>();\n for (const cell of cells) cellsByRow.set(cell.row, [...(cellsByRow.get(cell.row) ?? []), cell]);\n const inReadingOrder = [...cells].sort((a, b) => a.row - b.row || a.column - b.column);\n const [roving, setRoving] = useState<string>();\n // The cell that takes Tab: the last one focused, while it is still there.\n const first = inReadingOrder[0];\n const tabbable =\n roving && byPosition.has(roving) ? roving : first && key(first.row, first.column);\n const [hover, setHover] = useState<Tip>();\n const [focus, setFocus] = useState<Tip>();\n const tip = hover ?? focus;\n\n const tipFor = (cell: HeatCell, element: HTMLElement): Tip => {\n const host = (frame.current as HTMLElement).getBoundingClientRect();\n const box = element.getBoundingClientRect();\n const middle = box.left - host.left + box.width / 2;\n // The card hangs from the side of the cell nearest the middle of the grid,\n // so it never leaves the grid.\n const align =\n middle < host.width / 3 ? 'start' : middle > (2 * host.width) / 3 ? 'end' : 'center';\n return {\n cell,\n x: { start: box.left - host.left, center: middle, end: box.right - host.left }[align],\n top: box.top - host.top,\n bottom: box.bottom - host.top,\n align,\n // Not enough room above the cell for the card: it goes under.\n below: box.top - host.top < 90,\n };\n };\n\n const move = (event: KeyboardEvent<HTMLDivElement>) => {\n const origin = (event.target as HTMLElement).closest<HTMLElement>('[data-heat-cell]');\n if (!origin) return;\n const row = Number(origin.dataset.row);\n const column = Number(origin.dataset.column);\n // The next cell in a direction: empty slots are skipped, the edge stops.\n const step = (dRow: number, dColumn: number) => {\n for (\n let r = row + dRow, c = column + dColumn;\n r >= 0 && r < rows.length && c >= 0 && c < columns.length;\n r += dRow, c += dColumn\n ) {\n if (byPosition.has(key(r, c))) return key(r, c);\n }\n };\n const edge = (last: boolean) => {\n const pool = event.ctrlKey\n ? inReadingOrder\n : inReadingOrder.filter((cell) => cell.row === row);\n const cell = last ? pool.at(-1) : pool[0];\n return cell && key(cell.row, cell.column);\n };\n const targets: Record<string, () => string | undefined> = {\n ArrowRight: () => step(0, 1),\n ArrowLeft: () => step(0, -1),\n ArrowDown: () => step(1, 0),\n ArrowUp: () => step(-1, 0),\n Home: () => edge(false),\n End: () => edge(true),\n };\n const target = targets[event.key];\n if (!target) return;\n event.preventDefault();\n const next = target();\n if (next) gridRef.current?.querySelector<HTMLElement>(`[data-position=\"${next}\"]`)?.focus();\n };\n\n const focusIn = (cell: HeatCell, event: FocusEvent<HTMLElement>) => {\n setRoving(key(cell.row, cell.column));\n // A click focuses a cell too, and would leave its tooltip up: only the keyboard shows it.\n if (event.currentTarget.matches(':focus-visible')) {\n setFocus(tipFor(cell, event.currentTarget));\n }\n };\n const focusOut = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setFocus(undefined);\n };\n\n const rowOffset = yTitle ? 2 : 1;\n // The rows start under the labels when these sit above them.\n const top = labelsAbove ? 1 : 0;\n const labelsRow = labelsAbove ? 1 : rows.length + 1;\n const tipStyle: CSSProperties | undefined = tip && {\n position: 'absolute',\n left: tip.x,\n top: tip.below ? tip.bottom + TIP_GAP : tip.top - TIP_GAP,\n transform: `translate(${{ start: '0', center: '-50%', end: '-100%' }[tip.align]}, ${tip.below ? '0' : '-100%'})`,\n zIndex: 10,\n pointerEvents: 'none',\n };\n\n const grid = (\n <div\n ref={gridRef}\n role=\"grid\"\n aria-label={ariaLabel}\n onKeyDown={move}\n onBlur={focusOut}\n style={{\n display: 'grid',\n gridTemplateColumns: `${yTitle ? 'auto ' : ''}${columnWidth ? 'auto' : 'fit-content(40%)'} repeat(${columns.length}, ${columnWidth ? `${columnWidth}px` : 'minmax(0, 1fr)'})`,\n gridTemplateRows: `${labelsAbove ? 'auto ' : ''}repeat(${rows.length}, ${cellHeight ? `${cellHeight}px` : 'minmax(0, 1fr)'})${labelsAbove ? '' : ' auto'}${xTitle ? ' auto' : ''}`,\n gap,\n width: columnWidth ? 'max-content' : '100%',\n height: cellHeight ? undefined : '100%',\n fontSize: TEXT_SIZE,\n color: MUTED,\n }}\n >\n {yTitle && (\n <div\n aria-hidden\n style={{\n gridRow: `${1 + top} / ${rows.length + 1 + top}`,\n gridColumn: 1,\n writingMode: 'vertical-rl',\n transform: 'rotate(180deg)',\n textAlign: 'center',\n alignSelf: 'center',\n }}\n >\n {yTitle}\n </div>\n )}\n {rows.map((name, r) => (\n <div key={r} role=\"row\" style={{ display: 'contents' }}>\n <div\n aria-hidden\n data-heat-row=\"\"\n style={{\n gridRow: r + 1 + top,\n gridColumn: rowOffset,\n alignSelf: 'center',\n paddingRight: '0.5rem',\n // Stays in view when the grid scrolls sideways under it.\n ...(columnWidth ? { position: 'sticky', left: 0, zIndex: 2, background: PANEL } : {}),\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {name}\n </div>\n {(cellsByRow.get(r) ?? []).map((cell) => {\n const position = key(cell.row, cell.column);\n const active = tip?.cell === cell;\n return (\n <div\n key={position}\n role=\"gridcell\"\n data-heat-cell=\"\"\n data-position={position}\n data-row={cell.row}\n data-column={cell.column}\n tabIndex={position === tabbable ? 0 : -1}\n aria-label={`${cell.label ? `${cell.label}, ` : ''}${cell.title}: ${cell.value}`}\n onFocus={(event) => focusIn(cell, event)}\n onMouseEnter={(event) => setHover(tipFor(cell, event.currentTarget))}\n onMouseLeave={() => setHover(undefined)}\n style={{\n gridRow: r + 1 + top,\n gridColumn: cell.column + rowOffset + 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: 0,\n overflow: 'hidden',\n borderRadius: cellRadius,\n background: cell.color,\n color: textOn(cell.color),\n fontSize: 'var(--text-2xs, 0.6875rem)',\n fontWeight: 500,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n // The same ring for the pointer and the keyboard, in the text color\n // since an accent ring would vanish on the cells that are the accent.\n outline: active ? `2px solid ${TEXT}` : 'none',\n zIndex: active ? 1 : undefined,\n }}\n >\n {valuesFit && cell.text}\n </div>\n );\n })}\n </div>\n ))}\n {columns.map((name, c) => (\n <div\n key={c}\n ref={c === 0 ? columnRef : undefined}\n aria-hidden\n data-heat-column=\"\"\n style={{\n gridRow: labelsRow,\n gridColumn: c + rowOffset + 1,\n display: 'flex',\n justifyContent: thinLabels ? 'center' : 'flex-start',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n >\n {c % stride === 0 ? name : null}\n </div>\n ))}\n {xTitle && (\n <div\n aria-hidden\n style={{\n gridRow: (labelsAbove ? rows.length + 1 : labelsRow) + 1,\n gridColumn: `${rowOffset + 1} / -1`,\n textAlign: 'center',\n }}\n >\n {xTitle}\n </div>\n )}\n <span\n ref={probeRef}\n aria-hidden\n style={{ position: 'absolute', visibility: 'hidden', whiteSpace: 'nowrap' }}\n >\n {longest}\n </span>\n {/* In the font of a cell's value. */}\n <span\n ref={valueProbeRef}\n aria-hidden\n style={{\n position: 'absolute',\n visibility: 'hidden',\n whiteSpace: 'nowrap',\n fontSize: 'var(--text-2xs, 0.6875rem)',\n fontWeight: 500,\n }}\n >\n {longestValue}\n </span>\n </div>\n );\n\n return (\n <div ref={frame} style={{ position: 'relative', width: '100%', height: '100%', minWidth: 0 }}>\n {columnWidth ? (\n // The padding leaves room for the focus outline of the cells at the edges,\n // which the scrolling box would cut.\n <div\n ref={fade.ref}\n data-heat-scroll=\"\"\n style={{ overflowX: 'auto', padding: 3, ...fade.style }}\n >\n {grid}\n </div>\n ) : (\n grid\n )}\n {tip && tipStyle && (\n <div data-heat-tooltip=\"\" aria-hidden style={tipStyle}>\n <TooltipCard\n title={tip.cell.title}\n rows={[{ name: tip.cell.label, value: tip.cell.value, color: tip.cell.color }]}\n />\n </div>\n )}\n </div>\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sckyzo/cosmos-charts",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "React chart components for the Cosmos design system — themeable Recharts wrappers (bar, line, area, donut, radial gauges, sparkline, treemap, realtime, heatmap, radar, scatter, bubble, box plot, range bar, mixed) that follow the Cosmos theme and accent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SckyzO",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reference.tsx"],"names":[],"mappings":";;;;;;AAYA,IAAM,IAAA,GAAO,KAAA;AAEb,IAAM,UAAA,GAAa,EAAA;AAInB,IAAM,OAAA,GAAU,CAAC,KAAA,EAAe,QAAA,MAAkD;AAAA,EAChF,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,EAAW,0BAAA;AAAA,EACX,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,EAAE,QAAA,EAAU,SAAA;AACrB,CAAA,CAAA;AASO,IAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAiB,EAAC;AAAA,EAClB,iBAAiB,EAAC;AAAA,EAClB,IAAA,GAAO,GAAA;AAAA,EACP;AACF,CAAA,KAAwB;AACtB,EAAA,MAAM,MAAA,GAAS,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,GAAG,MAAA,EAAO;AACvE,EAAA,OAAO;AAAA,IACL,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACjC,MAAA,MAAM,CAAC,GAAA,EAAK,IAAI,IAAI,CAAC,IAAA,CAAK,IAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAC/E,MAAA,uBACE,GAAA;AAAA,QAAC,aAAA;AAAA,QAAA;AAAA,UAEE,GAAG,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,GAAA,EAAK,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,IAAA,EAAK;AAAA,UAC3C,GAAG,MAAA;AAAA,UACJ,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,UAC5C,WAAA,EAAa,IAAA;AAAA,UACb,UAAA,EAAW,cAAA;AAAA,UACX,MAAA,EAAQ,UAAA;AAAA,UACR,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,eAAe,CAAA,GAAI;AAAA,SAAA;AAAA,QAPtD,QAAQ,CAAC,CAAA;AAAA,OAQhB;AAAA,IAEJ,CAAC,CAAA;AAAA,IACD,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,qBAC3B,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QAEE,GAAG,EAAE,CAAC,IAAI,GAAG,KAAK,KAAA,EAAM;AAAA,QACxB,GAAG,MAAA;AAAA,QACJ,MAAA,EAAQ,aAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,QAC9C,WAAA,EAAa,GAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,MAAA;AAAA,QACtC,UAAA,EAAW,cAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,gBAAgB,CAAA,GAAI;AAAA,OAAA;AAAA,MAPvD,QAAQ,CAAC,CAAA;AAAA,KASjB;AAAA,GACH;AACF","file":"chunk-ESVGCUJN.js","sourcesContent":["import { ReferenceArea, ReferenceLine } from 'recharts';\nimport type { ChartReferenceProps } from '../types';\nimport { TEXT_SIZE } from './axes';\nimport { INTENT_COLORS, MUTED } from './colors';\n\ntype ReferenceOptions = ChartReferenceProps & {\n /** The axis the values are read on: `y` (default), or `x` on a chart of horizontal bars. */\n axis?: 'x' | 'y';\n /** The id of that axis, when the chart has several. */\n axisId?: string;\n};\n\nconst DASH = '6 4';\n// Behind the series (an area is at 100, a bar at 300) and above the grid.\nconst BAND_LAYER = 50;\n\n// Plain SVG text in the muted color: an amber or red label would not read on\n// the card in every theme, so the line and the band carry the intent.\nconst labelOf = (value: string, position: 'insideTopRight' | 'insideTopLeft') => ({\n value,\n position,\n className: 'recharts-reference-label',\n fill: MUTED,\n style: { fontSize: TEXT_SIZE },\n});\n\n/**\n * The `ReferenceArea`s then the `ReferenceLine`s of a chart's `referenceBands`\n * and `referenceLines`, to render inside it, before `children`. A mark outside\n * the data makes the axis reach it (`ifOverflow=\"extendDomain\"`) instead of\n * vanishing. Colors come from `INTENT_COLORS`, so a theme switch repaints\n * them; labels are text, not markup.\n */\nexport const referenceMarks = ({\n referenceLines = [],\n referenceBands = [],\n axis = 'y',\n axisId,\n}: ReferenceOptions) => {\n const onAxis = axisId === undefined ? {} : { [`${axis}AxisId`]: axisId };\n return [\n ...referenceBands.map((band, i) => {\n const [low, high] = [Math.min(band.from, band.to), Math.max(band.from, band.to)];\n return (\n <ReferenceArea\n key={`band-${i}`}\n {...{ [`${axis}1`]: low, [`${axis}2`]: high }}\n {...onAxis}\n fill={INTENT_COLORS[band.intent ?? 'neutral']}\n fillOpacity={0.14}\n ifOverflow=\"extendDomain\"\n zIndex={BAND_LAYER}\n label={band.label ? labelOf(band.label, 'insideTopLeft') : undefined}\n />\n );\n }),\n ...referenceLines.map((line, i) => (\n <ReferenceLine\n key={`line-${i}`}\n {...{ [axis]: line.value }}\n {...onAxis}\n stroke={INTENT_COLORS[line.intent ?? 'neutral']}\n strokeWidth={1.5}\n strokeDasharray={line.dashed ? DASH : undefined}\n ifOverflow=\"extendDomain\"\n label={line.label ? labelOf(line.label, 'insideTopRight') : undefined}\n />\n )),\n ];\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/HeatGrid.tsx"],"names":["cell"],"mappings":"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","file":"chunk-UL3SNXQR.js","sourcesContent":["import {\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n} from 'react';\nimport { TEXT_SIZE } from './axes';\nimport { TooltipCard } from './ChartTooltip';\nimport { MUTED, PANEL, TEXT } from './colors';\nimport { textOn } from './readable';\n\n/** One cell of a `HeatGrid`. A slot with no cell stays empty. */\nexport type HeatCell = {\n /** Zero-based position: the index in `rows` and in `columns`. */\n row: number;\n column: number;\n /** Any CSS color. The text printed in the cell reads on it. */\n color: string;\n /** Heads the tooltip, such as the column's category. */\n title: string;\n /** Names the cell in the tooltip, such as the row. May be empty when the value says it all. */\n label: string;\n /** The value, formatted: the tooltip's value, and the end of the cell's accessible name. */\n value: string;\n /** Printed inside the cell. */\n text?: string;\n};\n\ntype HeatGridProps = {\n /** The label of each row, top to bottom. An empty string leaves the row unlabelled. */\n rows: readonly string[];\n /** The label of each column, left to right. Too many for the width: every n-th one is drawn. */\n columns: readonly string[];\n cells: readonly HeatCell[];\n /**\n * Height of a row in px. Without it the rows share the height of the\n * parent, which must then have one.\n */\n cellHeight?: number;\n /** Names the grid for screen readers. */\n ariaLabel: string;\n /** Title under the columns. Drawn as plain text. */\n xTitle?: string;\n /** Title beside the rows. Drawn as plain text. */\n yTitle?: string;\n /** Space between two cells in px. Default 3. */\n gap?: number;\n /** Corner radius of a cell in px. Default 5. */\n cellRadius?: number;\n /**\n * Width of a column in px. Without it the columns share the width of the\n * parent; with it they keep this width, and the grid scrolls sideways inside\n * its own box when it is wider than the parent. The row labels stay in view.\n */\n columnWidth?: number;\n /** Draw the column labels above the rows instead of under them. */\n labelsAbove?: boolean;\n /**\n * Draw every column label, as given. By default the labels are centered on\n * their column and every n-th one is drawn so that none touches the next.\n * Off, each starts at the left of its column and may run over the columns\n * after it, which an empty label leaves free: for labels such as the months\n * of a calendar, where the caller decides which columns carry one.\n */\n thinLabels?: boolean;\n};\n\nconst GAP = 3;\nconst RADIUS = 5;\n// Clear space kept between two column labels.\nconst LABEL_GAP = 6;\n// Room the tooltip card leaves the pointer or the cell.\nconst TIP_GAP = 6;\n\nconst key = (row: number, column: number) => `${row}:${column}`;\n\n/**\n * How many columns apart the labels are drawn so that none touches the next:\n * 1 when they all fit. Measured on the page, since the text size, the font and\n * the width all change it.\n */\nconst useLabelStride = (probe: string, gap: number) => {\n const gridRef = useRef<HTMLDivElement>(null);\n const probeRef = useRef<HTMLSpanElement>(null);\n const columnRef = useRef<HTMLDivElement>(null);\n const [stride, setStride] = useState(1);\n useLayoutEffect(() => {\n const read = () => {\n const label = probeRef.current?.offsetWidth ?? 0;\n const column = columnRef.current?.offsetWidth ?? 0;\n setStride(column > 0 ? Math.max(1, Math.ceil((label + LABEL_GAP) / (column + gap))) : 1);\n };\n read();\n const observer = new ResizeObserver(read);\n for (const el of [gridRef.current, probeRef.current]) if (el) observer.observe(el);\n return () => observer.disconnect();\n }, [probe, gap]);\n return { gridRef, probeRef, columnRef, stride };\n};\n\ntype Tip = {\n cell: HeatCell;\n /** Where the card is anchored, in px from the grid's corner, and on which side of the cell. */\n x: number;\n top: number;\n bottom: number;\n align: 'start' | 'center' | 'end';\n below: boolean;\n};\n\n/**\n * A grid of colored cells with row and column labels: the drawing of\n * `HeatmapChart`, and of any chart laid out as rows and columns. Recharts has\n * no such chart, so it is plain HTML in a CSS grid, which sizes the label\n * column to the text (it follows the text size) and the cells to the width.\n *\n * Keyboard: the grid is one tab stop (a roving tabindex), and the arrow keys\n * move between cells, skipping empty slots; Home and End go to the ends of the\n * row, Ctrl+Home and Ctrl+End to the first and last cell. The cell under the\n * pointer or the keyboard shows its tooltip. Each cell is named\n * `label, title: value`, so a screen reader reads what the tooltip says.\n */\nexport const HeatGrid = ({\n rows,\n columns,\n cells,\n cellHeight,\n ariaLabel,\n xTitle,\n yTitle,\n gap = GAP,\n cellRadius = RADIUS,\n columnWidth,\n labelsAbove = false,\n thinLabels = true,\n}: HeatGridProps) => {\n const frame = useRef<HTMLDivElement>(null);\n const longest = columns.reduce((a, b) => (b.length > a.length ? b : a), '');\n const { gridRef, probeRef, columnRef, stride: measured } = useLabelStride(longest, gap);\n const stride = thinLabels ? measured : 1;\n const byPosition = new Map(cells.map((cell) => [key(cell.row, cell.column), cell]));\n const cellsByRow = new Map<number, HeatCell[]>();\n for (const cell of cells) cellsByRow.set(cell.row, [...(cellsByRow.get(cell.row) ?? []), cell]);\n const inReadingOrder = [...cells].sort((a, b) => a.row - b.row || a.column - b.column);\n const [roving, setRoving] = useState<string>();\n // The cell that takes Tab: the last one focused, while it is still there.\n const first = inReadingOrder[0];\n const tabbable =\n roving && byPosition.has(roving) ? roving : first && key(first.row, first.column);\n const [hover, setHover] = useState<Tip>();\n const [focus, setFocus] = useState<Tip>();\n const tip = hover ?? focus;\n\n const tipFor = (cell: HeatCell, element: HTMLElement): Tip => {\n const host = (frame.current as HTMLElement).getBoundingClientRect();\n const box = element.getBoundingClientRect();\n const middle = box.left - host.left + box.width / 2;\n // The card hangs from the side of the cell nearest the middle of the grid,\n // so it never leaves the grid.\n const align =\n middle < host.width / 3 ? 'start' : middle > (2 * host.width) / 3 ? 'end' : 'center';\n return {\n cell,\n x: { start: box.left - host.left, center: middle, end: box.right - host.left }[align],\n top: box.top - host.top,\n bottom: box.bottom - host.top,\n align,\n // Not enough room above the cell for the card: it goes under.\n below: box.top - host.top < 90,\n };\n };\n\n const move = (event: KeyboardEvent<HTMLDivElement>) => {\n const origin = (event.target as HTMLElement).closest<HTMLElement>('[data-heat-cell]');\n if (!origin) return;\n const row = Number(origin.dataset.row);\n const column = Number(origin.dataset.column);\n // The next cell in a direction: empty slots are skipped, the edge stops.\n const step = (dRow: number, dColumn: number) => {\n for (\n let r = row + dRow, c = column + dColumn;\n r >= 0 && r < rows.length && c >= 0 && c < columns.length;\n r += dRow, c += dColumn\n ) {\n if (byPosition.has(key(r, c))) return key(r, c);\n }\n };\n const edge = (last: boolean) => {\n const pool = event.ctrlKey\n ? inReadingOrder\n : inReadingOrder.filter((cell) => cell.row === row);\n const cell = last ? pool.at(-1) : pool[0];\n return cell && key(cell.row, cell.column);\n };\n const targets: Record<string, () => string | undefined> = {\n ArrowRight: () => step(0, 1),\n ArrowLeft: () => step(0, -1),\n ArrowDown: () => step(1, 0),\n ArrowUp: () => step(-1, 0),\n Home: () => edge(false),\n End: () => edge(true),\n };\n const target = targets[event.key];\n if (!target) return;\n event.preventDefault();\n const next = target();\n if (next) gridRef.current?.querySelector<HTMLElement>(`[data-position=\"${next}\"]`)?.focus();\n };\n\n const focusIn = (cell: HeatCell, event: FocusEvent<HTMLElement>) => {\n setRoving(key(cell.row, cell.column));\n // A click focuses a cell too, and would leave its tooltip up: only the keyboard shows it.\n if (event.currentTarget.matches(':focus-visible')) {\n setFocus(tipFor(cell, event.currentTarget));\n }\n };\n const focusOut = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setFocus(undefined);\n };\n\n const rowOffset = yTitle ? 2 : 1;\n // The rows start under the labels when these sit above them.\n const top = labelsAbove ? 1 : 0;\n const labelsRow = labelsAbove ? 1 : rows.length + 1;\n const tipStyle: CSSProperties | undefined = tip && {\n position: 'absolute',\n left: tip.x,\n top: tip.below ? tip.bottom + TIP_GAP : tip.top - TIP_GAP,\n transform: `translate(${{ start: '0', center: '-50%', end: '-100%' }[tip.align]}, ${tip.below ? '0' : '-100%'})`,\n zIndex: 10,\n pointerEvents: 'none',\n };\n\n const grid = (\n <div\n ref={gridRef}\n role=\"grid\"\n aria-label={ariaLabel}\n onKeyDown={move}\n onBlur={focusOut}\n style={{\n display: 'grid',\n gridTemplateColumns: `${yTitle ? 'auto ' : ''}${columnWidth ? 'auto' : 'fit-content(40%)'} repeat(${columns.length}, ${columnWidth ? `${columnWidth}px` : 'minmax(0, 1fr)'})`,\n gridTemplateRows: `${labelsAbove ? 'auto ' : ''}repeat(${rows.length}, ${cellHeight ? `${cellHeight}px` : 'minmax(0, 1fr)'})${labelsAbove ? '' : ' auto'}${xTitle ? ' auto' : ''}`,\n gap,\n width: columnWidth ? 'max-content' : '100%',\n height: cellHeight ? undefined : '100%',\n fontSize: TEXT_SIZE,\n color: MUTED,\n }}\n >\n {yTitle && (\n <div\n aria-hidden\n style={{\n gridRow: `${1 + top} / ${rows.length + 1 + top}`,\n gridColumn: 1,\n writingMode: 'vertical-rl',\n transform: 'rotate(180deg)',\n textAlign: 'center',\n alignSelf: 'center',\n }}\n >\n {yTitle}\n </div>\n )}\n {rows.map((name, r) => (\n <div key={r} role=\"row\" style={{ display: 'contents' }}>\n <div\n aria-hidden\n data-heat-row=\"\"\n style={{\n gridRow: r + 1 + top,\n gridColumn: rowOffset,\n alignSelf: 'center',\n paddingRight: '0.5rem',\n // Stays in view when the grid scrolls sideways under it.\n ...(columnWidth ? { position: 'sticky', left: 0, zIndex: 2, background: PANEL } : {}),\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {name}\n </div>\n {(cellsByRow.get(r) ?? []).map((cell) => {\n const position = key(cell.row, cell.column);\n const active = tip?.cell === cell;\n return (\n <div\n key={position}\n role=\"gridcell\"\n data-heat-cell=\"\"\n data-position={position}\n data-row={cell.row}\n data-column={cell.column}\n tabIndex={position === tabbable ? 0 : -1}\n aria-label={`${cell.label ? `${cell.label}, ` : ''}${cell.title}: ${cell.value}`}\n onFocus={(event) => focusIn(cell, event)}\n onMouseEnter={(event) => setHover(tipFor(cell, event.currentTarget))}\n onMouseLeave={() => setHover(undefined)}\n style={{\n gridRow: r + 1 + top,\n gridColumn: cell.column + rowOffset + 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: 0,\n overflow: 'hidden',\n borderRadius: cellRadius,\n background: cell.color,\n color: textOn(cell.color),\n fontSize: 'var(--text-2xs, 0.6875rem)',\n fontWeight: 500,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n // The same ring for the pointer and the keyboard, in the text color\n // since an accent ring would vanish on the cells that are the accent.\n outline: active ? `2px solid ${TEXT}` : 'none',\n zIndex: active ? 1 : undefined,\n }}\n >\n {cell.text}\n </div>\n );\n })}\n </div>\n ))}\n {columns.map((name, c) => (\n <div\n key={c}\n ref={c === 0 ? columnRef : undefined}\n aria-hidden\n data-heat-column=\"\"\n style={{\n gridRow: labelsRow,\n gridColumn: c + rowOffset + 1,\n display: 'flex',\n justifyContent: thinLabels ? 'center' : 'flex-start',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n >\n {c % stride === 0 ? name : null}\n </div>\n ))}\n {xTitle && (\n <div\n aria-hidden\n style={{\n gridRow: (labelsAbove ? rows.length + 1 : labelsRow) + 1,\n gridColumn: `${rowOffset + 1} / -1`,\n textAlign: 'center',\n }}\n >\n {xTitle}\n </div>\n )}\n <span\n ref={probeRef}\n aria-hidden\n style={{ position: 'absolute', visibility: 'hidden', whiteSpace: 'nowrap' }}\n >\n {longest}\n </span>\n </div>\n );\n\n return (\n <div ref={frame} style={{ position: 'relative', width: '100%', height: '100%', minWidth: 0 }}>\n {columnWidth ? (\n // The padding leaves room for the focus outline of the cells at the edges,\n // which the scrolling box would cut.\n <div data-heat-scroll=\"\" style={{ overflowX: 'auto', padding: 3 }}>\n {grid}\n </div>\n ) : (\n grid\n )}\n {tip && tipStyle && (\n <div data-heat-tooltip=\"\" aria-hidden style={tipStyle}>\n <TooltipCard\n title={tip.cell.title}\n rows={[{ name: tip.cell.label, value: tip.cell.value, color: tip.cell.color }]}\n />\n </div>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reference.tsx"],"names":["MUTED","TEXT_SIZE","jsx","ReferenceArea","INTENT_COLORS","ReferenceLine"],"mappings":";;;;;;;;AAYA,IAAM,IAAA,GAAO,KAAA;AAEb,IAAM,UAAA,GAAa,EAAA;AAInB,IAAM,OAAA,GAAU,CAAC,KAAA,EAAe,QAAA,MAAkD;AAAA,EAChF,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,EAAW,0BAAA;AAAA,EACX,IAAA,EAAMA,uBAAA;AAAA,EACN,KAAA,EAAO,EAAE,QAAA,EAAUC,2BAAA;AACrB,CAAA,CAAA;AASO,IAAM,iBAAiB,CAAC;AAAA,EAC7B,iBAAiB,EAAC;AAAA,EAClB,iBAAiB,EAAC;AAAA,EAClB,IAAA,GAAO,GAAA;AAAA,EACP;AACF,CAAA,KAAwB;AACtB,EAAA,MAAM,MAAA,GAAS,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,GAAG,MAAA,EAAO;AACvE,EAAA,OAAO;AAAA,IACL,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACjC,MAAA,MAAM,CAAC,GAAA,EAAK,IAAI,IAAI,CAAC,IAAA,CAAK,IAAI,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAC/E,MAAA,uBACEC,cAAA;AAAA,QAACC,sBAAA;AAAA,QAAA;AAAA,UAEE,GAAG,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,GAAA,EAAK,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,GAAG,IAAA,EAAK;AAAA,UAC3C,GAAG,MAAA;AAAA,UACJ,IAAA,EAAMC,+BAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,UAC5C,WAAA,EAAa,IAAA;AAAA,UACb,UAAA,EAAW,cAAA;AAAA,UACX,MAAA,EAAQ,UAAA;AAAA,UACR,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,eAAe,CAAA,GAAI;AAAA,SAAA;AAAA,QAPtD,QAAQ,CAAC,CAAA;AAAA,OAQhB;AAAA,IAEJ,CAAC,CAAA;AAAA,IACD,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,qBAC3BF,cAAA;AAAA,MAACG,sBAAA;AAAA,MAAA;AAAA,QAEE,GAAG,EAAE,CAAC,IAAI,GAAG,KAAK,KAAA,EAAM;AAAA,QACxB,GAAG,MAAA;AAAA,QACJ,MAAA,EAAQD,+BAAA,CAAc,IAAA,CAAK,MAAA,IAAU,SAAS,CAAA;AAAA,QAC9C,WAAA,EAAa,GAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,MAAA;AAAA,QACtC,UAAA,EAAW,cAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA,GAAQ,QAAQ,IAAA,CAAK,KAAA,EAAO,gBAAgB,CAAA,GAAI;AAAA,OAAA;AAAA,MAPvD,QAAQ,CAAC,CAAA;AAAA,KASjB;AAAA,GACH;AACF","file":"chunk-XUGQ6VXO.cjs","sourcesContent":["import { ReferenceArea, ReferenceLine } from 'recharts';\nimport type { ChartReferenceProps } from '../types';\nimport { TEXT_SIZE } from './axes';\nimport { INTENT_COLORS, MUTED } from './colors';\n\ntype ReferenceOptions = ChartReferenceProps & {\n /** The axis the values are read on: `y` (default), or `x` on a chart of horizontal bars. */\n axis?: 'x' | 'y';\n /** The id of that axis, when the chart has several. */\n axisId?: string;\n};\n\nconst DASH = '6 4';\n// Behind the series (an area is at 100, a bar at 300) and above the grid.\nconst BAND_LAYER = 50;\n\n// Plain SVG text in the muted color: an amber or red label would not read on\n// the card in every theme, so the line and the band carry the intent.\nconst labelOf = (value: string, position: 'insideTopRight' | 'insideTopLeft') => ({\n value,\n position,\n className: 'recharts-reference-label',\n fill: MUTED,\n style: { fontSize: TEXT_SIZE },\n});\n\n/**\n * The `ReferenceArea`s then the `ReferenceLine`s of a chart's `referenceBands`\n * and `referenceLines`, to render inside it, before `children`. A mark outside\n * the data makes the axis reach it (`ifOverflow=\"extendDomain\"`) instead of\n * vanishing. Colors come from `INTENT_COLORS`, so a theme switch repaints\n * them; labels are text, not markup.\n */\nexport const referenceMarks = ({\n referenceLines = [],\n referenceBands = [],\n axis = 'y',\n axisId,\n}: ReferenceOptions) => {\n const onAxis = axisId === undefined ? {} : { [`${axis}AxisId`]: axisId };\n return [\n ...referenceBands.map((band, i) => {\n const [low, high] = [Math.min(band.from, band.to), Math.max(band.from, band.to)];\n return (\n <ReferenceArea\n key={`band-${i}`}\n {...{ [`${axis}1`]: low, [`${axis}2`]: high }}\n {...onAxis}\n fill={INTENT_COLORS[band.intent ?? 'neutral']}\n fillOpacity={0.14}\n ifOverflow=\"extendDomain\"\n zIndex={BAND_LAYER}\n label={band.label ? labelOf(band.label, 'insideTopLeft') : undefined}\n />\n );\n }),\n ...referenceLines.map((line, i) => (\n <ReferenceLine\n key={`line-${i}`}\n {...{ [axis]: line.value }}\n {...onAxis}\n stroke={INTENT_COLORS[line.intent ?? 'neutral']}\n strokeWidth={1.5}\n strokeDasharray={line.dashed ? DASH : undefined}\n ifOverflow=\"extendDomain\"\n label={line.label ? labelOf(line.label, 'insideTopRight') : undefined}\n />\n )),\n ];\n};\n"]}
|