@mantine/charts 9.5.1 → 9.6.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/cjs/AreaChart/AreaChart.cjs +49 -11
- package/cjs/AreaChart/AreaChart.cjs.map +1 -1
- package/cjs/AreaChart/AreaGradient.cjs.map +1 -1
- package/cjs/AreaChart/AreaSplit.cjs.map +1 -1
- package/cjs/BarChart/BarChart.cjs +44 -6
- package/cjs/BarChart/BarChart.cjs.map +1 -1
- package/cjs/BarsList/BarsList.cjs.map +1 -1
- package/cjs/BubbleChart/BubbleChart.cjs.map +1 -1
- package/cjs/BulletChart/BulletChart.cjs +7 -5
- package/cjs/BulletChart/BulletChart.cjs.map +1 -1
- package/cjs/CandlestickChart/CandlestickChart.cjs +340 -0
- package/cjs/CandlestickChart/CandlestickChart.cjs.map +1 -0
- package/cjs/CandlestickChart/get-candle-geometry/get-candle-geometry.cjs +30 -0
- package/cjs/CandlestickChart/get-candle-geometry/get-candle-geometry.cjs.map +1 -0
- package/cjs/CandlestickChart/get-candlestick-domain/get-candlestick-domain.cjs +40 -0
- package/cjs/CandlestickChart/get-candlestick-domain/get-candlestick-domain.cjs.map +1 -0
- package/cjs/ChartBrush/ChartBrush.cjs.map +1 -1
- package/cjs/ChartLegend/ChartLegend.cjs.map +1 -1
- package/cjs/ChartTooltip/ChartTooltip.cjs.map +1 -1
- package/cjs/CompositeChart/CompositeChart.cjs +44 -6
- package/cjs/CompositeChart/CompositeChart.cjs.map +1 -1
- package/cjs/DonutChart/DonutChart.cjs.map +1 -1
- package/cjs/FunnelChart/FunnelChart.cjs.map +1 -1
- package/cjs/GaugeChart/GaugeChart.cjs +208 -0
- package/cjs/GaugeChart/GaugeChart.cjs.map +1 -0
- package/cjs/GaugeChart/GaugeChart.module.cjs +10 -0
- package/cjs/GaugeChart/GaugeChart.module.cjs.map +1 -0
- package/cjs/Heatmap/Heatmap.cjs +5 -2
- package/cjs/Heatmap/Heatmap.cjs.map +1 -1
- package/cjs/Heatmap/HeatmapSplitWeeks.cjs +2 -1
- package/cjs/Heatmap/HeatmapSplitWeeks.cjs.map +1 -1
- package/cjs/Heatmap/HeatmapWeeks.cjs.map +1 -1
- package/cjs/LineChart/LineChart.cjs +44 -6
- package/cjs/LineChart/LineChart.cjs.map +1 -1
- package/cjs/MatrixChart/MatrixChart.cjs +211 -0
- package/cjs/MatrixChart/MatrixChart.cjs.map +1 -0
- package/cjs/MatrixChart/MatrixChart.module.cjs +14 -0
- package/cjs/MatrixChart/MatrixChart.module.cjs.map +1 -0
- package/cjs/MatrixChart/build-cell-map/build-cell-map.cjs +17 -0
- package/cjs/MatrixChart/build-cell-map/build-cell-map.cjs.map +1 -0
- package/cjs/MatrixChart/get-domain/get-domain.cjs +28 -0
- package/cjs/MatrixChart/get-domain/get-domain.cjs.map +1 -0
- package/cjs/MatrixChart/get-legend-width/get-legend-width.cjs +15 -0
- package/cjs/MatrixChart/get-legend-width/get-legend-width.cjs.map +1 -0
- package/cjs/MatrixChart/get-unique-values/get-unique-values.cjs +19 -0
- package/cjs/MatrixChart/get-unique-values/get-unique-values.cjs.map +1 -0
- package/cjs/PieChart/PieChart.cjs +2 -1
- package/cjs/PieChart/PieChart.cjs.map +1 -1
- package/cjs/PointLabel/PointLabel.cjs.map +1 -1
- package/cjs/RadarChart/RadarChart.cjs.map +1 -1
- package/cjs/RadialBarChart/RadialBarChart.cjs.map +1 -1
- package/cjs/SankeyChart/SankeyChart.cjs.map +1 -1
- package/cjs/ScatterChart/ScatterChart.cjs +43 -7
- package/cjs/ScatterChart/ScatterChart.cjs.map +1 -1
- package/cjs/Sparkline/Sparkline.cjs.map +1 -1
- package/cjs/SunburstChart/SunburstChart.cjs.map +1 -1
- package/cjs/Treemap/Treemap.cjs.map +1 -1
- package/cjs/WaffleChart/WaffleChart.cjs +189 -0
- package/cjs/WaffleChart/WaffleChart.cjs.map +1 -0
- package/cjs/WaffleChart/WaffleChart.module.cjs +14 -0
- package/cjs/WaffleChart/WaffleChart.module.cjs.map +1 -0
- package/cjs/_virtual/_rolldown/runtime.cjs +1 -1
- package/cjs/index.cjs +8 -0
- package/cjs/utils/get-pie-chart-data/get-pie-chart-data.cjs.map +1 -1
- package/esm/AreaChart/AreaChart.mjs +50 -12
- package/esm/AreaChart/AreaChart.mjs.map +1 -1
- package/esm/AreaChart/AreaGradient.mjs.map +1 -1
- package/esm/AreaChart/AreaSplit.mjs.map +1 -1
- package/esm/BarChart/BarChart.mjs +45 -7
- package/esm/BarChart/BarChart.mjs.map +1 -1
- package/esm/BarsList/BarsList.mjs.map +1 -1
- package/esm/BubbleChart/BubbleChart.mjs.map +1 -1
- package/esm/BulletChart/BulletChart.mjs +7 -5
- package/esm/BulletChart/BulletChart.mjs.map +1 -1
- package/esm/CandlestickChart/CandlestickChart.mjs +340 -0
- package/esm/CandlestickChart/CandlestickChart.mjs.map +1 -0
- package/esm/CandlestickChart/get-candle-geometry/get-candle-geometry.mjs +30 -0
- package/esm/CandlestickChart/get-candle-geometry/get-candle-geometry.mjs.map +1 -0
- package/esm/CandlestickChart/get-candlestick-domain/get-candlestick-domain.mjs +39 -0
- package/esm/CandlestickChart/get-candlestick-domain/get-candlestick-domain.mjs.map +1 -0
- package/esm/ChartLegend/ChartLegend.mjs.map +1 -1
- package/esm/ChartTooltip/ChartTooltip.mjs.map +1 -1
- package/esm/CompositeChart/CompositeChart.mjs +45 -7
- package/esm/CompositeChart/CompositeChart.mjs.map +1 -1
- package/esm/DonutChart/DonutChart.mjs.map +1 -1
- package/esm/FunnelChart/FunnelChart.mjs.map +1 -1
- package/esm/GaugeChart/GaugeChart.mjs +208 -0
- package/esm/GaugeChart/GaugeChart.mjs.map +1 -0
- package/esm/GaugeChart/GaugeChart.module.mjs +10 -0
- package/esm/GaugeChart/GaugeChart.module.mjs.map +1 -0
- package/esm/Heatmap/Heatmap.mjs +5 -2
- package/esm/Heatmap/Heatmap.mjs.map +1 -1
- package/esm/Heatmap/HeatmapSplitWeeks.mjs +2 -1
- package/esm/Heatmap/HeatmapSplitWeeks.mjs.map +1 -1
- package/esm/Heatmap/HeatmapWeeks.mjs.map +1 -1
- package/esm/LineChart/LineChart.mjs +45 -7
- package/esm/LineChart/LineChart.mjs.map +1 -1
- package/esm/MatrixChart/MatrixChart.mjs +211 -0
- package/esm/MatrixChart/MatrixChart.mjs.map +1 -0
- package/esm/MatrixChart/MatrixChart.module.mjs +14 -0
- package/esm/MatrixChart/MatrixChart.module.mjs.map +1 -0
- package/esm/MatrixChart/build-cell-map/build-cell-map.mjs +16 -0
- package/esm/MatrixChart/build-cell-map/build-cell-map.mjs.map +1 -0
- package/esm/MatrixChart/get-domain/get-domain.mjs +28 -0
- package/esm/MatrixChart/get-domain/get-domain.mjs.map +1 -0
- package/esm/MatrixChart/get-legend-width/get-legend-width.mjs +15 -0
- package/esm/MatrixChart/get-legend-width/get-legend-width.mjs.map +1 -0
- package/esm/MatrixChart/get-unique-values/get-unique-values.mjs +19 -0
- package/esm/MatrixChart/get-unique-values/get-unique-values.mjs.map +1 -0
- package/esm/PieChart/PieChart.mjs +2 -1
- package/esm/PieChart/PieChart.mjs.map +1 -1
- package/esm/PointLabel/PointLabel.mjs.map +1 -1
- package/esm/RadarChart/RadarChart.mjs.map +1 -1
- package/esm/RadialBarChart/RadialBarChart.mjs.map +1 -1
- package/esm/SankeyChart/SankeyChart.mjs.map +1 -1
- package/esm/ScatterChart/ScatterChart.mjs +44 -8
- package/esm/ScatterChart/ScatterChart.mjs.map +1 -1
- package/esm/Sparkline/Sparkline.mjs.map +1 -1
- package/esm/SunburstChart/SunburstChart.mjs.map +1 -1
- package/esm/Treemap/Treemap.mjs.map +1 -1
- package/esm/WaffleChart/WaffleChart.mjs +189 -0
- package/esm/WaffleChart/WaffleChart.mjs.map +1 -0
- package/esm/WaffleChart/WaffleChart.module.mjs +14 -0
- package/esm/WaffleChart/WaffleChart.module.mjs.map +1 -0
- package/esm/index.mjs +5 -1
- package/lib/AreaChart/AreaChart.d.ts +7 -3
- package/lib/AreaChart/AreaGradient.d.ts +1 -1
- package/lib/AreaChart/AreaSplit.d.ts +1 -1
- package/lib/CandlestickChart/CandlestickChart.d.ts +68 -0
- package/lib/CandlestickChart/get-candle-geometry/get-candle-geometry.d.ts +30 -0
- package/lib/CandlestickChart/get-candlestick-domain/get-candlestick-domain.d.ts +21 -0
- package/lib/CandlestickChart/index.d.ts +3 -0
- package/lib/GaugeChart/GaugeChart.d.ts +57 -0
- package/lib/GaugeChart/index.d.ts +10 -0
- package/lib/Heatmap/HeatmapSplitWeeks.d.ts +1 -1
- package/lib/Heatmap/HeatmapWeeks.d.ts +1 -1
- package/lib/MatrixChart/MatrixChart.d.ts +64 -0
- package/lib/MatrixChart/build-cell-map/build-cell-map.d.ts +3 -0
- package/lib/MatrixChart/get-domain/get-domain.d.ts +10 -0
- package/lib/MatrixChart/get-legend-width/get-legend-width.d.ts +9 -0
- package/lib/MatrixChart/get-unique-values/get-unique-values.d.ts +2 -0
- package/lib/MatrixChart/index.d.ts +8 -0
- package/lib/PointLabel/PointLabel.d.ts +1 -1
- package/lib/WaffleChart/WaffleChart.d.ts +57 -0
- package/lib/WaffleChart/index.d.ts +10 -0
- package/lib/index.d.mts +4 -0
- package/lib/index.d.ts +4 -0
- package/lib/types.d.ts +16 -2
- package/package.json +5 -5
- package/styles.css +109 -0
- package/styles.layer.css +109 -0
package/esm/Heatmap/Heatmap.mjs
CHANGED
|
@@ -105,7 +105,8 @@ const Heatmap = factory((_props) => {
|
|
|
105
105
|
const computeMonthLabelX = (monthPosition, monthIndex) => {
|
|
106
106
|
if (!splitMonths) return monthPosition * rectSizeWithGap + gap + weekdaysOffset;
|
|
107
107
|
const firstMonth = monthsRange[monthIndex];
|
|
108
|
-
const
|
|
108
|
+
const columns = getColumns(datesRange, splitMonths);
|
|
109
|
+
const i = getFirstMonthColumnIndex(columns, firstMonth.month);
|
|
109
110
|
return ((i >= 0 ? i : monthPosition) + 1) * rectSizeWithGap + gap + weekdaysOffset;
|
|
110
111
|
};
|
|
111
112
|
const monthsLabelsNodes = withMonthLabels && monthLabels ? monthsRange.map((month, monthIndex) => {
|
|
@@ -145,8 +146,10 @@ const Heatmap = factory((_props) => {
|
|
|
145
146
|
const rectsWidth = allColors.length * rectSize + (allColors.length - 1) * gap;
|
|
146
147
|
const moreWidth = moreLabel.length * charWidth;
|
|
147
148
|
const totalLegendWidth = lessWidth + textGap + rectsWidth + textGap + moreWidth;
|
|
149
|
+
const legendX = svgWidth - totalLegendWidth;
|
|
150
|
+
const legendY = rectSizeWithGap * 7 + gap + monthsOffset + monthsBottomHeight + legendPadding;
|
|
148
151
|
return /* @__PURE__ */ jsxs("g", {
|
|
149
|
-
transform: `translate(${
|
|
152
|
+
transform: `translate(${legendX}, ${legendY})`,
|
|
150
153
|
"data-id": "legend",
|
|
151
154
|
...getStyles("legend"),
|
|
152
155
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Heatmap.mjs","names":["classes"],"sources":["../../src/Heatmap/Heatmap.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Box,\n BoxProps,\n ElementProps,\n factory,\n Factory,\n StylesApiProps,\n Tooltip,\n TooltipFloatingProps,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport { getBoundaries } from './get-boundaries/get-boundaries';\nimport { getColumns, getFirstMonthColumnIndex, HeatmapColumn } from './get-columns/get-columns';\nimport { getDatesRange } from './get-dates-range/get-dates-range';\nimport { getMonthsRange } from './get-months-range/get-months-range';\nimport { HeatmapSplitWeeks } from './HeatmapSplitWeeks';\nimport { HeatmapWeeks } from './HeatmapWeeks';\nimport { rotateWeekdaysNames } from './rotate-weekdays-names/rotate-weekdays-names';\nimport classes from './Heatmap.module.css';\n\nexport type HeatmapStylesNames =\n | 'root'\n | 'rect'\n | 'weekdayLabel'\n | 'monthLabel'\n | 'legend'\n | 'legendLabel'\n | 'legendRect';\n\ninterface HeatmapRectData {\n date: string;\n value: number | null;\n}\n\nexport interface HeatmapProps\n extends\n BoxProps,\n StylesApiProps<HeatmapFactory>,\n ElementProps<'svg', 'display' | 'opacity' | 'viewBox' | 'width' | 'height'> {\n /** Heatmap data, key is date in `YYYY-MM-DD` format (interpreted as a UTC calendar day) */\n data: Record<string, number>;\n\n /** Heatmap domain, array of 2 numbers, min and max values, calculated from data by default */\n domain?: [number, number];\n\n /** Heatmap start date. Current date - 1 year by default. Date is normalized to UTC midnight of the intended calendar day. */\n startDate?: Date | string;\n\n /** Heatmap end date. Current date by default. Date is normalized to UTC midnight of the intended calendar day. */\n endDate?: Date | string;\n\n /** If set, month labels are displayed @default false */\n withMonthLabels?: boolean;\n\n /** Month labels position relative to the heatmap @default 'top' */\n monthLabelsPosition?: 'top' | 'bottom';\n\n /** Month labels, array of 12 elements, can be used for localization */\n monthLabels?: string[];\n\n /** If set, weekday labels are displayed @default false */\n withWeekdayLabels?: boolean;\n\n /** Weekday labels, array of 7 elements, can be used for localization */\n weekdayLabels?: string[];\n\n /** If set, trailing dates that do not fall into the given `startDate` – `endDate` range are displayed to fill empty space. @default true */\n withOutsideDates?: boolean;\n\n /** First day of week, 0 – Sunday, 1 – Monday. @default 1 – Monday */\n firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\n /** Size of day rect in px @default 10 */\n rectSize?: number;\n\n /** Gap between rects in px @default 1 */\n gap?: number;\n\n /** Rect radius in px @default 2 */\n rectRadius?: number;\n\n /** Colors array, used to calculate color for each value, by default 4 shades of green colors are used */\n colors?: string[];\n\n /** Width of weekday labels column @default 30 */\n weekdaysLabelsWidth?: number;\n\n /** Height of month labels row @default 30 */\n monthsLabelsHeight?: number;\n\n /** Font size of month and weekday labels @default 12 */\n fontSize?: number;\n\n /** A function to generate tooltip label based on the hovered rect date and value, required for the tooltip to be visible */\n getTooltipLabel?: (input: HeatmapRectData) => React.ReactNode;\n\n /** If set, tooltip is displayed on rect hover @default false */\n withTooltip?: boolean;\n\n /** Props passed down to the `Tooltip.Floating` component */\n tooltipProps?: Partial<TooltipFloatingProps>;\n\n /** Props passed down to each rect depending on its date and associated value */\n getRectProps?: (input: HeatmapRectData) => React.ComponentProps<'rect'>;\n\n /** If set, inserts a spacer column between months @default false */\n splitMonths?: boolean;\n\n /** If set, legend with color levels is displayed below the heatmap @default false */\n withLegend?: boolean;\n\n /** Legend labels, array of 2 elements: [min label, max label] @default ['Less', 'More'] */\n legendLabels?: [string, string];\n}\n\nexport type HeatmapFactory = Factory<{\n props: HeatmapProps;\n ref: SVGSVGElement;\n stylesNames: HeatmapStylesNames;\n}>;\n\nconst defaultProps = {\n monthLabels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n weekdayLabels: ['Sun', 'Mon', '', 'Wed', '', 'Fri', ''],\n monthLabelsPosition: 'top',\n withOutsideDates: true,\n firstDayOfWeek: 1,\n rectSize: 10,\n weekdaysLabelsWidth: 30,\n monthsLabelsHeight: 14,\n gap: 1,\n rectRadius: 2,\n fontSize: 12,\n colors: [\n 'var(--heatmap-level-1)',\n 'var(--heatmap-level-2)',\n 'var(--heatmap-level-3)',\n 'var(--heatmap-level-4)',\n ],\n legendLabels: ['Less', 'More'] as [string, string],\n} satisfies Partial<HeatmapProps>;\n\nexport const Heatmap = factory<HeatmapFactory>((_props) => {\n const props = useProps('Heatmap', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n startDate,\n endDate,\n withMonthLabels,\n monthLabelsPosition,\n withWeekdayLabels,\n weekdayLabels,\n withOutsideDates,\n monthLabels,\n firstDayOfWeek,\n rectSize = 10,\n gap = 1,\n rectRadius,\n domain,\n colors,\n weekdaysLabelsWidth,\n monthsLabelsHeight,\n fontSize,\n getTooltipLabel,\n withTooltip,\n tooltipProps,\n getRectProps,\n splitMonths,\n withLegend,\n legendLabels,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<HeatmapFactory>({\n name: 'Heatmap',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n });\n\n const [hoveredRect, setHoveredRect] = useState<HeatmapRectData | null>(null);\n const rectSizeWithGap = rectSize + gap;\n const weekdaysOffset = withWeekdayLabels ? weekdaysLabelsWidth : 0;\n const monthsLabelAtTop = withMonthLabels && monthLabelsPosition === 'top';\n const monthsLabelAtBottom = withMonthLabels && monthLabelsPosition === 'bottom';\n const monthsOffset = monthsLabelAtTop ? monthsLabelsHeight : 0;\n const monthsBottomHeight = monthsLabelAtBottom ? monthsLabelsHeight : 0;\n const [min, max] = getBoundaries({ data, domain });\n const rotatedWeekdayLabels = useMemo(\n () => rotateWeekdaysNames(weekdayLabels, firstDayOfWeek),\n [weekdayLabels, firstDayOfWeek]\n );\n\n const datesRange = getDatesRange({\n startDate,\n endDate,\n withOutsideDates,\n firstDayOfWeek,\n });\n\n // Calculate months range for labels and optional split between months\n const monthsRange = withMonthLabels || splitMonths ? getMonthsRange(datesRange) : [];\n\n // Shared props for weeks rendering components\n const weeksProps = {\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n };\n\n // Use different rendering logic based on splitMonths\n const weeks = splitMonths ? (\n <HeatmapSplitWeeks {...weeksProps} />\n ) : (\n <HeatmapWeeks {...weeksProps} />\n );\n\n // Calculate total columns based on whether splitMonths is enabled\n const totalColumns = splitMonths ? getColumns(datesRange, splitMonths).length : datesRange.length;\n\n const computeMonthLabelX = (monthPosition: number, monthIndex: number) => {\n if (!splitMonths) {\n return monthPosition * rectSizeWithGap + gap + weekdaysOffset;\n }\n\n // For split months, find the first column index that has this month and shift label by 1 column\n const firstMonth = monthsRange[monthIndex];\n const columns: HeatmapColumn[] = getColumns(datesRange, splitMonths);\n const i = getFirstMonthColumnIndex(columns, firstMonth.month);\n const base = i >= 0 ? i : monthPosition;\n // shift right by one column\n return (base + 1) * rectSizeWithGap + gap + weekdaysOffset;\n };\n\n const monthsLabelsNodes =\n withMonthLabels && monthLabels\n ? monthsRange.map((month, monthIndex) => {\n // For non-split months, use original logic with minimum size of 3\n // For split months, use minimum size of 2\n const minSize = splitMonths ? 2 : 3;\n if (month.size < minSize) {\n return null;\n }\n\n const monthLabel = monthLabels[month.month];\n\n const monthLabelY = monthsLabelAtBottom\n ? rectSizeWithGap * 7 + gap + monthsLabelsHeight - 4\n : monthsLabelsHeight - 4;\n\n return (\n <text\n key={monthIndex}\n x={computeMonthLabelX(month.position, monthIndex)}\n y={monthLabelY}\n width={month.size * rectSizeWithGap}\n fontSize={fontSize}\n {...getStyles('monthLabel')}\n >\n {monthLabel}\n </text>\n );\n })\n : null;\n\n const weekdayLabelsNodes =\n withWeekdayLabels && weekdayLabels\n ? rotatedWeekdayLabels.map((weekdayLabel, dayIndex) => (\n <text\n key={dayIndex}\n x={0}\n y={(dayIndex + 1) * rectSizeWithGap - gap + monthsOffset}\n width={weekdaysLabelsWidth}\n fontSize={fontSize}\n {...getStyles('weekdayLabel')}\n >\n {weekdayLabel}\n </text>\n ))\n : null;\n\n const label = getTooltipLabel && hoveredRect && withTooltip ? getTooltipLabel(hoveredRect) : null;\n\n const legendPadding = 10;\n const legendHeight = withLegend ? legendPadding + rectSize : 0;\n const svgWidth = rectSizeWithGap * totalColumns + gap + weekdaysOffset;\n const svgHeight = rectSizeWithGap * 7 + gap + monthsOffset + monthsBottomHeight + legendHeight;\n\n const legendNode = withLegend\n ? (() => {\n const lessLabel = legendLabels![0];\n const moreLabel = legendLabels![1];\n const textGap = 6;\n const charWidth = fontSize! * 0.6;\n const lessWidth = lessLabel.length * charWidth;\n const allColors = [undefined, ...(colors || [])];\n const rectsWidth = allColors.length * rectSize + (allColors.length - 1) * gap;\n const moreWidth = moreLabel.length * charWidth;\n const totalLegendWidth = lessWidth + textGap + rectsWidth + textGap + moreWidth;\n\n const legendX = svgWidth - totalLegendWidth;\n const legendY =\n rectSizeWithGap * 7 + gap + monthsOffset + monthsBottomHeight + legendPadding;\n\n return (\n <g\n transform={`translate(${legendX}, ${legendY})`}\n data-id=\"legend\"\n {...getStyles('legend')}\n >\n <text\n x={0}\n y={rectSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {lessLabel}\n </text>\n {allColors.map((color, i) => (\n <rect\n key={i}\n x={lessWidth + textGap + i * (rectSize + gap)}\n y={0}\n width={rectSize}\n height={rectSize}\n rx={rectRadius}\n fill={color}\n data-empty={color === undefined || undefined}\n {...getStyles('legendRect')}\n />\n ))}\n <text\n x={lessWidth + textGap + rectsWidth + textGap}\n y={rectSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {moreLabel}\n </text>\n </g>\n );\n })()\n : null;\n\n return (\n <Box component=\"svg\" width={svgWidth} height={svgHeight} {...getStyles('root')} {...others}>\n <Tooltip.Floating\n label={label}\n disabled={!withTooltip || !label}\n position=\"top\"\n {...tooltipProps}\n >\n <g transform={`translate(${weekdaysOffset}, ${monthsOffset})`} data-id=\"all-weeks\">\n {/* Required for tooltip to remain visible while gaps between rects are hovered */}\n {withTooltip && (\n <rect\n fill=\"transparent\"\n width={rectSizeWithGap * totalColumns + gap}\n height={rectSizeWithGap * 7 + gap}\n />\n )}\n {weeks}\n </g>\n </Tooltip.Floating>\n {weekdayLabelsNodes}\n {monthsLabelsNodes}\n {legendNode}\n </Box>\n );\n});\n\nHeatmap.displayName = '@mantine/charts/Heatmap';\nHeatmap.classes = classes;\n\nexport namespace Heatmap {\n export type Props = HeatmapProps;\n export type StylesNames = HeatmapStylesNames;\n export type Factory = HeatmapFactory;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Heatmap.mjs","names":["classes"],"sources":["../../src/Heatmap/Heatmap.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Box,\n BoxProps,\n ElementProps,\n factory,\n Factory,\n StylesApiProps,\n Tooltip,\n TooltipFloatingProps,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport { getBoundaries } from './get-boundaries/get-boundaries';\nimport { getColumns, getFirstMonthColumnIndex, HeatmapColumn } from './get-columns/get-columns';\nimport { getDatesRange } from './get-dates-range/get-dates-range';\nimport { getMonthsRange } from './get-months-range/get-months-range';\nimport { HeatmapSplitWeeks } from './HeatmapSplitWeeks';\nimport { HeatmapWeeks } from './HeatmapWeeks';\nimport { rotateWeekdaysNames } from './rotate-weekdays-names/rotate-weekdays-names';\nimport classes from './Heatmap.module.css';\n\nexport type HeatmapStylesNames =\n | 'root'\n | 'rect'\n | 'weekdayLabel'\n | 'monthLabel'\n | 'legend'\n | 'legendLabel'\n | 'legendRect';\n\ninterface HeatmapRectData {\n date: string;\n value: number | null;\n}\n\nexport interface HeatmapProps\n extends\n BoxProps,\n StylesApiProps<HeatmapFactory>,\n ElementProps<'svg', 'display' | 'opacity' | 'viewBox' | 'width' | 'height'> {\n /** Heatmap data, key is date in `YYYY-MM-DD` format (interpreted as a UTC calendar day) */\n data: Record<string, number>;\n\n /** Heatmap domain, array of 2 numbers, min and max values, calculated from data by default */\n domain?: [number, number];\n\n /** Heatmap start date. Current date - 1 year by default. Date is normalized to UTC midnight of the intended calendar day. */\n startDate?: Date | string;\n\n /** Heatmap end date. Current date by default. Date is normalized to UTC midnight of the intended calendar day. */\n endDate?: Date | string;\n\n /** If set, month labels are displayed @default false */\n withMonthLabels?: boolean;\n\n /** Month labels position relative to the heatmap @default 'top' */\n monthLabelsPosition?: 'top' | 'bottom';\n\n /** Month labels, array of 12 elements, can be used for localization */\n monthLabels?: string[];\n\n /** If set, weekday labels are displayed @default false */\n withWeekdayLabels?: boolean;\n\n /** Weekday labels, array of 7 elements, can be used for localization */\n weekdayLabels?: string[];\n\n /** If set, trailing dates that do not fall into the given `startDate` – `endDate` range are displayed to fill empty space. @default true */\n withOutsideDates?: boolean;\n\n /** First day of week, 0 – Sunday, 1 – Monday. @default 1 – Monday */\n firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\n /** Size of day rect in px @default 10 */\n rectSize?: number;\n\n /** Gap between rects in px @default 1 */\n gap?: number;\n\n /** Rect radius in px @default 2 */\n rectRadius?: number;\n\n /** Colors array, used to calculate color for each value, by default 4 shades of green colors are used */\n colors?: string[];\n\n /** Width of weekday labels column @default 30 */\n weekdaysLabelsWidth?: number;\n\n /** Height of month labels row @default 30 */\n monthsLabelsHeight?: number;\n\n /** Font size of month and weekday labels @default 12 */\n fontSize?: number;\n\n /** A function to generate tooltip label based on the hovered rect date and value, required for the tooltip to be visible */\n getTooltipLabel?: (input: HeatmapRectData) => React.ReactNode;\n\n /** If set, tooltip is displayed on rect hover @default false */\n withTooltip?: boolean;\n\n /** Props passed down to the `Tooltip.Floating` component */\n tooltipProps?: Partial<TooltipFloatingProps>;\n\n /** Props passed down to each rect depending on its date and associated value */\n getRectProps?: (input: HeatmapRectData) => React.ComponentProps<'rect'>;\n\n /** If set, inserts a spacer column between months @default false */\n splitMonths?: boolean;\n\n /** If set, legend with color levels is displayed below the heatmap @default false */\n withLegend?: boolean;\n\n /** Legend labels, array of 2 elements: [min label, max label] @default ['Less', 'More'] */\n legendLabels?: [string, string];\n}\n\nexport type HeatmapFactory = Factory<{\n props: HeatmapProps;\n ref: SVGSVGElement;\n stylesNames: HeatmapStylesNames;\n}>;\n\nconst defaultProps = {\n monthLabels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n weekdayLabels: ['Sun', 'Mon', '', 'Wed', '', 'Fri', ''],\n monthLabelsPosition: 'top',\n withOutsideDates: true,\n firstDayOfWeek: 1,\n rectSize: 10,\n weekdaysLabelsWidth: 30,\n monthsLabelsHeight: 14,\n gap: 1,\n rectRadius: 2,\n fontSize: 12,\n colors: [\n 'var(--heatmap-level-1)',\n 'var(--heatmap-level-2)',\n 'var(--heatmap-level-3)',\n 'var(--heatmap-level-4)',\n ],\n legendLabels: ['Less', 'More'] as [string, string],\n} satisfies Partial<HeatmapProps>;\n\nexport const Heatmap = factory<HeatmapFactory>((_props) => {\n const props = useProps('Heatmap', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n startDate,\n endDate,\n withMonthLabels,\n monthLabelsPosition,\n withWeekdayLabels,\n weekdayLabels,\n withOutsideDates,\n monthLabels,\n firstDayOfWeek,\n rectSize = 10,\n gap = 1,\n rectRadius,\n domain,\n colors,\n weekdaysLabelsWidth,\n monthsLabelsHeight,\n fontSize,\n getTooltipLabel,\n withTooltip,\n tooltipProps,\n getRectProps,\n splitMonths,\n withLegend,\n legendLabels,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<HeatmapFactory>({\n name: 'Heatmap',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n });\n\n const [hoveredRect, setHoveredRect] = useState<HeatmapRectData | null>(null);\n const rectSizeWithGap = rectSize + gap;\n const weekdaysOffset = withWeekdayLabels ? weekdaysLabelsWidth : 0;\n const monthsLabelAtTop = withMonthLabels && monthLabelsPosition === 'top';\n const monthsLabelAtBottom = withMonthLabels && monthLabelsPosition === 'bottom';\n const monthsOffset = monthsLabelAtTop ? monthsLabelsHeight : 0;\n const monthsBottomHeight = monthsLabelAtBottom ? monthsLabelsHeight : 0;\n const [min, max] = getBoundaries({ data, domain });\n const rotatedWeekdayLabels = useMemo(\n () => rotateWeekdaysNames(weekdayLabels, firstDayOfWeek),\n [weekdayLabels, firstDayOfWeek]\n );\n\n const datesRange = getDatesRange({\n startDate,\n endDate,\n withOutsideDates,\n firstDayOfWeek,\n });\n\n // Calculate months range for labels and optional split between months\n const monthsRange = withMonthLabels || splitMonths ? getMonthsRange(datesRange) : [];\n\n // Shared props for weeks rendering components\n const weeksProps = {\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n };\n\n // Use different rendering logic based on splitMonths\n const weeks = splitMonths ? (\n <HeatmapSplitWeeks {...weeksProps} />\n ) : (\n <HeatmapWeeks {...weeksProps} />\n );\n\n // Calculate total columns based on whether splitMonths is enabled\n const totalColumns = splitMonths ? getColumns(datesRange, splitMonths).length : datesRange.length;\n\n const computeMonthLabelX = (monthPosition: number, monthIndex: number) => {\n if (!splitMonths) {\n return monthPosition * rectSizeWithGap + gap + weekdaysOffset;\n }\n\n // For split months, find the first column index that has this month and shift label by 1 column\n const firstMonth = monthsRange[monthIndex];\n const columns: HeatmapColumn[] = getColumns(datesRange, splitMonths);\n const i = getFirstMonthColumnIndex(columns, firstMonth.month);\n const base = i >= 0 ? i : monthPosition;\n // shift right by one column\n return (base + 1) * rectSizeWithGap + gap + weekdaysOffset;\n };\n\n const monthsLabelsNodes =\n withMonthLabels && monthLabels\n ? monthsRange.map((month, monthIndex) => {\n // For non-split months, use original logic with minimum size of 3\n // For split months, use minimum size of 2\n const minSize = splitMonths ? 2 : 3;\n if (month.size < minSize) {\n return null;\n }\n\n const monthLabel = monthLabels[month.month];\n\n const monthLabelY = monthsLabelAtBottom\n ? rectSizeWithGap * 7 + gap + monthsLabelsHeight - 4\n : monthsLabelsHeight - 4;\n\n return (\n <text\n key={monthIndex}\n x={computeMonthLabelX(month.position, monthIndex)}\n y={monthLabelY}\n width={month.size * rectSizeWithGap}\n fontSize={fontSize}\n {...getStyles('monthLabel')}\n >\n {monthLabel}\n </text>\n );\n })\n : null;\n\n const weekdayLabelsNodes =\n withWeekdayLabels && weekdayLabels\n ? rotatedWeekdayLabels.map((weekdayLabel, dayIndex) => (\n <text\n key={dayIndex}\n x={0}\n y={(dayIndex + 1) * rectSizeWithGap - gap + monthsOffset}\n width={weekdaysLabelsWidth}\n fontSize={fontSize}\n {...getStyles('weekdayLabel')}\n >\n {weekdayLabel}\n </text>\n ))\n : null;\n\n const label = getTooltipLabel && hoveredRect && withTooltip ? getTooltipLabel(hoveredRect) : null;\n\n const legendPadding = 10;\n const legendHeight = withLegend ? legendPadding + rectSize : 0;\n const svgWidth = rectSizeWithGap * totalColumns + gap + weekdaysOffset;\n const svgHeight = rectSizeWithGap * 7 + gap + monthsOffset + monthsBottomHeight + legendHeight;\n\n const legendNode = withLegend\n ? (() => {\n const lessLabel = legendLabels![0];\n const moreLabel = legendLabels![1];\n const textGap = 6;\n const charWidth = fontSize! * 0.6;\n const lessWidth = lessLabel.length * charWidth;\n const allColors = [undefined, ...(colors || [])];\n const rectsWidth = allColors.length * rectSize + (allColors.length - 1) * gap;\n const moreWidth = moreLabel.length * charWidth;\n const totalLegendWidth = lessWidth + textGap + rectsWidth + textGap + moreWidth;\n\n const legendX = svgWidth - totalLegendWidth;\n const legendY =\n rectSizeWithGap * 7 + gap + monthsOffset + monthsBottomHeight + legendPadding;\n\n return (\n <g\n transform={`translate(${legendX}, ${legendY})`}\n data-id=\"legend\"\n {...getStyles('legend')}\n >\n <text\n x={0}\n y={rectSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {lessLabel}\n </text>\n {allColors.map((color, i) => (\n <rect\n key={i}\n x={lessWidth + textGap + i * (rectSize + gap)}\n y={0}\n width={rectSize}\n height={rectSize}\n rx={rectRadius}\n fill={color}\n data-empty={color === undefined || undefined}\n {...getStyles('legendRect')}\n />\n ))}\n <text\n x={lessWidth + textGap + rectsWidth + textGap}\n y={rectSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {moreLabel}\n </text>\n </g>\n );\n })()\n : null;\n\n return (\n <Box component=\"svg\" width={svgWidth} height={svgHeight} {...getStyles('root')} {...others}>\n <Tooltip.Floating\n label={label}\n disabled={!withTooltip || !label}\n position=\"top\"\n {...tooltipProps}\n >\n <g transform={`translate(${weekdaysOffset}, ${monthsOffset})`} data-id=\"all-weeks\">\n {/* Required for tooltip to remain visible while gaps between rects are hovered */}\n {withTooltip && (\n <rect\n fill=\"transparent\"\n width={rectSizeWithGap * totalColumns + gap}\n height={rectSizeWithGap * 7 + gap}\n />\n )}\n {weeks}\n </g>\n </Tooltip.Floating>\n {weekdayLabelsNodes}\n {monthsLabelsNodes}\n {legendNode}\n </Box>\n );\n});\n\nHeatmap.displayName = '@mantine/charts/Heatmap';\nHeatmap.classes = classes;\n\nexport namespace Heatmap {\n export type Props = HeatmapProps;\n export type StylesNames = HeatmapStylesNames;\n export type Factory = HeatmapFactory;\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,8 @@ import { Fragment, jsx } from "react/jsx-runtime";
|
|
|
5
5
|
//#region packages/@mantine/charts/src/Heatmap/HeatmapSplitWeeks.tsx
|
|
6
6
|
function HeatmapSplitWeeks({ data, datesRange, rectSize, gap, rectRadius, min, max, colors, withTooltip, setHoveredRect, getRectProps, getStyles }) {
|
|
7
7
|
const rectSizeWithGap = rectSize + gap;
|
|
8
|
-
|
|
8
|
+
const columns = getColumns(datesRange, true);
|
|
9
|
+
return /* @__PURE__ */ jsx(Fragment, { children: columns.map((col, columnIndex) => {
|
|
9
10
|
if (col.type === "spacer") return /* @__PURE__ */ jsx("g", { transform: `translate(${columnIndex * rectSizeWithGap}, 0)` }, `spacer-${columnIndex}`);
|
|
10
11
|
const days = datesRange[col.weekIndex].map((date, dayIndex) => {
|
|
11
12
|
if (!date) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeatmapSplitWeeks.mjs","names":[],"sources":["../../src/Heatmap/HeatmapSplitWeeks.tsx"],"sourcesContent":["import { getColumns, HeatmapColumn } from './get-columns/get-columns';\nimport { getHeatColor } from './get-heat-color/get-heat-color';\nimport { HeatmapWeeksSharedProps } from './HeatmapWeeks.types';\n\nexport function HeatmapSplitWeeks({\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n}: HeatmapWeeksSharedProps) {\n const rectSizeWithGap = rectSize + gap;\n\n // Columns: computed by a helper so logic is isolated\n const columns: HeatmapColumn[] = getColumns(datesRange, true);\n\n return (\n <>\n {columns.map((col, columnIndex) => {\n if (col.type === 'spacer') {\n return (\n <g\n key={`spacer-${columnIndex}`}\n transform={`translate(${columnIndex * rectSizeWithGap}, 0)`}\n />\n );\n }\n\n const week = datesRange[col.weekIndex];\n\n const days = week.map((date, dayIndex) => {\n if (!date) {\n return null;\n }\n if (new Date(date).getUTCMonth() !== col.month) {\n return null;\n }\n\n const hasValue = date in data && data[date] !== null;\n const rectValue = hasValue ? data[date] : null;\n\n return (\n <rect\n key={`${date}-${col.month}`}\n width={rectSize}\n height={rectSize}\n x={gap}\n y={dayIndex * rectSizeWithGap + gap}\n rx={rectRadius}\n data-empty={!hasValue || undefined}\n fill={hasValue ? getHeatColor({ value: data[date], min, max, colors }) : undefined}\n onPointerEnter={\n withTooltip ? () => setHoveredRect({ date, value: rectValue }) : undefined\n }\n {...getRectProps?.({ date, value: rectValue })}\n {...getStyles('rect')}\n />\n );\n });\n\n return (\n <g\n key={`col-${col.weekIndex}-${col.month}-${columnIndex}`}\n transform={`translate(${columnIndex * rectSizeWithGap}, 0)`}\n data-id=\"week\"\n >\n {days}\n </g>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;;AAIA,SAAgB,kBAAkB,EAChC,MACA,YACA,UACA,KACA,YACA,KACA,KACA,QACA,aACA,gBACA,cACA,aAC0B;CAC1B,MAAM,kBAAkB,WAAW;
|
|
1
|
+
{"version":3,"file":"HeatmapSplitWeeks.mjs","names":[],"sources":["../../src/Heatmap/HeatmapSplitWeeks.tsx"],"sourcesContent":["import { getColumns, HeatmapColumn } from './get-columns/get-columns';\nimport { getHeatColor } from './get-heat-color/get-heat-color';\nimport { HeatmapWeeksSharedProps } from './HeatmapWeeks.types';\n\nexport function HeatmapSplitWeeks({\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n}: HeatmapWeeksSharedProps) {\n const rectSizeWithGap = rectSize + gap;\n\n // Columns: computed by a helper so logic is isolated\n const columns: HeatmapColumn[] = getColumns(datesRange, true);\n\n return (\n <>\n {columns.map((col, columnIndex) => {\n if (col.type === 'spacer') {\n return (\n <g\n key={`spacer-${columnIndex}`}\n transform={`translate(${columnIndex * rectSizeWithGap}, 0)`}\n />\n );\n }\n\n const week = datesRange[col.weekIndex];\n\n const days = week.map((date, dayIndex) => {\n if (!date) {\n return null;\n }\n if (new Date(date).getUTCMonth() !== col.month) {\n return null;\n }\n\n const hasValue = date in data && data[date] !== null;\n const rectValue = hasValue ? data[date] : null;\n\n return (\n <rect\n key={`${date}-${col.month}`}\n width={rectSize}\n height={rectSize}\n x={gap}\n y={dayIndex * rectSizeWithGap + gap}\n rx={rectRadius}\n data-empty={!hasValue || undefined}\n fill={hasValue ? getHeatColor({ value: data[date], min, max, colors }) : undefined}\n onPointerEnter={\n withTooltip ? () => setHoveredRect({ date, value: rectValue }) : undefined\n }\n {...getRectProps?.({ date, value: rectValue })}\n {...getStyles('rect')}\n />\n );\n });\n\n return (\n <g\n key={`col-${col.weekIndex}-${col.month}-${columnIndex}`}\n transform={`translate(${columnIndex * rectSizeWithGap}, 0)`}\n data-id=\"week\"\n >\n {days}\n </g>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;;AAIA,SAAgB,kBAAkB,EAChC,MACA,YACA,UACA,KACA,YACA,KACA,KACA,QACA,aACA,gBACA,cACA,aAC0B;CAC1B,MAAM,kBAAkB,WAAW;CAGnC,MAAM,UAA2B,WAAW,YAAY,IAAI;CAE5D,OACE,oBAAA,UAAA,EAAA,UACG,QAAQ,KAAK,KAAK,gBAAgB;EACjC,IAAI,IAAI,SAAS,UACf,OACE,oBAAC,KAAD,EAEE,WAAW,aAAa,cAAc,gBAAgB,MACvD,GAFM,UAAU,aAEhB;EAML,MAAM,OAFO,WAAW,IAAI,UAEX,CAAC,KAAK,MAAM,aAAa;GACxC,IAAI,CAAC,MACH,OAAO;GAET,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,YAAY,MAAM,IAAI,OACvC,OAAO;GAGT,MAAM,WAAW,QAAQ,QAAQ,KAAK,UAAU;GAChD,MAAM,YAAY,WAAW,KAAK,QAAQ;GAE1C,OACE,oBAAC,QAAD;IAEE,OAAO;IACP,QAAQ;IACR,GAAG;IACH,GAAG,WAAW,kBAAkB;IAChC,IAAI;IACJ,cAAY,CAAC,YAAY,KAAA;IACzB,MAAM,WAAW,aAAa;KAAE,OAAO,KAAK;KAAO;KAAK;KAAK;IAAO,CAAC,IAAI,KAAA;IACzE,gBACE,oBAAoB,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC,IAAI,KAAA;IAEnE,GAAI,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC;IAC7C,GAAI,UAAU,MAAM;GACrB,GAbM,GAAG,KAAK,GAAG,IAAI,OAarB;EAEL,CAAC;EAED,OACE,oBAAC,KAAD;GAEE,WAAW,aAAa,cAAc,gBAAgB;GACtD,WAAQ;GAEP,UAAA;EACA,GALI,OAAO,IAAI,UAAU,GAAG,IAAI,MAAM,GAAG,aAKzC;CAEP,CAAC,EACD,CAAA;AAEN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeatmapWeeks.mjs","names":[],"sources":["../../src/Heatmap/HeatmapWeeks.tsx"],"sourcesContent":["import { getHeatColor } from './get-heat-color/get-heat-color';\nimport { HeatmapWeeksSharedProps } from './HeatmapWeeks.types';\n\nexport function HeatmapWeeks({\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n}: HeatmapWeeksSharedProps) {\n const rectSizeWithGap = rectSize + gap;\n\n return (\n <>\n {datesRange.map((week, weekIndex) => {\n // Original simple logic without month splitting\n const days = week.map((date, dayIndex) => {\n if (!date) {\n return null;\n }\n\n const hasValue = date in data && data[date] !== null;\n const rectValue = hasValue ? data[date] : null;\n\n return (\n <rect\n key={date}\n width={rectSize}\n height={rectSize}\n x={gap}\n y={dayIndex * rectSizeWithGap + gap}\n rx={rectRadius}\n data-empty={!hasValue || undefined}\n fill={hasValue ? getHeatColor({ value: data[date], min, max, colors }) : undefined}\n onPointerEnter={\n withTooltip ? () => setHoveredRect({ date, value: rectValue }) : undefined\n }\n {...getRectProps?.({ date, value: rectValue })}\n {...getStyles('rect')}\n />\n );\n });\n\n return (\n <g\n key={weekIndex}\n transform={`translate(${weekIndex * rectSizeWithGap}, 0)`}\n data-id=\"week\"\n >\n {days}\n </g>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;AAGA,SAAgB,aAAa,EAC3B,MACA,YACA,UACA,KACA,YACA,KACA,KACA,QACA,aACA,gBACA,cACA,aAC0B;CAC1B,MAAM,kBAAkB,WAAW;CAEnC,OACE,oBAAA,UAAA,EAAA,UACG,WAAW,KAAK,MAAM,cAAc;EAEnC,MAAM,OAAO,KAAK,KAAK,MAAM,aAAa;GACxC,IAAI,CAAC,MACH,OAAO;GAGT,MAAM,WAAW,QAAQ,QAAQ,KAAK,UAAU;GAChD,MAAM,YAAY,WAAW,KAAK,QAAQ;GAE1C,OACE,oBAAC,QAAD;IAEE,OAAO;IACP,QAAQ;IACR,GAAG;IACH,GAAG,WAAW,kBAAkB;IAChC,IAAI;IACJ,cAAY,CAAC,YAAY,KAAA;IACzB,MAAM,WAAW,aAAa;KAAE,OAAO,KAAK;KAAO;KAAK;KAAK;IAAO,CAAC,IAAI,KAAA;IACzE,gBACE,oBAAoB,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC,IAAI,KAAA;IAEnE,GAAI,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC;IAC7C,GAAI,UAAU,MAAM;GACrB,GAbM,IAaN;EAEL,CAAC;EAED,OACE,oBAAC,KAAD;GAEE,WAAW,aAAa,YAAY,gBAAgB;GACpD,WAAQ;
|
|
1
|
+
{"version":3,"file":"HeatmapWeeks.mjs","names":[],"sources":["../../src/Heatmap/HeatmapWeeks.tsx"],"sourcesContent":["import { getHeatColor } from './get-heat-color/get-heat-color';\nimport { HeatmapWeeksSharedProps } from './HeatmapWeeks.types';\n\nexport function HeatmapWeeks({\n data,\n datesRange,\n rectSize,\n gap,\n rectRadius,\n min,\n max,\n colors,\n withTooltip,\n setHoveredRect,\n getRectProps,\n getStyles,\n}: HeatmapWeeksSharedProps) {\n const rectSizeWithGap = rectSize + gap;\n\n return (\n <>\n {datesRange.map((week, weekIndex) => {\n // Original simple logic without month splitting\n const days = week.map((date, dayIndex) => {\n if (!date) {\n return null;\n }\n\n const hasValue = date in data && data[date] !== null;\n const rectValue = hasValue ? data[date] : null;\n\n return (\n <rect\n key={date}\n width={rectSize}\n height={rectSize}\n x={gap}\n y={dayIndex * rectSizeWithGap + gap}\n rx={rectRadius}\n data-empty={!hasValue || undefined}\n fill={hasValue ? getHeatColor({ value: data[date], min, max, colors }) : undefined}\n onPointerEnter={\n withTooltip ? () => setHoveredRect({ date, value: rectValue }) : undefined\n }\n {...getRectProps?.({ date, value: rectValue })}\n {...getStyles('rect')}\n />\n );\n });\n\n return (\n <g\n key={weekIndex}\n transform={`translate(${weekIndex * rectSizeWithGap}, 0)`}\n data-id=\"week\"\n >\n {days}\n </g>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;AAGA,SAAgB,aAAa,EAC3B,MACA,YACA,UACA,KACA,YACA,KACA,KACA,QACA,aACA,gBACA,cACA,aAC0B;CAC1B,MAAM,kBAAkB,WAAW;CAEnC,OACE,oBAAA,UAAA,EAAA,UACG,WAAW,KAAK,MAAM,cAAc;EAEnC,MAAM,OAAO,KAAK,KAAK,MAAM,aAAa;GACxC,IAAI,CAAC,MACH,OAAO;GAGT,MAAM,WAAW,QAAQ,QAAQ,KAAK,UAAU;GAChD,MAAM,YAAY,WAAW,KAAK,QAAQ;GAE1C,OACE,oBAAC,QAAD;IAEE,OAAO;IACP,QAAQ;IACR,GAAG;IACH,GAAG,WAAW,kBAAkB;IAChC,IAAI;IACJ,cAAY,CAAC,YAAY,KAAA;IACzB,MAAM,WAAW,aAAa;KAAE,OAAO,KAAK;KAAO;KAAK;KAAK;IAAO,CAAC,IAAI,KAAA;IACzE,gBACE,oBAAoB,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC,IAAI,KAAA;IAEnE,GAAI,eAAe;KAAE;KAAM,OAAO;IAAU,CAAC;IAC7C,GAAI,UAAU,MAAM;GACrB,GAbM,IAaN;EAEL,CAAC;EAED,OACE,oBAAC,KAAD;GAEE,WAAW,aAAa,YAAY,gBAAgB;GACpD,WAAQ;GAEP,UAAA;EACA,GALI,SAKJ;CAEP,CAAC,EACD,CAAA;AAEN"}
|
|
@@ -6,7 +6,7 @@ import { PointLabel } from "../PointLabel/PointLabel.mjs";
|
|
|
6
6
|
import grid_chart_module_default from "../grid-chart.module.mjs";
|
|
7
7
|
import { Box, createVarsResolver, factory, getThemeColor, useMantineTheme, useProps, useResolvedStylesApi, useStyles } from "@mantine/core";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { CartesianGrid, Label, Legend, Line, LineChart, ReferenceLine, ResponsiveContainer, Tooltip as Tooltip$1, XAxis, YAxis } from "recharts";
|
|
9
|
+
import { CartesianGrid, Label, Legend, Line, LineChart, ReferenceArea, ReferenceDot, ReferenceLine, ResponsiveContainer, Tooltip as Tooltip$1, XAxis, YAxis } from "recharts";
|
|
10
10
|
import { createElement, useState } from "react";
|
|
11
11
|
import { useId as useId$1 } from "@mantine/hooks";
|
|
12
12
|
//#region packages/@mantine/charts/src/LineChart/LineChart.tsx
|
|
@@ -38,7 +38,7 @@ const varsResolver = createVarsResolver((theme, { textColor, gridColor }) => ({
|
|
|
38
38
|
} }));
|
|
39
39
|
const LineChart$1 = factory((_props) => {
|
|
40
40
|
const props = useProps("LineChart", defaultProps, _props);
|
|
41
|
-
const { classNames, className, style, styles, unstyled, vars, data, withLegend, legendProps, series, onMouseLeave, dataKey, withTooltip, withXAxis, withYAxis, gridAxis, tickLine, xAxisProps, yAxisProps, unit, tooltipAnimationDuration, strokeDasharray, gridProps, tooltipProps, referenceLines, withDots, dotProps, activeDotProps, strokeWidth, lineChartProps, connectNulls, fillOpacity, curveType, orientation, dir, valueFormatter, children, lineProps, xAxisLabel, yAxisLabel, type, gradientStops, withRightYAxis, rightYAxisLabel, rightYAxisProps, withPointLabels, attributes, gridColor, accessibilityLayer, withBrush, brushProps, ...others } = props;
|
|
41
|
+
const { classNames, className, style, styles, unstyled, vars, data, withLegend, legendProps, series, onMouseLeave, dataKey, withTooltip, withXAxis, withYAxis, gridAxis, tickLine, xAxisProps, yAxisProps, unit, tooltipAnimationDuration, strokeDasharray, gridProps, tooltipProps, referenceLines, referenceAreas, referenceDots, withDots, dotProps, activeDotProps, strokeWidth, lineChartProps, connectNulls, fillOpacity, curveType, orientation, dir, valueFormatter, children, lineProps, xAxisLabel, yAxisLabel, type, gradientStops, withRightYAxis, rightYAxisLabel, rightYAxisProps, withPointLabels, attributes, gridColor, accessibilityLayer, withBrush, brushProps, ...others } = props;
|
|
42
42
|
const theme = useMantineTheme();
|
|
43
43
|
const withXTickLine = gridAxis !== "none" && (tickLine === "x" || tickLine === "xy");
|
|
44
44
|
const withYTickLine = gridAxis !== "none" && (tickLine === "y" || tickLine === "xy");
|
|
@@ -106,22 +106,58 @@ const LineChart$1 = factory((_props) => {
|
|
|
106
106
|
...typeof lineProps === "function" ? lineProps(item) : lineProps
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
|
-
const referenceLinesItems = referenceLines?.map((line, index) => {
|
|
110
|
-
const color = getThemeColor(
|
|
109
|
+
const referenceLinesItems = referenceLines?.map(({ color: lineColor, labelPosition, ...line }, index) => {
|
|
110
|
+
const color = getThemeColor(lineColor, theme);
|
|
111
111
|
return /* @__PURE__ */ jsx(ReferenceLine, {
|
|
112
|
-
stroke:
|
|
112
|
+
stroke: lineColor ? color : "var(--chart-grid-color)",
|
|
113
113
|
strokeWidth: 1,
|
|
114
114
|
yAxisId: line.yAxisId || void 0,
|
|
115
115
|
...line,
|
|
116
116
|
label: {
|
|
117
|
-
fill:
|
|
117
|
+
fill: lineColor ? color : "currentColor",
|
|
118
118
|
fontSize: 12,
|
|
119
|
-
position:
|
|
119
|
+
position: labelPosition ?? "insideBottomLeft",
|
|
120
120
|
...typeof line.label === "object" ? line.label : { value: line.label }
|
|
121
121
|
},
|
|
122
122
|
...getStyles("referenceLine")
|
|
123
123
|
}, index);
|
|
124
124
|
});
|
|
125
|
+
const referenceAreasItems = referenceAreas?.map(({ color: areaColor, labelPosition, ...area }, index) => {
|
|
126
|
+
const color = getThemeColor(areaColor, theme);
|
|
127
|
+
return /* @__PURE__ */ jsx(ReferenceArea, {
|
|
128
|
+
fill: areaColor ? color : "var(--chart-grid-color)",
|
|
129
|
+
fillOpacity: .2,
|
|
130
|
+
stroke: areaColor ? color : "var(--chart-grid-color)",
|
|
131
|
+
strokeOpacity: .6,
|
|
132
|
+
yAxisId: area.yAxisId || void 0,
|
|
133
|
+
...area,
|
|
134
|
+
label: {
|
|
135
|
+
fill: areaColor ? color : "currentColor",
|
|
136
|
+
fontSize: 12,
|
|
137
|
+
position: labelPosition ?? "insideTop",
|
|
138
|
+
...typeof area.label === "object" ? area.label : { value: area.label }
|
|
139
|
+
},
|
|
140
|
+
...getStyles("referenceArea")
|
|
141
|
+
}, index);
|
|
142
|
+
});
|
|
143
|
+
const referenceDotsItems = referenceDots?.map(({ color: dotColor, labelPosition, ...dot }, index) => {
|
|
144
|
+
const color = getThemeColor(dotColor, theme);
|
|
145
|
+
return /* @__PURE__ */ jsx(ReferenceDot, {
|
|
146
|
+
r: 5,
|
|
147
|
+
fill: dotColor ? color : "var(--chart-grid-color)",
|
|
148
|
+
stroke: "var(--mantine-color-body)",
|
|
149
|
+
strokeWidth: 2,
|
|
150
|
+
yAxisId: dot.yAxisId || void 0,
|
|
151
|
+
...dot,
|
|
152
|
+
label: {
|
|
153
|
+
fill: dotColor ? color : "currentColor",
|
|
154
|
+
fontSize: 12,
|
|
155
|
+
position: labelPosition ?? "top",
|
|
156
|
+
...typeof dot.label === "object" ? dot.label : { value: dot.label }
|
|
157
|
+
},
|
|
158
|
+
...getStyles("referenceDot")
|
|
159
|
+
}, index);
|
|
160
|
+
});
|
|
125
161
|
const sharedYAxisProps = {
|
|
126
162
|
axisLine: false,
|
|
127
163
|
...orientation === "vertical" ? {
|
|
@@ -152,6 +188,7 @@ const LineChart$1 = factory((_props) => {
|
|
|
152
188
|
accessibilityLayer,
|
|
153
189
|
...lineChartProps,
|
|
154
190
|
children: [
|
|
191
|
+
referenceAreasItems,
|
|
155
192
|
type === "gradient" && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("linearGradient", {
|
|
156
193
|
id: gradientId,
|
|
157
194
|
x1: "0",
|
|
@@ -268,6 +305,7 @@ const LineChart$1 = factory((_props) => {
|
|
|
268
305
|
}),
|
|
269
306
|
lines,
|
|
270
307
|
referenceLinesItems,
|
|
308
|
+
referenceDotsItems,
|
|
271
309
|
withBrush && /* @__PURE__ */ jsx(ChartBrush, {
|
|
272
310
|
dataKey,
|
|
273
311
|
classNames: resolvedClassNames,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineChart.mjs","names":["LineChart","useId","ReChartsLineChart","Tooltip","classes"],"sources":["../../src/LineChart/LineChart.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n CartesianGrid,\n Label,\n Legend,\n Line,\n LineProps,\n LineChart as ReChartsLineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n factory,\n Factory,\n getThemeColor,\n MantineColor,\n StylesApiProps,\n useMantineTheme,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useId } from '@mantine/hooks';\nimport { ChartBrush } from '../ChartBrush';\nimport { ChartLegend, ChartLegendStylesNames } from '../ChartLegend';\nimport { ChartTooltip, ChartTooltipStylesNames } from '../ChartTooltip';\nimport { PointLabel } from '../PointLabel/PointLabel';\nimport type {\n BaseChartStylesNames,\n ChartSeries,\n GridChartBaseProps,\n MantineChartDotProps,\n} from '../types';\nimport classes from '../grid-chart.module.css';\n\nexport type LineChartType = 'default' | 'gradient';\n\nexport interface LineChartGradientStop {\n offset: number;\n color: MantineColor;\n}\n\nexport type LineChartCurveType =\n | 'bump'\n | 'linear'\n | 'natural'\n | 'monotone'\n | 'step'\n | 'stepBefore'\n | 'stepAfter';\n\nexport interface LineChartSeries extends ChartSeries {\n strokeDasharray?: string | number;\n curveType?: LineChartCurveType;\n}\n\nexport type LineChartStylesNames =\n | 'line'\n | BaseChartStylesNames\n | ChartLegendStylesNames\n | ChartTooltipStylesNames;\n\nexport type LineChartCssVariables = {\n root: '--chart-text-color' | '--chart-grid-color';\n};\n\nexport interface LineChartProps\n extends BoxProps, GridChartBaseProps, StylesApiProps<LineChartFactory>, ElementProps<'div'> {\n /** Data used to display chart */\n data: Record<string, any>[];\n\n /** An array of objects with `name` and `color` keys. Determines which data should be consumed from the `data` array. */\n series: LineChartSeries[];\n\n /** Controls styles of the line @default 'default' */\n type?: LineChartType;\n\n /** Data used to generate gradient stops @default [{ offset: 0, color: 'red' }, { offset: 100, color: 'blue' }] */\n gradientStops?: LineChartGradientStop[];\n\n /** Type of the curve @default 'monotone' */\n curveType?: LineChartCurveType;\n\n /** Controls fill opacity of all lines @default 1 */\n fillOpacity?: number;\n\n /** Determines whether dots should be displayed @default true */\n withDots?: boolean;\n\n /** Props passed down to all dots. Ignored if `withDots={false}` is set. */\n dotProps?: MantineChartDotProps;\n\n /** Props passed down to all active dots. Ignored if `withDots={false}` is set. */\n activeDotProps?: MantineChartDotProps;\n\n /** Stroke width for the chart lines @default 2 */\n strokeWidth?: number;\n\n /** Props passed down to recharts `LineChart` component */\n lineChartProps?: React.ComponentProps<typeof ReChartsLineChart>;\n\n /** Determines whether points with `null` values should be connected @default true */\n connectNulls?: boolean;\n\n /** Additional components that are rendered inside recharts `LineChart` component */\n children?: React.ReactNode;\n\n /** Props passed down to recharts `Line` component */\n lineProps?:\n | ((series: LineChartSeries) => Partial<Omit<LineProps, 'ref'>>)\n | Partial<Omit<LineProps, 'ref'>>;\n\n /** Determines whether each point should have associated label @default false */\n withPointLabels?: boolean;\n}\n\nexport type LineChartFactory = Factory<{\n props: LineChartProps;\n ref: HTMLDivElement;\n stylesNames: LineChartStylesNames;\n vars: LineChartCssVariables;\n}>;\n\nconst defaultProps = {\n withXAxis: true,\n withYAxis: true,\n withTooltip: true,\n tooltipAnimationDuration: 0,\n fillOpacity: 1,\n tickLine: 'y',\n strokeDasharray: '5 5',\n gridAxis: 'x',\n withDots: true,\n connectNulls: true,\n strokeWidth: 2,\n curveType: 'monotone',\n gradientStops: [\n { offset: 0, color: 'red' },\n { offset: 100, color: 'blue' },\n ],\n accessibilityLayer: true,\n} satisfies Partial<LineChartProps>;\n\nconst varsResolver = createVarsResolver<LineChartFactory>((theme, { textColor, gridColor }) => ({\n root: {\n '--chart-text-color': textColor ? getThemeColor(textColor, theme) : undefined,\n '--chart-grid-color': gridColor ? getThemeColor(gridColor, theme) : undefined,\n },\n}));\n\nexport const LineChart = factory<LineChartFactory>((_props) => {\n const props = useProps('LineChart', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n withLegend,\n legendProps,\n series,\n onMouseLeave,\n dataKey,\n withTooltip,\n withXAxis,\n withYAxis,\n gridAxis,\n tickLine,\n xAxisProps,\n yAxisProps,\n unit,\n tooltipAnimationDuration,\n strokeDasharray,\n gridProps,\n tooltipProps,\n referenceLines,\n withDots,\n dotProps,\n activeDotProps,\n strokeWidth,\n lineChartProps,\n connectNulls,\n fillOpacity,\n curveType,\n orientation,\n dir,\n valueFormatter,\n children,\n lineProps,\n xAxisLabel,\n yAxisLabel,\n type,\n gradientStops,\n withRightYAxis,\n rightYAxisLabel,\n rightYAxisProps,\n withPointLabels,\n attributes,\n gridColor,\n accessibilityLayer,\n withBrush,\n brushProps,\n ...others\n } = props;\n\n const theme = useMantineTheme();\n const withXTickLine = gridAxis !== 'none' && (tickLine === 'x' || tickLine === 'xy');\n const withYTickLine = gridAxis !== 'none' && (tickLine === 'y' || tickLine === 'xy');\n const [highlightedArea, setHighlightedArea] = useState<string | number | null>(null);\n const shouldHighlight = highlightedArea !== null;\n const handleMouseLeave = (event: React.MouseEvent<HTMLDivElement>) => {\n setHighlightedArea(null);\n onMouseLeave?.(event);\n };\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<LineChartFactory>({\n classNames,\n styles,\n props,\n });\n\n const getStyles = useStyles<LineChartFactory>({\n name: 'LineChart',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const id = useId();\n const gradientId = `line-chart-gradient-${id}`;\n const stops = gradientStops?.map((stop) => (\n <stop\n key={stop.color}\n offset={`${stop.offset}%`}\n stopColor={getThemeColor(stop.color, theme)}\n />\n ));\n\n const lines = series.map((item) => {\n const color = getThemeColor(item.color, theme);\n const dimmed = shouldHighlight && highlightedArea !== item.name;\n\n return (\n <Line\n {...getStyles('line')}\n key={item.name}\n name={item.name}\n dataKey={item.name}\n dot={\n withDots\n ? {\n fillOpacity: dimmed ? 0 : 1,\n strokeOpacity: dimmed ? 0 : 1,\n strokeWidth: 1,\n fill: type === 'gradient' ? 'var(--mantine-color-gray-7)' : color,\n stroke: type === 'gradient' ? 'white' : color,\n ...dotProps,\n }\n : false\n }\n activeDot={\n withDots\n ? {\n fill: type === 'gradient' ? 'var(--mantine-color-gray-7)' : color,\n stroke: type === 'gradient' ? 'white' : color,\n ...activeDotProps,\n }\n : false\n }\n fill={color}\n stroke={type === 'gradient' ? `url(#${gradientId})` : color}\n strokeWidth={strokeWidth}\n isAnimationActive={false}\n fillOpacity={dimmed ? 0 : fillOpacity}\n strokeOpacity={dimmed ? 0.5 : fillOpacity}\n connectNulls={connectNulls}\n type={item.curveType ?? curveType}\n strokeDasharray={item.strokeDasharray}\n yAxisId={item.yAxisId || undefined}\n label={withPointLabels ? <PointLabel valueFormatter={valueFormatter} /> : undefined}\n {...(typeof lineProps === 'function' ? lineProps(item) : lineProps)}\n />\n );\n });\n\n const referenceLinesItems = referenceLines?.map((line, index) => {\n const color = getThemeColor(line.color, theme);\n return (\n <ReferenceLine\n key={index}\n stroke={line.color ? color : 'var(--chart-grid-color)'}\n strokeWidth={1}\n yAxisId={line.yAxisId || undefined}\n {...line}\n label={{\n fill: line.color ? color : 'currentColor',\n fontSize: 12,\n position: line.labelPosition ?? 'insideBottomLeft',\n ...(typeof line.label === 'object' ? line.label : { value: line.label }),\n }}\n {...getStyles('referenceLine')}\n />\n );\n });\n\n const sharedYAxisProps = {\n axisLine: false,\n ...(orientation === 'vertical'\n ? { dataKey, type: 'category' as const }\n : { type: 'number' as const }),\n tickLine: withYTickLine ? { stroke: 'currentColor' } : false,\n allowDecimals: true,\n unit,\n tickFormatter: orientation === 'vertical' ? undefined : valueFormatter,\n ...getStyles('axis'),\n };\n\n return (\n <Box {...getStyles('root')} onMouseLeave={handleMouseLeave} dir={dir || 'ltr'} {...others}>\n <ResponsiveContainer {...getStyles('container')}>\n <ReChartsLineChart\n data={data}\n layout={orientation}\n margin={{\n bottom: xAxisLabel ? 30 : undefined,\n left: yAxisLabel ? 10 : undefined,\n right: yAxisLabel ? 5 : undefined,\n }}\n accessibilityLayer={accessibilityLayer}\n {...lineChartProps}\n >\n {type === 'gradient' && (\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {stops}\n </linearGradient>\n </defs>\n )}\n\n {withLegend && (\n <Legend\n verticalAlign=\"top\"\n content={(payload) => (\n <ChartLegend\n payload={payload.payload}\n onHighlight={setHighlightedArea}\n legendPosition={legendProps?.verticalAlign || 'top'}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n series={series}\n showColor={type !== 'gradient'}\n attributes={attributes}\n />\n )}\n {...legendProps}\n />\n )}\n\n <XAxis\n hide={!withXAxis}\n {...(orientation === 'vertical' ? { type: 'number' } : { dataKey })}\n tick={{ transform: 'translate(0, 10)', fontSize: 12, fill: 'currentColor' }}\n stroke=\"\"\n interval=\"preserveStartEnd\"\n tickLine={withXTickLine ? { stroke: 'currentColor' } : false}\n minTickGap={5}\n tickFormatter={orientation === 'vertical' ? valueFormatter : undefined}\n {...getStyles('axis')}\n {...xAxisProps}\n >\n {xAxisLabel && (\n <Label position=\"insideBottom\" offset={-20} fontSize={12} {...getStyles('axisLabel')}>\n {xAxisLabel}\n </Label>\n )}\n {xAxisProps?.children}\n </XAxis>\n\n <YAxis\n // yAxisId=\"left\"\n // orientation=\"left\"\n tick={{ transform: 'translate(-10, 0)', fontSize: 12, fill: 'currentColor' }}\n hide={!withYAxis}\n {...sharedYAxisProps}\n {...yAxisProps}\n >\n {yAxisLabel && (\n <Label\n position=\"insideLeft\"\n angle={-90}\n textAnchor=\"middle\"\n fontSize={12}\n offset={-5}\n {...getStyles('axisLabel')}\n >\n {yAxisLabel}\n </Label>\n )}\n {yAxisProps?.children}\n </YAxis>\n\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ transform: 'translate(10, 0)', fontSize: 12, fill: 'currentColor' }}\n hide={!withRightYAxis}\n {...sharedYAxisProps}\n {...rightYAxisProps}\n >\n {rightYAxisLabel && (\n <Label\n position=\"insideRight\"\n angle={90}\n textAnchor=\"middle\"\n fontSize={12}\n offset={-5}\n {...getStyles('axisLabel')}\n >\n {rightYAxisLabel}\n </Label>\n )}\n {yAxisProps?.children}\n </YAxis>\n\n <CartesianGrid\n strokeDasharray={strokeDasharray as string}\n vertical={gridAxis === 'y' || gridAxis === 'xy'}\n horizontal={gridAxis === 'x' || gridAxis === 'xy'}\n {...getStyles('grid')}\n {...gridProps}\n />\n\n {withTooltip && (\n <Tooltip\n animationDuration={tooltipAnimationDuration}\n isAnimationActive={tooltipAnimationDuration !== 0}\n position={orientation === 'vertical' ? {} : { y: 0 }}\n cursor={{\n stroke: 'var(--chart-grid-color)',\n strokeWidth: 1,\n strokeDasharray,\n }}\n content={({ label, payload, labelFormatter }) => (\n <ChartTooltip\n label={labelFormatter && payload ? labelFormatter(label, payload) : label}\n payload={payload}\n unit={unit}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n series={series}\n valueFormatter={valueFormatter}\n showColor={type !== 'gradient'}\n attributes={attributes}\n />\n )}\n {...tooltipProps}\n />\n )}\n\n {lines}\n {referenceLinesItems}\n {withBrush && (\n <ChartBrush\n dataKey={dataKey}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n {...brushProps}\n />\n )}\n {children}\n </ReChartsLineChart>\n </ResponsiveContainer>\n </Box>\n );\n});\n\nLineChart.displayName = '@mantine/charts/LineChart';\nLineChart.classes = classes;\nLineChart.varsResolver = varsResolver;\n\nexport namespace LineChart {\n export type Props = LineChartProps;\n export type CssVariables = LineChartCssVariables;\n export type Factory = LineChartFactory;\n export type Series = LineChartSeries;\n export type StylesNames = LineChartStylesNames;\n export type CurveType = LineChartCurveType;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LineChart.mjs","names":["LineChart","useId","ReChartsLineChart","Tooltip","classes"],"sources":["../../src/LineChart/LineChart.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n CartesianGrid,\n Label,\n Legend,\n Line,\n LineProps,\n LineChart as ReChartsLineChart,\n ReferenceArea,\n ReferenceDot,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n factory,\n Factory,\n getThemeColor,\n MantineColor,\n StylesApiProps,\n useMantineTheme,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useId } from '@mantine/hooks';\nimport { ChartBrush } from '../ChartBrush';\nimport { ChartLegend, ChartLegendStylesNames } from '../ChartLegend';\nimport { ChartTooltip, ChartTooltipStylesNames } from '../ChartTooltip';\nimport { PointLabel } from '../PointLabel/PointLabel';\nimport type {\n BaseChartStylesNames,\n ChartSeries,\n GridChartBaseProps,\n MantineChartDotProps,\n} from '../types';\nimport classes from '../grid-chart.module.css';\n\nexport type LineChartType = 'default' | 'gradient';\n\nexport interface LineChartGradientStop {\n offset: number;\n color: MantineColor;\n}\n\nexport type LineChartCurveType =\n | 'bump'\n | 'linear'\n | 'natural'\n | 'monotone'\n | 'step'\n | 'stepBefore'\n | 'stepAfter';\n\nexport interface LineChartSeries extends ChartSeries {\n strokeDasharray?: string | number;\n curveType?: LineChartCurveType;\n}\n\nexport type LineChartStylesNames =\n | 'line'\n | BaseChartStylesNames\n | ChartLegendStylesNames\n | ChartTooltipStylesNames;\n\nexport type LineChartCssVariables = {\n root: '--chart-text-color' | '--chart-grid-color';\n};\n\nexport interface LineChartProps\n extends BoxProps, GridChartBaseProps, StylesApiProps<LineChartFactory>, ElementProps<'div'> {\n /** Data used to display chart */\n data: Record<string, any>[];\n\n /** An array of objects with `name` and `color` keys. Determines which data should be consumed from the `data` array. */\n series: LineChartSeries[];\n\n /** Controls styles of the line @default 'default' */\n type?: LineChartType;\n\n /** Data used to generate gradient stops @default [{ offset: 0, color: 'red' }, { offset: 100, color: 'blue' }] */\n gradientStops?: LineChartGradientStop[];\n\n /** Type of the curve @default 'monotone' */\n curveType?: LineChartCurveType;\n\n /** Controls fill opacity of all lines @default 1 */\n fillOpacity?: number;\n\n /** Determines whether dots should be displayed @default true */\n withDots?: boolean;\n\n /** Props passed down to all dots. Ignored if `withDots={false}` is set. */\n dotProps?: MantineChartDotProps;\n\n /** Props passed down to all active dots. Ignored if `withDots={false}` is set. */\n activeDotProps?: MantineChartDotProps;\n\n /** Stroke width for the chart lines @default 2 */\n strokeWidth?: number;\n\n /** Props passed down to recharts `LineChart` component */\n lineChartProps?: React.ComponentProps<typeof ReChartsLineChart>;\n\n /** Determines whether points with `null` values should be connected @default true */\n connectNulls?: boolean;\n\n /** Additional components that are rendered inside recharts `LineChart` component */\n children?: React.ReactNode;\n\n /** Props passed down to recharts `Line` component */\n lineProps?:\n | ((series: LineChartSeries) => Partial<Omit<LineProps, 'ref'>>)\n | Partial<Omit<LineProps, 'ref'>>;\n\n /** Determines whether each point should have associated label @default false */\n withPointLabels?: boolean;\n}\n\nexport type LineChartFactory = Factory<{\n props: LineChartProps;\n ref: HTMLDivElement;\n stylesNames: LineChartStylesNames;\n vars: LineChartCssVariables;\n}>;\n\nconst defaultProps = {\n withXAxis: true,\n withYAxis: true,\n withTooltip: true,\n tooltipAnimationDuration: 0,\n fillOpacity: 1,\n tickLine: 'y',\n strokeDasharray: '5 5',\n gridAxis: 'x',\n withDots: true,\n connectNulls: true,\n strokeWidth: 2,\n curveType: 'monotone',\n gradientStops: [\n { offset: 0, color: 'red' },\n { offset: 100, color: 'blue' },\n ],\n accessibilityLayer: true,\n} satisfies Partial<LineChartProps>;\n\nconst varsResolver = createVarsResolver<LineChartFactory>((theme, { textColor, gridColor }) => ({\n root: {\n '--chart-text-color': textColor ? getThemeColor(textColor, theme) : undefined,\n '--chart-grid-color': gridColor ? getThemeColor(gridColor, theme) : undefined,\n },\n}));\n\nexport const LineChart = factory<LineChartFactory>((_props) => {\n const props = useProps('LineChart', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n withLegend,\n legendProps,\n series,\n onMouseLeave,\n dataKey,\n withTooltip,\n withXAxis,\n withYAxis,\n gridAxis,\n tickLine,\n xAxisProps,\n yAxisProps,\n unit,\n tooltipAnimationDuration,\n strokeDasharray,\n gridProps,\n tooltipProps,\n referenceLines,\n referenceAreas,\n referenceDots,\n withDots,\n dotProps,\n activeDotProps,\n strokeWidth,\n lineChartProps,\n connectNulls,\n fillOpacity,\n curveType,\n orientation,\n dir,\n valueFormatter,\n children,\n lineProps,\n xAxisLabel,\n yAxisLabel,\n type,\n gradientStops,\n withRightYAxis,\n rightYAxisLabel,\n rightYAxisProps,\n withPointLabels,\n attributes,\n gridColor,\n accessibilityLayer,\n withBrush,\n brushProps,\n ...others\n } = props;\n\n const theme = useMantineTheme();\n const withXTickLine = gridAxis !== 'none' && (tickLine === 'x' || tickLine === 'xy');\n const withYTickLine = gridAxis !== 'none' && (tickLine === 'y' || tickLine === 'xy');\n const [highlightedArea, setHighlightedArea] = useState<string | number | null>(null);\n const shouldHighlight = highlightedArea !== null;\n const handleMouseLeave = (event: React.MouseEvent<HTMLDivElement>) => {\n setHighlightedArea(null);\n onMouseLeave?.(event);\n };\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<LineChartFactory>({\n classNames,\n styles,\n props,\n });\n\n const getStyles = useStyles<LineChartFactory>({\n name: 'LineChart',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const id = useId();\n const gradientId = `line-chart-gradient-${id}`;\n const stops = gradientStops?.map((stop) => (\n <stop\n key={stop.color}\n offset={`${stop.offset}%`}\n stopColor={getThemeColor(stop.color, theme)}\n />\n ));\n\n const lines = series.map((item) => {\n const color = getThemeColor(item.color, theme);\n const dimmed = shouldHighlight && highlightedArea !== item.name;\n\n return (\n <Line\n {...getStyles('line')}\n key={item.name}\n name={item.name}\n dataKey={item.name}\n dot={\n withDots\n ? {\n fillOpacity: dimmed ? 0 : 1,\n strokeOpacity: dimmed ? 0 : 1,\n strokeWidth: 1,\n fill: type === 'gradient' ? 'var(--mantine-color-gray-7)' : color,\n stroke: type === 'gradient' ? 'white' : color,\n ...dotProps,\n }\n : false\n }\n activeDot={\n withDots\n ? {\n fill: type === 'gradient' ? 'var(--mantine-color-gray-7)' : color,\n stroke: type === 'gradient' ? 'white' : color,\n ...activeDotProps,\n }\n : false\n }\n fill={color}\n stroke={type === 'gradient' ? `url(#${gradientId})` : color}\n strokeWidth={strokeWidth}\n isAnimationActive={false}\n fillOpacity={dimmed ? 0 : fillOpacity}\n strokeOpacity={dimmed ? 0.5 : fillOpacity}\n connectNulls={connectNulls}\n type={item.curveType ?? curveType}\n strokeDasharray={item.strokeDasharray}\n yAxisId={item.yAxisId || undefined}\n label={withPointLabels ? <PointLabel valueFormatter={valueFormatter} /> : undefined}\n {...(typeof lineProps === 'function' ? lineProps(item) : lineProps)}\n />\n );\n });\n\n const referenceLinesItems = referenceLines?.map(\n ({ color: lineColor, labelPosition, ...line }, index) => {\n const color = getThemeColor(lineColor, theme);\n return (\n <ReferenceLine\n key={index}\n stroke={lineColor ? color : 'var(--chart-grid-color)'}\n strokeWidth={1}\n yAxisId={line.yAxisId || undefined}\n {...line}\n label={{\n fill: lineColor ? color : 'currentColor',\n fontSize: 12,\n position: labelPosition ?? 'insideBottomLeft',\n ...(typeof line.label === 'object' ? line.label : { value: line.label }),\n }}\n {...getStyles('referenceLine')}\n />\n );\n }\n );\n\n const referenceAreasItems = referenceAreas?.map(\n ({ color: areaColor, labelPosition, ...area }, index) => {\n const color = getThemeColor(areaColor, theme);\n return (\n <ReferenceArea\n key={index}\n fill={areaColor ? color : 'var(--chart-grid-color)'}\n fillOpacity={0.2}\n stroke={areaColor ? color : 'var(--chart-grid-color)'}\n strokeOpacity={0.6}\n yAxisId={area.yAxisId || undefined}\n {...area}\n label={{\n fill: areaColor ? color : 'currentColor',\n fontSize: 12,\n position: labelPosition ?? 'insideTop',\n ...(typeof area.label === 'object' ? area.label : { value: area.label }),\n }}\n {...getStyles('referenceArea')}\n />\n );\n }\n );\n\n const referenceDotsItems = referenceDots?.map(\n ({ color: dotColor, labelPosition, ...dot }, index) => {\n const color = getThemeColor(dotColor, theme);\n return (\n <ReferenceDot\n key={index}\n r={5}\n fill={dotColor ? color : 'var(--chart-grid-color)'}\n stroke=\"var(--mantine-color-body)\"\n strokeWidth={2}\n yAxisId={dot.yAxisId || undefined}\n {...dot}\n label={{\n fill: dotColor ? color : 'currentColor',\n fontSize: 12,\n position: labelPosition ?? 'top',\n ...(typeof dot.label === 'object' ? dot.label : { value: dot.label }),\n }}\n {...getStyles('referenceDot')}\n />\n );\n }\n );\n\n const sharedYAxisProps = {\n axisLine: false,\n ...(orientation === 'vertical'\n ? { dataKey, type: 'category' as const }\n : { type: 'number' as const }),\n tickLine: withYTickLine ? { stroke: 'currentColor' } : false,\n allowDecimals: true,\n unit,\n tickFormatter: orientation === 'vertical' ? undefined : valueFormatter,\n ...getStyles('axis'),\n };\n\n return (\n <Box {...getStyles('root')} onMouseLeave={handleMouseLeave} dir={dir || 'ltr'} {...others}>\n <ResponsiveContainer {...getStyles('container')}>\n <ReChartsLineChart\n data={data}\n layout={orientation}\n margin={{\n bottom: xAxisLabel ? 30 : undefined,\n left: yAxisLabel ? 10 : undefined,\n right: yAxisLabel ? 5 : undefined,\n }}\n accessibilityLayer={accessibilityLayer}\n {...lineChartProps}\n >\n {referenceAreasItems}\n {type === 'gradient' && (\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {stops}\n </linearGradient>\n </defs>\n )}\n\n {withLegend && (\n <Legend\n verticalAlign=\"top\"\n content={(payload) => (\n <ChartLegend\n payload={payload.payload}\n onHighlight={setHighlightedArea}\n legendPosition={legendProps?.verticalAlign || 'top'}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n series={series}\n showColor={type !== 'gradient'}\n attributes={attributes}\n />\n )}\n {...legendProps}\n />\n )}\n\n <XAxis\n hide={!withXAxis}\n {...(orientation === 'vertical' ? { type: 'number' } : { dataKey })}\n tick={{ transform: 'translate(0, 10)', fontSize: 12, fill: 'currentColor' }}\n stroke=\"\"\n interval=\"preserveStartEnd\"\n tickLine={withXTickLine ? { stroke: 'currentColor' } : false}\n minTickGap={5}\n tickFormatter={orientation === 'vertical' ? valueFormatter : undefined}\n {...getStyles('axis')}\n {...xAxisProps}\n >\n {xAxisLabel && (\n <Label position=\"insideBottom\" offset={-20} fontSize={12} {...getStyles('axisLabel')}>\n {xAxisLabel}\n </Label>\n )}\n {xAxisProps?.children}\n </XAxis>\n\n <YAxis\n // yAxisId=\"left\"\n // orientation=\"left\"\n tick={{ transform: 'translate(-10, 0)', fontSize: 12, fill: 'currentColor' }}\n hide={!withYAxis}\n {...sharedYAxisProps}\n {...yAxisProps}\n >\n {yAxisLabel && (\n <Label\n position=\"insideLeft\"\n angle={-90}\n textAnchor=\"middle\"\n fontSize={12}\n offset={-5}\n {...getStyles('axisLabel')}\n >\n {yAxisLabel}\n </Label>\n )}\n {yAxisProps?.children}\n </YAxis>\n\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ transform: 'translate(10, 0)', fontSize: 12, fill: 'currentColor' }}\n hide={!withRightYAxis}\n {...sharedYAxisProps}\n {...rightYAxisProps}\n >\n {rightYAxisLabel && (\n <Label\n position=\"insideRight\"\n angle={90}\n textAnchor=\"middle\"\n fontSize={12}\n offset={-5}\n {...getStyles('axisLabel')}\n >\n {rightYAxisLabel}\n </Label>\n )}\n {yAxisProps?.children}\n </YAxis>\n\n <CartesianGrid\n strokeDasharray={strokeDasharray as string}\n vertical={gridAxis === 'y' || gridAxis === 'xy'}\n horizontal={gridAxis === 'x' || gridAxis === 'xy'}\n {...getStyles('grid')}\n {...gridProps}\n />\n\n {withTooltip && (\n <Tooltip\n animationDuration={tooltipAnimationDuration}\n isAnimationActive={tooltipAnimationDuration !== 0}\n position={orientation === 'vertical' ? {} : { y: 0 }}\n cursor={{\n stroke: 'var(--chart-grid-color)',\n strokeWidth: 1,\n strokeDasharray,\n }}\n content={({ label, payload, labelFormatter }) => (\n <ChartTooltip\n label={labelFormatter && payload ? labelFormatter(label, payload) : label}\n payload={payload}\n unit={unit}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n series={series}\n valueFormatter={valueFormatter}\n showColor={type !== 'gradient'}\n attributes={attributes}\n />\n )}\n {...tooltipProps}\n />\n )}\n\n {lines}\n {referenceLinesItems}\n {referenceDotsItems}\n {withBrush && (\n <ChartBrush\n dataKey={dataKey}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n {...brushProps}\n />\n )}\n {children}\n </ReChartsLineChart>\n </ResponsiveContainer>\n </Box>\n );\n});\n\nLineChart.displayName = '@mantine/charts/LineChart';\nLineChart.classes = classes;\nLineChart.varsResolver = varsResolver;\n\nexport namespace LineChart {\n export type Props = LineChartProps;\n export type CssVariables = LineChartCssVariables;\n export type Factory = LineChartFactory;\n export type Series = LineChartSeries;\n export type StylesNames = LineChartStylesNames;\n export type CurveType = LineChartCurveType;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { getHeatColor } from "../Heatmap/get-heat-color/get-heat-color.mjs";
|
|
3
|
+
import { buildCellMap, getCellKey } from "./build-cell-map/build-cell-map.mjs";
|
|
4
|
+
import { getDomain } from "./get-domain/get-domain.mjs";
|
|
5
|
+
import { getLegendWidth } from "./get-legend-width/get-legend-width.mjs";
|
|
6
|
+
import { getUniqueValues } from "./get-unique-values/get-unique-values.mjs";
|
|
7
|
+
import MatrixChart_module_default from "./MatrixChart.module.mjs";
|
|
8
|
+
import { Box, Tooltip, factory, getThemeColor, useMantineTheme, useProps, useStyles } from "@mantine/core";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { useMemo, useState } from "react";
|
|
11
|
+
//#region packages/@mantine/charts/src/MatrixChart/MatrixChart.tsx
|
|
12
|
+
const defaultProps = {
|
|
13
|
+
cellSize: 20,
|
|
14
|
+
gap: 1,
|
|
15
|
+
cellRadius: 2,
|
|
16
|
+
yLabelsWidth: 60,
|
|
17
|
+
xLabelsHeight: 60,
|
|
18
|
+
xLabelsPosition: "bottom",
|
|
19
|
+
fontSize: 12,
|
|
20
|
+
xLabelsRotation: -90,
|
|
21
|
+
colors: [
|
|
22
|
+
"var(--matrix-level-1)",
|
|
23
|
+
"var(--matrix-level-2)",
|
|
24
|
+
"var(--matrix-level-3)",
|
|
25
|
+
"var(--matrix-level-4)"
|
|
26
|
+
],
|
|
27
|
+
legendLabels: ["Less", "More"]
|
|
28
|
+
};
|
|
29
|
+
const LEGEND_PADDING = 10;
|
|
30
|
+
const TEXT_GAP = 6;
|
|
31
|
+
const MatrixChart = factory((_props) => {
|
|
32
|
+
const props = useProps("MatrixChart", defaultProps, _props);
|
|
33
|
+
const { classNames, className, style, styles, unstyled, vars, data, xLabels: xLabelsProp, yLabels: yLabelsProp, domain, colors, cellSize, gap, cellRadius, withTooltip, getTooltipLabel, tooltipProps, getCellProps, yLabelsWidth, xLabelsHeight, xLabelsPosition, fontSize, emptyColor, withLegend, legendLabels, withXLabels, withYLabels, xLabelsRotation, attributes, ...others } = props;
|
|
34
|
+
const getStyles = useStyles({
|
|
35
|
+
name: "MatrixChart",
|
|
36
|
+
classes: MatrixChart_module_default,
|
|
37
|
+
props,
|
|
38
|
+
className,
|
|
39
|
+
style,
|
|
40
|
+
classNames,
|
|
41
|
+
styles,
|
|
42
|
+
unstyled,
|
|
43
|
+
attributes,
|
|
44
|
+
vars
|
|
45
|
+
});
|
|
46
|
+
const [hoveredCell, setHoveredCell] = useState(null);
|
|
47
|
+
const xValues = useMemo(() => getUniqueValues(data, "x", xLabelsProp), [data, xLabelsProp]);
|
|
48
|
+
const yValues = useMemo(() => getUniqueValues(data, "y", yLabelsProp), [data, yLabelsProp]);
|
|
49
|
+
const cellMap = useMemo(() => buildCellMap(data), [data]);
|
|
50
|
+
const [min, max] = useMemo(() => getDomain(data, domain), [data, domain]);
|
|
51
|
+
const theme = useMantineTheme();
|
|
52
|
+
const resolvedColors = useMemo(() => {
|
|
53
|
+
return (colors && colors.length > 0 ? colors : defaultProps.colors).map((color) => getThemeColor(color, theme));
|
|
54
|
+
}, [colors, theme]);
|
|
55
|
+
const resolvedEmptyColor = emptyColor ? getThemeColor(emptyColor, theme) : void 0;
|
|
56
|
+
const resolvedCellSize = cellSize;
|
|
57
|
+
const resolvedGap = gap;
|
|
58
|
+
const cellSizeWithGap = resolvedCellSize + resolvedGap;
|
|
59
|
+
const hasXLabels = withXLabels === true && xValues.length > 0;
|
|
60
|
+
const hasYLabels = withYLabels === true && yValues.length > 0;
|
|
61
|
+
const isRotated = xLabelsRotation !== 0 && xLabelsRotation !== void 0;
|
|
62
|
+
const yOffset = hasYLabels ? yLabelsWidth : 0;
|
|
63
|
+
const xLabelAtTop = hasXLabels && xLabelsPosition === "top";
|
|
64
|
+
const xLabelAtBottom = hasXLabels && xLabelsPosition === "bottom";
|
|
65
|
+
const xTopOffset = xLabelAtTop ? xLabelsHeight : 0;
|
|
66
|
+
const xBottomHeight = xLabelAtBottom ? xLabelsHeight : 0;
|
|
67
|
+
const legendHeight = withLegend ? LEGEND_PADDING + resolvedCellSize : 0;
|
|
68
|
+
const gridWidth = Math.max(0, xValues.length * cellSizeWithGap - resolvedGap);
|
|
69
|
+
const gridHeight = Math.max(0, yValues.length * cellSizeWithGap - resolvedGap);
|
|
70
|
+
const legendWidth = withLegend ? getLegendWidth({
|
|
71
|
+
legendLabels,
|
|
72
|
+
fontSize,
|
|
73
|
+
colorsCount: resolvedColors.length,
|
|
74
|
+
cellSize: resolvedCellSize,
|
|
75
|
+
gap: resolvedGap
|
|
76
|
+
}) : 0;
|
|
77
|
+
const svgWidth = Math.max(yOffset + gridWidth, legendWidth);
|
|
78
|
+
const svgHeight = xTopOffset + gridHeight + xBottomHeight + legendHeight;
|
|
79
|
+
const cellNodes = yValues.map((yVal, rowIndex) => xValues.map((xVal, colIndex) => {
|
|
80
|
+
const cell = cellMap.get(getCellKey(xVal, yVal));
|
|
81
|
+
const value = cell?.value ?? null;
|
|
82
|
+
const isEmpty = value === null || !Number.isFinite(value);
|
|
83
|
+
const fill = isEmpty ? resolvedEmptyColor : getHeatColor({
|
|
84
|
+
value,
|
|
85
|
+
min,
|
|
86
|
+
max,
|
|
87
|
+
colors: resolvedColors
|
|
88
|
+
});
|
|
89
|
+
const extraProps = getCellProps && cell ? getCellProps(cell) : {};
|
|
90
|
+
return /* @__PURE__ */ jsx("rect", {
|
|
91
|
+
x: yOffset + colIndex * cellSizeWithGap,
|
|
92
|
+
y: xTopOffset + rowIndex * cellSizeWithGap,
|
|
93
|
+
width: resolvedCellSize,
|
|
94
|
+
height: resolvedCellSize,
|
|
95
|
+
rx: cellRadius,
|
|
96
|
+
fill,
|
|
97
|
+
"data-empty": isEmpty && !emptyColor || void 0,
|
|
98
|
+
onPointerEnter: withTooltip ? () => setHoveredCell(cell || {
|
|
99
|
+
x: xVal,
|
|
100
|
+
y: yVal,
|
|
101
|
+
value: null
|
|
102
|
+
}) : void 0,
|
|
103
|
+
...getStyles("cell"),
|
|
104
|
+
...extraProps
|
|
105
|
+
}, `${colIndex}-${rowIndex}`);
|
|
106
|
+
}));
|
|
107
|
+
const yLabelNodes = hasYLabels ? yValues.map((label, index) => /* @__PURE__ */ jsx("text", {
|
|
108
|
+
x: yOffset - 8,
|
|
109
|
+
y: xTopOffset + index * cellSizeWithGap + resolvedCellSize / 2,
|
|
110
|
+
fontSize,
|
|
111
|
+
textAnchor: "end",
|
|
112
|
+
dominantBaseline: "central",
|
|
113
|
+
...getStyles("yLabel"),
|
|
114
|
+
children: label
|
|
115
|
+
}, index)) : null;
|
|
116
|
+
const xLabelNodes = hasXLabels ? xValues.map((label, index) => {
|
|
117
|
+
const x = yOffset + index * cellSizeWithGap + resolvedCellSize / 2;
|
|
118
|
+
const y = xLabelAtTop ? xLabelsHeight - 8 : xTopOffset + gridHeight + 8;
|
|
119
|
+
return /* @__PURE__ */ jsx("text", {
|
|
120
|
+
x,
|
|
121
|
+
y,
|
|
122
|
+
fontSize,
|
|
123
|
+
textAnchor: isRotated ? "end" : "middle",
|
|
124
|
+
dominantBaseline: isRotated ? "central" : xLabelAtTop ? "auto" : "hanging",
|
|
125
|
+
transform: isRotated ? `rotate(${xLabelsRotation}, ${x}, ${y})` : void 0,
|
|
126
|
+
...getStyles("xLabel"),
|
|
127
|
+
children: label
|
|
128
|
+
}, index);
|
|
129
|
+
}) : null;
|
|
130
|
+
const label = getTooltipLabel && hoveredCell && withTooltip ? getTooltipLabel(hoveredCell) : null;
|
|
131
|
+
const charWidth = fontSize * .6;
|
|
132
|
+
const lessLabel = legendLabels[0];
|
|
133
|
+
const moreLabel = legendLabels[1];
|
|
134
|
+
const lessWidth = lessLabel.length * charWidth;
|
|
135
|
+
const allColors = [resolvedEmptyColor, ...resolvedColors];
|
|
136
|
+
const rectsWidth = allColors.length * resolvedCellSize + (allColors.length - 1) * resolvedGap;
|
|
137
|
+
const legendX = svgWidth - legendWidth;
|
|
138
|
+
const legendY = xTopOffset + gridHeight + xBottomHeight + LEGEND_PADDING;
|
|
139
|
+
const legendNode = withLegend ? /* @__PURE__ */ jsxs("g", {
|
|
140
|
+
transform: `translate(${legendX}, ${legendY})`,
|
|
141
|
+
"data-id": "legend",
|
|
142
|
+
...getStyles("legend"),
|
|
143
|
+
children: [
|
|
144
|
+
/* @__PURE__ */ jsx("text", {
|
|
145
|
+
x: 0,
|
|
146
|
+
y: resolvedCellSize / 2,
|
|
147
|
+
fontSize,
|
|
148
|
+
dominantBaseline: "central",
|
|
149
|
+
...getStyles("legendLabel"),
|
|
150
|
+
children: lessLabel
|
|
151
|
+
}),
|
|
152
|
+
allColors.map((color, i) => /* @__PURE__ */ jsx("rect", {
|
|
153
|
+
x: lessWidth + TEXT_GAP + i * (resolvedCellSize + resolvedGap),
|
|
154
|
+
y: 0,
|
|
155
|
+
width: resolvedCellSize,
|
|
156
|
+
height: resolvedCellSize,
|
|
157
|
+
rx: cellRadius,
|
|
158
|
+
fill: color,
|
|
159
|
+
"data-empty": color === void 0 || void 0,
|
|
160
|
+
...getStyles("legendRect")
|
|
161
|
+
}, i)),
|
|
162
|
+
/* @__PURE__ */ jsx("text", {
|
|
163
|
+
x: lessWidth + TEXT_GAP + rectsWidth + TEXT_GAP,
|
|
164
|
+
y: resolvedCellSize / 2,
|
|
165
|
+
fontSize,
|
|
166
|
+
dominantBaseline: "central",
|
|
167
|
+
...getStyles("legendLabel"),
|
|
168
|
+
children: moreLabel
|
|
169
|
+
})
|
|
170
|
+
]
|
|
171
|
+
}) : null;
|
|
172
|
+
const isLabelled = others["aria-label"] !== void 0 || others["aria-labelledby"] !== void 0;
|
|
173
|
+
const gridLabel = xValues.length > 0 && yValues.length > 0 ? `Heatmap, ${xValues.length} columns by ${yValues.length} rows, values from ${min} to ${max}` : void 0;
|
|
174
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
175
|
+
component: "svg",
|
|
176
|
+
width: svgWidth,
|
|
177
|
+
height: svgHeight,
|
|
178
|
+
role: isLabelled || gridLabel ? "img" : void 0,
|
|
179
|
+
"aria-label": isLabelled ? void 0 : gridLabel,
|
|
180
|
+
...getStyles("root"),
|
|
181
|
+
...others,
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsx(Tooltip.Floating, {
|
|
184
|
+
label,
|
|
185
|
+
disabled: !withTooltip || label == null,
|
|
186
|
+
position: "top",
|
|
187
|
+
...tooltipProps,
|
|
188
|
+
children: /* @__PURE__ */ jsxs("g", {
|
|
189
|
+
"data-id": "all-cells",
|
|
190
|
+
onPointerLeave: withTooltip ? () => setHoveredCell(null) : void 0,
|
|
191
|
+
children: [withTooltip && /* @__PURE__ */ jsx("rect", {
|
|
192
|
+
fill: "transparent",
|
|
193
|
+
x: yOffset,
|
|
194
|
+
y: xTopOffset,
|
|
195
|
+
width: gridWidth,
|
|
196
|
+
height: gridHeight
|
|
197
|
+
}), cellNodes]
|
|
198
|
+
})
|
|
199
|
+
}),
|
|
200
|
+
yLabelNodes,
|
|
201
|
+
xLabelNodes,
|
|
202
|
+
legendNode
|
|
203
|
+
]
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
MatrixChart.displayName = "@mantine/charts/MatrixChart";
|
|
207
|
+
MatrixChart.classes = MatrixChart_module_default;
|
|
208
|
+
//#endregion
|
|
209
|
+
export { MatrixChart };
|
|
210
|
+
|
|
211
|
+
//# sourceMappingURL=MatrixChart.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MatrixChart.mjs","names":["classes"],"sources":["../../src/MatrixChart/MatrixChart.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Box,\n BoxProps,\n ElementProps,\n factory,\n Factory,\n getThemeColor,\n MantineColor,\n StylesApiProps,\n Tooltip,\n TooltipFloatingProps,\n useMantineTheme,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport { getHeatColor } from '../Heatmap/get-heat-color/get-heat-color';\nimport { buildCellMap, getCellKey } from './build-cell-map/build-cell-map';\nimport { getDomain } from './get-domain/get-domain';\nimport { getLegendWidth } from './get-legend-width/get-legend-width';\nimport { getUniqueValues } from './get-unique-values/get-unique-values';\nimport classes from './MatrixChart.module.css';\n\nexport interface MatrixChartCell {\n x: string;\n y: string;\n value: number | null;\n}\n\nexport type MatrixChartData = MatrixChartCell[];\n\nexport type MatrixChartStylesNames =\n | 'root'\n | 'cell'\n | 'xLabel'\n | 'yLabel'\n | 'legend'\n | 'legendLabel'\n | 'legendRect';\n\nexport interface MatrixChartProps\n extends\n BoxProps,\n StylesApiProps<MatrixChartFactory>,\n ElementProps<'svg', 'display' | 'opacity' | 'viewBox' | 'width' | 'height'> {\n /** Array of cell objects with x, y, and value */\n data: MatrixChartData;\n\n /** Labels for x-axis (columns), displayed along top or bottom */\n xLabels?: string[];\n\n /** Labels for y-axis (rows), displayed along left side */\n yLabels?: string[];\n\n /** Value domain [min, max] for color interpolation, auto-calculated if not set */\n domain?: [number, number];\n\n /** Array of colors for value interpolation, by default 4 shades of green colors are used */\n colors?: MantineColor[];\n\n /** Cell size in px, @default 20 */\n cellSize?: number;\n\n /** Gap between cells in px, @default 1 */\n gap?: number;\n\n /** Cell border radius, @default 2 */\n cellRadius?: number;\n\n /** If set, tooltip is displayed on cell hover, requires `getTooltipLabel` to be set @default false */\n withTooltip?: boolean;\n\n /** A function to generate tooltip label based on the hovered cell, required for the tooltip to be visible */\n getTooltipLabel?: (cell: MatrixChartCell) => React.ReactNode;\n\n /** Props passed down to the `Tooltip.Floating` component */\n tooltipProps?: Partial<TooltipFloatingProps>;\n\n /** Callback to add custom props to cells */\n getCellProps?: (cell: MatrixChartCell) => React.ComponentProps<'rect'>;\n\n /** Width reserved for y-axis labels, @default 60 */\n yLabelsWidth?: number;\n\n /** Height reserved for x-axis labels, @default 60 */\n xLabelsHeight?: number;\n\n /** X-axis label position, @default 'bottom' */\n xLabelsPosition?: 'top' | 'bottom';\n\n /** Font size for axis labels, @default 12 */\n fontSize?: number;\n\n /** Color for empty/null cells */\n emptyColor?: MantineColor;\n\n /** Whether to show legend, @default false */\n withLegend?: boolean;\n\n /** Legend labels, @default ['Less', 'More'] */\n legendLabels?: [string, string];\n\n /** If set, x-axis labels are displayed, @default false */\n withXLabels?: boolean;\n\n /** If set, y-axis labels are displayed, @default false */\n withYLabels?: boolean;\n\n /** Rotation angle for x-axis labels in degrees, @default -90 */\n xLabelsRotation?: number;\n}\n\nexport type MatrixChartFactory = Factory<{\n props: MatrixChartProps;\n ref: SVGSVGElement;\n stylesNames: MatrixChartStylesNames;\n}>;\n\nconst defaultProps = {\n cellSize: 20,\n gap: 1,\n cellRadius: 2,\n yLabelsWidth: 60,\n xLabelsHeight: 60,\n xLabelsPosition: 'bottom',\n fontSize: 12,\n xLabelsRotation: -90,\n colors: [\n 'var(--matrix-level-1)',\n 'var(--matrix-level-2)',\n 'var(--matrix-level-3)',\n 'var(--matrix-level-4)',\n ],\n legendLabels: ['Less', 'More'] as [string, string],\n} satisfies Partial<MatrixChartProps>;\n\nconst LEGEND_PADDING = 10;\nconst TEXT_GAP = 6;\n\nexport const MatrixChart = factory<MatrixChartFactory>((_props) => {\n const props = useProps('MatrixChart', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n data,\n xLabels: xLabelsProp,\n yLabels: yLabelsProp,\n domain,\n colors,\n cellSize,\n gap,\n cellRadius,\n withTooltip,\n getTooltipLabel,\n tooltipProps,\n getCellProps,\n yLabelsWidth,\n xLabelsHeight,\n xLabelsPosition,\n fontSize,\n emptyColor,\n withLegend,\n legendLabels,\n withXLabels,\n withYLabels,\n xLabelsRotation,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<MatrixChartFactory>({\n name: 'MatrixChart',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n });\n\n const [hoveredCell, setHoveredCell] = useState<MatrixChartCell | null>(null);\n\n const xValues = useMemo(() => getUniqueValues(data, 'x', xLabelsProp), [data, xLabelsProp]);\n\n const yValues = useMemo(() => getUniqueValues(data, 'y', yLabelsProp), [data, yLabelsProp]);\n\n const cellMap = useMemo(() => buildCellMap(data), [data]);\n const [min, max] = useMemo(() => getDomain(data, domain), [data, domain]);\n\n const theme = useMantineTheme();\n\n const resolvedColors = useMemo(() => {\n const palette = colors && colors.length > 0 ? colors : defaultProps.colors;\n return palette.map((color) => getThemeColor(color, theme));\n }, [colors, theme]);\n\n const resolvedEmptyColor = emptyColor ? getThemeColor(emptyColor, theme) : undefined;\n\n const resolvedCellSize = cellSize!;\n const resolvedGap = gap!;\n const cellSizeWithGap = resolvedCellSize + resolvedGap;\n\n const hasXLabels = withXLabels === true && xValues.length > 0;\n const hasYLabels = withYLabels === true && yValues.length > 0;\n const isRotated = xLabelsRotation !== 0 && xLabelsRotation !== undefined;\n\n const yOffset = hasYLabels ? yLabelsWidth! : 0;\n const xLabelAtTop = hasXLabels && xLabelsPosition === 'top';\n const xLabelAtBottom = hasXLabels && xLabelsPosition === 'bottom';\n const xTopOffset = xLabelAtTop ? xLabelsHeight! : 0;\n const xBottomHeight = xLabelAtBottom ? xLabelsHeight! : 0;\n\n const legendHeight = withLegend ? LEGEND_PADDING + resolvedCellSize : 0;\n\n const gridWidth = Math.max(0, xValues.length * cellSizeWithGap - resolvedGap);\n const gridHeight = Math.max(0, yValues.length * cellSizeWithGap - resolvedGap);\n\n const legendWidth = withLegend\n ? getLegendWidth({\n legendLabels: legendLabels!,\n fontSize: fontSize!,\n colorsCount: resolvedColors.length,\n cellSize: resolvedCellSize,\n gap: resolvedGap,\n })\n : 0;\n\n const svgWidth = Math.max(yOffset + gridWidth, legendWidth);\n const svgHeight = xTopOffset + gridHeight + xBottomHeight + legendHeight;\n\n const cellNodes = yValues.map((yVal, rowIndex) =>\n xValues.map((xVal, colIndex) => {\n const cell = cellMap.get(getCellKey(xVal, yVal));\n const value = cell?.value ?? null;\n // Non-finite values are excluded from the domain, so they cannot be interpolated\n // to a color either – they are treated the same way as missing cells.\n const isEmpty = value === null || !Number.isFinite(value);\n\n const fill = isEmpty\n ? resolvedEmptyColor\n : getHeatColor({ value, min, max, colors: resolvedColors });\n\n const extraProps = getCellProps && cell ? getCellProps(cell) : {};\n\n return (\n <rect\n key={`${colIndex}-${rowIndex}`}\n x={yOffset + colIndex * cellSizeWithGap}\n y={xTopOffset + rowIndex * cellSizeWithGap}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRadius}\n fill={fill}\n data-empty={(isEmpty && !emptyColor) || undefined}\n onPointerEnter={\n withTooltip\n ? () => setHoveredCell(cell || { x: xVal, y: yVal, value: null })\n : undefined\n }\n {...getStyles('cell')}\n {...extraProps}\n />\n );\n })\n );\n\n const yLabelNodes = hasYLabels\n ? yValues.map((label, index) => (\n <text\n key={index}\n x={yOffset - 8}\n y={xTopOffset + index * cellSizeWithGap + resolvedCellSize / 2}\n fontSize={fontSize}\n textAnchor=\"end\"\n dominantBaseline=\"central\"\n {...getStyles('yLabel')}\n >\n {label}\n </text>\n ))\n : null;\n\n const xLabelNodes = hasXLabels\n ? xValues.map((label, index) => {\n const x = yOffset + index * cellSizeWithGap + resolvedCellSize / 2;\n const y = xLabelAtTop ? xLabelsHeight! - 8 : xTopOffset + gridHeight + 8;\n\n return (\n <text\n key={index}\n x={x}\n y={y}\n fontSize={fontSize}\n textAnchor={isRotated ? 'end' : 'middle'}\n dominantBaseline={isRotated ? 'central' : xLabelAtTop ? 'auto' : 'hanging'}\n transform={isRotated ? `rotate(${xLabelsRotation}, ${x}, ${y})` : undefined}\n {...getStyles('xLabel')}\n >\n {label}\n </text>\n );\n })\n : null;\n\n const label = getTooltipLabel && hoveredCell && withTooltip ? getTooltipLabel(hoveredCell) : null;\n\n const charWidth = fontSize! * 0.6;\n const lessLabel = legendLabels![0];\n const moreLabel = legendLabels![1];\n const lessWidth = lessLabel.length * charWidth;\n const allColors = [resolvedEmptyColor, ...resolvedColors];\n const rectsWidth = allColors.length * resolvedCellSize + (allColors.length - 1) * resolvedGap;\n const legendX = svgWidth - legendWidth;\n const legendY = xTopOffset + gridHeight + xBottomHeight + LEGEND_PADDING;\n\n const legendNode = withLegend ? (\n <g transform={`translate(${legendX}, ${legendY})`} data-id=\"legend\" {...getStyles('legend')}>\n <text\n x={0}\n y={resolvedCellSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {lessLabel}\n </text>\n {allColors.map((color, i) => (\n <rect\n key={i}\n x={lessWidth + TEXT_GAP + i * (resolvedCellSize + resolvedGap)}\n y={0}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRadius}\n fill={color}\n data-empty={color === undefined || undefined}\n {...getStyles('legendRect')}\n />\n ))}\n <text\n x={lessWidth + TEXT_GAP + rectsWidth + TEXT_GAP}\n y={resolvedCellSize / 2}\n fontSize={fontSize}\n dominantBaseline=\"central\"\n {...getStyles('legendLabel')}\n >\n {moreLabel}\n </text>\n </g>\n ) : null;\n\n // Individual cells carry no accessible information, so the chart is announced as one image\n // rather than letting assistive tech walk a grid of anonymous rectangles. Listing every\n // cell would be unusable on a large matrix, so the generated summary describes its shape\n // and value range instead – the same approach as `WaffleChart`, bounded for a 2D grid.\n // A caller-supplied `aria-label` or `aria-labelledby` always wins.\n const isLabelled = others['aria-label'] !== undefined || others['aria-labelledby'] !== undefined;\n const gridLabel =\n xValues.length > 0 && yValues.length > 0\n ? `Heatmap, ${xValues.length} columns by ${yValues.length} rows, values from ${min} to ${max}`\n : undefined;\n\n return (\n <Box\n component=\"svg\"\n width={svgWidth}\n height={svgHeight}\n role={isLabelled || gridLabel ? 'img' : undefined}\n aria-label={isLabelled ? undefined : gridLabel}\n {...getStyles('root')}\n {...others}\n >\n <Tooltip.Floating\n label={label}\n disabled={!withTooltip || label == null}\n position=\"top\"\n {...tooltipProps}\n >\n <g\n data-id=\"all-cells\"\n onPointerLeave={withTooltip ? () => setHoveredCell(null) : undefined}\n >\n {withTooltip && (\n <rect\n fill=\"transparent\"\n x={yOffset}\n y={xTopOffset}\n width={gridWidth}\n height={gridHeight}\n />\n )}\n {cellNodes}\n </g>\n </Tooltip.Floating>\n {yLabelNodes}\n {xLabelNodes}\n {legendNode}\n </Box>\n );\n});\n\nMatrixChart.displayName = '@mantine/charts/MatrixChart';\nMatrixChart.classes = classes;\n"],"mappings":"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"}
|