@automattic/charts 4.1.0 → 4.2.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/CHANGELOG.md +28 -0
- package/TOKENS.md +7 -5
- package/dist/index.cjs +1115 -471
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +39 -1
- package/dist/index.d.cts +116 -16
- package/dist/index.d.ts +116 -16
- package/dist/index.js +1115 -473
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/charts/area-chart/area-chart.tsx +2 -1
- package/src/charts/area-chart/private/overlays.tsx +1 -2
- package/src/charts/area-chart/test/area-chart.test.tsx +31 -0
- package/src/charts/bar-chart/bar-chart.tsx +67 -17
- package/src/charts/bar-chart/index.ts +1 -1
- package/src/charts/bar-chart/private/band-highlight.tsx +85 -0
- package/src/charts/bar-chart/private/band-scale.ts +13 -0
- package/src/charts/bar-chart/private/band-tooltip.tsx +138 -0
- package/src/charts/bar-chart/private/comparison-bars.tsx +5 -10
- package/src/charts/bar-chart/private/index.ts +2 -0
- package/src/charts/bar-chart/private/test/band-highlight.test.tsx +109 -0
- package/src/charts/bar-chart/private/test/band-tooltip.test.ts +26 -0
- package/src/charts/bar-chart/private/truncated-tick-component.tsx +1 -1
- package/src/charts/bar-chart/private/use-bar-chart-options.ts +1 -1
- package/src/charts/bar-chart/test/bar-chart-pointer-events.test.tsx +11 -23
- package/src/charts/bar-chart/test/bar-chart.test.tsx +565 -1
- package/src/charts/bar-list-chart/bar-list-chart.tsx +5 -3
- package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +1 -1
- package/src/charts/conversion-funnel-chart/types.ts +4 -2
- package/src/charts/geo-chart/types.ts +4 -2
- package/src/charts/heatmap-chart/{private/build-calendar-data.ts → build-calendar-data.ts} +15 -45
- package/src/charts/heatmap-chart/build-month-calendar-data.ts +124 -0
- package/src/charts/heatmap-chart/heatmap-chart.module.scss +32 -0
- package/src/charts/heatmap-chart/heatmap-chart.tsx +191 -114
- package/src/charts/heatmap-chart/index.ts +15 -3
- package/src/charts/heatmap-chart/private/civil-day.ts +26 -0
- package/src/charts/heatmap-chart/private/column-groups.ts +71 -0
- package/src/charts/heatmap-chart/private/heatmap-legend.tsx +19 -3
- package/src/charts/heatmap-chart/private/index.ts +2 -2
- package/src/charts/heatmap-chart/private/keyboard-navigation.ts +201 -0
- package/src/charts/heatmap-chart/test/build-calendar-data.test.ts +37 -1
- package/src/charts/heatmap-chart/test/build-month-calendar-data.test.ts +194 -0
- package/src/charts/heatmap-chart/test/column-groups.test.ts +83 -0
- package/src/charts/heatmap-chart/test/heatmap-chart.test.tsx +428 -2
- package/src/charts/heatmap-chart/test/keyboard-navigation.test.ts +25 -0
- package/src/charts/heatmap-chart/test/use-calendar-heatmap-data.test.tsx +1 -1
- package/src/charts/heatmap-chart/test/use-month-calendar-heatmap-data.test.tsx +90 -0
- package/src/charts/heatmap-chart/test/zoned-calendar-data.test.ts +1 -1
- package/src/charts/heatmap-chart/test/zoned-month-calendar-data.test.ts +23 -0
- package/src/charts/heatmap-chart/types.ts +88 -3
- package/src/charts/heatmap-chart/use-calendar-heatmap-data.ts +2 -2
- package/src/charts/heatmap-chart/use-month-calendar-heatmap-data.ts +34 -0
- package/src/charts/leaderboard-chart/types.ts +13 -14
- package/src/charts/line-chart/line-chart.tsx +3 -2
- package/src/charts/line-chart/private/line-chart-annotation.tsx +1 -1
- package/src/charts/line-chart/test/line-chart.test.tsx +31 -0
- package/src/charts/line-chart/types.ts +2 -2
- package/src/charts/private/time-axis-options.ts +1 -1
- package/src/charts/private/with-responsive/with-responsive.tsx +2 -2
- package/src/charts/private/x-zoom/test/x-zoom.test.tsx +1 -3
- package/src/charts/private/x-zoom/x-zoom.tsx +1 -2
- package/src/components/legend/private/base-legend.tsx +1 -1
- package/src/components/tooltip/accessible-tooltip.tsx +146 -37
- package/src/components/tooltip/base-tooltip.module.scss +6 -1
- package/src/components/tooltip/private/bounded-tooltip.tsx +12 -6
- package/src/components/tooltip/test/accessible-tooltip.test.tsx +160 -0
- package/src/components/tooltip/test/bounded-tooltip.test.tsx +17 -0
- package/src/components/tooltip/test/xy-chart-tooltip.test.tsx +29 -3
- package/src/components/tooltip/xy-chart-tooltip.tsx +11 -11
- package/src/hooks/test/use-element-size.test.tsx +13 -13
- package/src/hooks/use-xychart-theme.ts +1 -1
- package/src/index.ts +7 -1
- package/src/providers/chart-context/themes.ts +1 -0
- package/src/styles/chart-scope.scss +11 -3
- package/src/styles/test/chart-scope.test.ts +36 -2
- package/src/types.ts +6 -13
- package/src/utils/format-metric-value.ts +4 -4
- package/src/utils/get-edge-tick-widths.ts +1 -1
- package/src/utils/get-styles.ts +1 -1
- package/src/visx/types.ts +7 -10
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getStringWidth as getStringWidth$1 } from "./visx/text/index.js";
|
|
2
2
|
import { formatNumber, formatNumberCompact } from "@automattic/number-formatters";
|
|
3
|
-
import { AnimatedAreaSeries, AnimatedAreaStack, AreaSeries, Axis, BarGroup, BarSeries, DataContext, Grid, TooltipContext, XYChart, buildChartTheme } from "@visx/xychart";
|
|
3
|
+
import { AnimatedAreaSeries, AnimatedAreaStack, AreaSeries, Axis, BarGroup, BarSeries, DataContext, Grid, TooltipContext, XYChart, buildChartTheme, useEventEmitter } from "@visx/xychart";
|
|
4
4
|
import { __, _x, sprintf } from "@wordpress/i18n";
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
import * as React from "react";
|
|
@@ -981,7 +981,8 @@ const defaultTheme = {
|
|
|
981
981
|
},
|
|
982
982
|
heatmapChart: {
|
|
983
983
|
compactCellGap: 2,
|
|
984
|
-
compactCellSize: 11
|
|
984
|
+
compactCellSize: 11,
|
|
985
|
+
groupGap: 24
|
|
985
986
|
}
|
|
986
987
|
};
|
|
987
988
|
//#endregion
|
|
@@ -2181,7 +2182,10 @@ function useChartLegendItems(data, options = {}, legendShape) {
|
|
|
2181
2182
|
}
|
|
2182
2183
|
//#endregion
|
|
2183
2184
|
//#region src/components/tooltip/base-tooltip.module.scss
|
|
2184
|
-
var base_tooltip_module_default = {
|
|
2185
|
+
var base_tooltip_module_default = {
|
|
2186
|
+
"surface": "a8ccharts--zY0xG-surface",
|
|
2187
|
+
"tooltip": "a8ccharts--zY0xG-tooltip"
|
|
2188
|
+
};
|
|
2185
2189
|
//#endregion
|
|
2186
2190
|
//#region src/components/tooltip/base-tooltip.tsx
|
|
2187
2191
|
const DefaultTooltipContent = ({ data }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
@@ -2231,7 +2235,8 @@ const findClippingAncestor = (wrapper) => {
|
|
|
2231
2235
|
/**
|
|
2232
2236
|
* Where the box goes, in wrapper coordinates. Automatic placement flips to
|
|
2233
2237
|
* the side that clips less, then clamps inside `bounds`; below-axis placement
|
|
2234
|
-
* is centered on the anchor and clamped horizontally
|
|
2238
|
+
* is centered on the anchor and clamped horizontally; beside placement preserves
|
|
2239
|
+
* the anchor's y and only flips horizontally before bounds clamping.
|
|
2235
2240
|
*
|
|
2236
2241
|
* The flip measures against the visible part of the wrapper, its intersection
|
|
2237
2242
|
* with `bounds`. Only the clamp is bound by the page: a box that fits inside the
|
|
@@ -2245,7 +2250,7 @@ const findClippingAncestor = (wrapper) => {
|
|
|
2245
2250
|
* @param params.offsetTop - Gap between the anchor and the box, vertically.
|
|
2246
2251
|
* @param params.box - Rendered size of the box.
|
|
2247
2252
|
* @param params.wrapper - The wrapper's own edges, in wrapper coordinates.
|
|
2248
|
-
* @param params.placement -
|
|
2253
|
+
* @param params.placement - Below-axis, beside without vertical flipping, or automatic flipping.
|
|
2249
2254
|
* @param params.bounds - Edges the box must keep inside, in wrapper coordinates.
|
|
2250
2255
|
* @return The box's top-left corner; fixed placement preserves the axis's subpixel y.
|
|
2251
2256
|
*/
|
|
@@ -2269,7 +2274,8 @@ const getBoundedPosition = ({ left, top, offsetLeft, offsetTop, box, wrapper, bo
|
|
|
2269
2274
|
const upY = top - offsetTop - box.height;
|
|
2270
2275
|
const downOverflow = downY + box.height - fit.bottom;
|
|
2271
2276
|
const upOverflow = fit.top - upY;
|
|
2272
|
-
let y =
|
|
2277
|
+
let y = top;
|
|
2278
|
+
if (placement !== "beside") y = downOverflow > 0 && downOverflow > upOverflow ? upY : downY;
|
|
2273
2279
|
x = clamp(x, bounds.left, bounds.right, box.width);
|
|
2274
2280
|
y = clamp(y, bounds.top, bounds.bottom, box.height);
|
|
2275
2281
|
return {
|
|
@@ -2285,8 +2291,7 @@ const getBoundedPosition = ({ left, top, offsetLeft, offsetTop, box, wrapper, bo
|
|
|
2285
2291
|
* alone would let the box spill into an `overflow: hidden` card and be cut off.
|
|
2286
2292
|
*
|
|
2287
2293
|
* Re-measures on every render, so a box whose content changes width between
|
|
2288
|
-
* two hovers is placed for its current size.
|
|
2289
|
-
* below-axis exception.
|
|
2294
|
+
* two hovers is placed for its current size.
|
|
2290
2295
|
*
|
|
2291
2296
|
* @param props - visx `Tooltip` props.
|
|
2292
2297
|
* @param props.left - Anchor x, in wrapper coordinates.
|
|
@@ -2296,7 +2301,7 @@ const getBoundedPosition = ({ left, top, offsetLeft, offsetTop, box, wrapper, bo
|
|
|
2296
2301
|
* @param props.style - Box styles; visx's defaults unless `unstyled`.
|
|
2297
2302
|
* @param props.unstyled - Skip `style` and leave the box bare.
|
|
2298
2303
|
* @param props.children - Box content.
|
|
2299
|
-
* @param props.placement -
|
|
2304
|
+
* @param props.placement - Below-axis, beside without vertical flipping, or automatic flipping.
|
|
2300
2305
|
* @return The tooltip box.
|
|
2301
2306
|
*/
|
|
2302
2307
|
const BoundedTooltip = ({ left = 0, top = 0, offsetLeft = DEFAULT_OFFSET, offsetTop = DEFAULT_OFFSET, style = defaultStyles, unstyled = false, children, placement = "auto", ...rest }) => {
|
|
@@ -2399,7 +2404,6 @@ const crosshairPaintProps = (props = {}) => {
|
|
|
2399
2404
|
};
|
|
2400
2405
|
const DEFAULT_GLYPH_RADIUS = 4;
|
|
2401
2406
|
const FALLBACK_COLOR = "#222";
|
|
2402
|
-
const DEFAULT_TOOLTIP_Z_INDEX = 3;
|
|
2403
2407
|
const PORTAL_OPTIONS = /* @__PURE__ */ new Set([
|
|
2404
2408
|
"scroll",
|
|
2405
2409
|
"debounce",
|
|
@@ -2427,7 +2431,7 @@ const defaultRenderGlyph$1 = ({ key, ...props }) => /* @__PURE__ */ jsx(DefaultG
|
|
|
2427
2431
|
seriesKey: key,
|
|
2428
2432
|
...props
|
|
2429
2433
|
}, key);
|
|
2430
|
-
const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, renderGlyph = defaultRenderGlyph$1, glyphStyle, snapTooltipToDatumX = false, snapTooltipToDatumY = false, showVerticalCrosshair = false, showHorizontalCrosshair = false, showDatumGlyph = false, showSeriesGlyphs = false, verticalCrosshairStyle, horizontalCrosshairStyle, detectBounds = true, tooltipPlacement = "auto", zIndex =
|
|
2434
|
+
const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, renderGlyph = defaultRenderGlyph$1, glyphStyle, snapTooltipToDatumX = false, snapTooltipToDatumY = false, showVerticalCrosshair = false, showHorizontalCrosshair = false, showDatumGlyph = false, showSeriesGlyphs = false, verticalCrosshairStyle, horizontalCrosshairStyle, detectBounds = true, tooltipPlacement = "auto", tooltipAnchorTop, zIndex = 3, style, ...rest }) => {
|
|
2431
2435
|
const tooltipProps = Object.fromEntries(Object.entries(rest).filter(([key]) => !PORTAL_OPTIONS.has(key)));
|
|
2432
2436
|
const { colorScale, theme, innerHeight = 0, innerWidth = 0, margin, xScale, yScale, dataRegistry } = useContext(DataContext) || {};
|
|
2433
2437
|
const tooltipContent = renderTooltip ? renderTooltip({
|
|
@@ -2482,12 +2486,12 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
|
|
|
2482
2486
|
const crosshairStroke = theme?.gridStyles?.stroke ?? theme?.htmlLabel?.color ?? FALLBACK_COLOR;
|
|
2483
2487
|
const marginTop = margin?.top ?? 0;
|
|
2484
2488
|
const marginLeft = margin?.left ?? 0;
|
|
2485
|
-
const TooltipComponent = detectBounds || tooltipPlacement
|
|
2489
|
+
const TooltipComponent = detectBounds || tooltipPlacement !== "auto" ? BoundedTooltip : Tooltip;
|
|
2486
2490
|
const boxStyle = {
|
|
2487
2491
|
...defaultStyles,
|
|
2488
2492
|
zIndex,
|
|
2489
2493
|
backgroundColor: theme?.backgroundColor ?? "white",
|
|
2490
|
-
boxShadow: `0 1px 2px ${theme?.htmlLabel?.color ? `${theme.htmlLabel.color}55` : "#22222255"}`,
|
|
2494
|
+
boxShadow: `0 1px 2px ${isValidHexColor(theme?.htmlLabel?.color) ? `${theme.htmlLabel.color}55` : "#22222255"}`,
|
|
2491
2495
|
...theme?.htmlLabel,
|
|
2492
2496
|
...style
|
|
2493
2497
|
};
|
|
@@ -2519,11 +2523,11 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
|
|
|
2519
2523
|
]
|
|
2520
2524
|
}), container && createPortal(/* @__PURE__ */ jsx(TooltipComponent, {
|
|
2521
2525
|
left: tooltipLeft,
|
|
2522
|
-
top: tooltipPlacement === "below-axis" ? marginTop + innerHeight + (margin?.bottom ?? 0) : tooltipTop,
|
|
2526
|
+
top: tooltipPlacement === "below-axis" ? marginTop + innerHeight + (margin?.bottom ?? 0) : tooltipAnchorTop ?? tooltipTop,
|
|
2523
2527
|
style: boxStyle,
|
|
2524
2528
|
applyPositionStyle: true,
|
|
2525
2529
|
...tooltipProps,
|
|
2526
|
-
...tooltipPlacement
|
|
2530
|
+
...tooltipPlacement !== "auto" && { placement: tooltipPlacement },
|
|
2527
2531
|
children: tooltipContent
|
|
2528
2532
|
}), container)] });
|
|
2529
2533
|
};
|
|
@@ -2589,11 +2593,32 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
|
|
|
2589
2593
|
return flattened;
|
|
2590
2594
|
}, [series, mode]);
|
|
2591
2595
|
const hasKeyboardSelection = useRef(false);
|
|
2596
|
+
const closeTooltipNow = useCallback(() => {
|
|
2597
|
+
tooltipContext?.updateTooltip({
|
|
2598
|
+
tooltipOpen: false,
|
|
2599
|
+
tooltipLeft: void 0,
|
|
2600
|
+
tooltipTop: void 0,
|
|
2601
|
+
tooltipData: void 0
|
|
2602
|
+
});
|
|
2603
|
+
}, []);
|
|
2604
|
+
const chartId = useContext(ChartInstanceContext)?.chartId;
|
|
2605
|
+
const { getHiddenSeries } = useGlobalChartsContext();
|
|
2606
|
+
const hiddenSeriesKey = chartId ? JSON.stringify([...getHiddenSeries(chartId)].sort()) : void 0;
|
|
2607
|
+
const lastHiddenSeriesKey = useRef(hiddenSeriesKey);
|
|
2608
|
+
useEffect(() => {
|
|
2609
|
+
const changed = lastHiddenSeriesKey.current !== hiddenSeriesKey;
|
|
2610
|
+
lastHiddenSeriesKey.current = hiddenSeriesKey;
|
|
2611
|
+
if (changed && selectedIndex === void 0) closeTooltipNow();
|
|
2612
|
+
}, [
|
|
2613
|
+
hiddenSeriesKey,
|
|
2614
|
+
selectedIndex,
|
|
2615
|
+
closeTooltipNow
|
|
2616
|
+
]);
|
|
2592
2617
|
useEffect(() => {
|
|
2593
2618
|
if (selectedIndex === void 0) {
|
|
2594
2619
|
if (hasKeyboardSelection.current) {
|
|
2595
2620
|
hasKeyboardSelection.current = false;
|
|
2596
|
-
|
|
2621
|
+
closeTooltipNow();
|
|
2597
2622
|
}
|
|
2598
2623
|
return;
|
|
2599
2624
|
}
|
|
@@ -2662,15 +2687,45 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
|
|
|
2662
2687
|
renderTooltip: focusableRenderTooltip
|
|
2663
2688
|
});
|
|
2664
2689
|
};
|
|
2665
|
-
const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate, preventTooltipScroll = false }) => {
|
|
2690
|
+
const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate, preventTooltipScroll = false, visibleSeriesKey }) => {
|
|
2691
|
+
const getChartRoot = useCallback(() => chartRef.current?.closest("[role=\"grid\"]") ?? chartRef.current, [chartRef]);
|
|
2692
|
+
const focusWithoutScrollIfNeeded = useCallback((element) => {
|
|
2693
|
+
if (preventTooltipScroll) element?.focus({ preventScroll: true });
|
|
2694
|
+
else element?.focus();
|
|
2695
|
+
}, [preventTooltipScroll]);
|
|
2696
|
+
const tooltipRef = useCallback((element) => {
|
|
2697
|
+
if (element && selectedIndex !== void 0) focusWithoutScrollIfNeeded(element);
|
|
2698
|
+
}, [focusWithoutScrollIfNeeded, selectedIndex]);
|
|
2699
|
+
const previousTotalPoints = useRef(totalPoints);
|
|
2700
|
+
const previousVisibleSeriesKey = useRef(visibleSeriesKey);
|
|
2701
|
+
useEffect(() => {
|
|
2702
|
+
const countChanged = previousTotalPoints.current !== totalPoints;
|
|
2703
|
+
const seriesChanged = previousVisibleSeriesKey.current !== visibleSeriesKey;
|
|
2704
|
+
previousTotalPoints.current = totalPoints;
|
|
2705
|
+
previousVisibleSeriesKey.current = visibleSeriesKey;
|
|
2706
|
+
if (!countChanged && !seriesChanged || selectedIndex === void 0) return;
|
|
2707
|
+
const { activeElement } = document;
|
|
2708
|
+
const focusIsInChart = activeElement !== null && !!getChartRoot()?.contains(activeElement);
|
|
2709
|
+
if (totalPoints === 0 || !focusIsInChart || !countChanged) {
|
|
2710
|
+
setSelectedIndex(void 0);
|
|
2711
|
+
setIsNavigating(false);
|
|
2712
|
+
if (focusIsInChart) focusWithoutScrollIfNeeded(getChartRoot());
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
setSelectedIndex(Math.min(selectedIndex, totalPoints - 1));
|
|
2716
|
+
}, [
|
|
2717
|
+
selectedIndex,
|
|
2718
|
+
totalPoints,
|
|
2719
|
+
visibleSeriesKey,
|
|
2720
|
+
setSelectedIndex,
|
|
2721
|
+
setIsNavigating,
|
|
2722
|
+
getChartRoot,
|
|
2723
|
+
focusWithoutScrollIfNeeded
|
|
2724
|
+
]);
|
|
2666
2725
|
return {
|
|
2667
|
-
tooltipRef
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
else element.focus();
|
|
2671
|
-
}
|
|
2672
|
-
}, [preventTooltipScroll, selectedIndex]),
|
|
2673
|
-
onChartFocus: useCallback(() => {
|
|
2726
|
+
tooltipRef,
|
|
2727
|
+
onChartFocus: useCallback((event) => {
|
|
2728
|
+
if (event.currentTarget.contains(event.relatedTarget)) return;
|
|
2674
2729
|
if (!isNavigating && selectedIndex !== void 0) setSelectedIndex(0);
|
|
2675
2730
|
}, [
|
|
2676
2731
|
isNavigating,
|
|
@@ -2681,38 +2736,34 @@ const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating,
|
|
|
2681
2736
|
setIsNavigating(false);
|
|
2682
2737
|
}, [setIsNavigating]),
|
|
2683
2738
|
onChartKeyDown: useCallback((event) => {
|
|
2684
|
-
if (
|
|
2685
|
-
|
|
2686
|
-
|
|
2739
|
+
if (event.key === "Tab" || event.key === "Escape") {
|
|
2740
|
+
if (event.key === "Escape" && selectedIndex !== void 0) event.preventDefault();
|
|
2741
|
+
focusWithoutScrollIfNeeded(getChartRoot());
|
|
2687
2742
|
setSelectedIndex(void 0);
|
|
2688
2743
|
setIsNavigating(false);
|
|
2689
2744
|
return;
|
|
2690
2745
|
}
|
|
2746
|
+
if (totalPoints === 0) return;
|
|
2691
2747
|
const currentSelectedIndex = selectedIndex === void 0 ? -1 : selectedIndex;
|
|
2692
|
-
if (
|
|
2693
|
-
|
|
2694
|
-
setSelectedIndex(void 0);
|
|
2695
|
-
setIsNavigating(false);
|
|
2696
|
-
return;
|
|
2697
|
-
}
|
|
2698
|
-
event.preventDefault();
|
|
2699
|
-
if (["ArrowRight"].includes(event.key)) {
|
|
2748
|
+
if (event.key === "ArrowRight") {
|
|
2749
|
+
event.preventDefault();
|
|
2700
2750
|
setIsNavigating(true);
|
|
2701
|
-
setSelectedIndex((currentSelectedIndex + 1
|
|
2702
|
-
} else if (
|
|
2751
|
+
setSelectedIndex(Math.min(currentSelectedIndex + 1, totalPoints - 1));
|
|
2752
|
+
} else if (event.key === "ArrowLeft") {
|
|
2753
|
+
event.preventDefault();
|
|
2703
2754
|
setIsNavigating(true);
|
|
2704
|
-
setSelectedIndex((currentSelectedIndex - 1
|
|
2705
|
-
} else if (event.key === "
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
} else if ((event.key === "Enter" || event.key === " ") && selectedIndex !== void 0) onActivate?.(selectedIndex);
|
|
2755
|
+
setSelectedIndex(Math.max(currentSelectedIndex - 1, 0));
|
|
2756
|
+
} else if ((event.key === "Enter" || event.key === " ") && selectedIndex !== void 0) {
|
|
2757
|
+
event.preventDefault();
|
|
2758
|
+
onActivate?.(selectedIndex);
|
|
2759
|
+
}
|
|
2710
2760
|
}, [
|
|
2711
2761
|
totalPoints,
|
|
2712
2762
|
selectedIndex,
|
|
2713
2763
|
setSelectedIndex,
|
|
2714
2764
|
setIsNavigating,
|
|
2715
|
-
|
|
2765
|
+
getChartRoot,
|
|
2766
|
+
focusWithoutScrollIfNeeded,
|
|
2716
2767
|
onActivate
|
|
2717
2768
|
])
|
|
2718
2769
|
};
|
|
@@ -4316,6 +4367,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4316
4367
|
children: ({ contentHeight }) => {
|
|
4317
4368
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
4318
4369
|
return /* @__PURE__ */ jsx("div", {
|
|
4370
|
+
ref: chartRef,
|
|
4319
4371
|
role: "grid",
|
|
4320
4372
|
"aria-label": __("Line chart", "jetpack-charts"),
|
|
4321
4373
|
tabIndex: 0,
|
|
@@ -4323,7 +4375,6 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4323
4375
|
onFocus: onChartFocus,
|
|
4324
4376
|
onBlur: onChartBlur,
|
|
4325
4377
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
4326
|
-
ref: chartRef,
|
|
4327
4378
|
className: xy_plot_module_default["xy-plot"],
|
|
4328
4379
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
4329
4380
|
theme,
|
|
@@ -4821,6 +4872,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4821
4872
|
children: ({ contentHeight }) => {
|
|
4822
4873
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
4823
4874
|
return /* @__PURE__ */ jsx("div", {
|
|
4875
|
+
ref: chartRef,
|
|
4824
4876
|
role: "grid",
|
|
4825
4877
|
"aria-label": __("Area chart", "jetpack-charts"),
|
|
4826
4878
|
tabIndex: 0,
|
|
@@ -4828,7 +4880,6 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4828
4880
|
onFocus: onChartFocus,
|
|
4829
4881
|
onBlur: onChartBlur,
|
|
4830
4882
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
4831
|
-
ref: chartRef,
|
|
4832
4883
|
className: xy_plot_module_default["xy-plot"],
|
|
4833
4884
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
4834
4885
|
theme,
|
|
@@ -5270,6 +5321,20 @@ function useBarChartOptions(data, horizontal, options = {}, isSeriesRendered = A
|
|
|
5270
5321
|
]);
|
|
5271
5322
|
}
|
|
5272
5323
|
//#endregion
|
|
5324
|
+
//#region src/charts/bar-chart/private/band-scale.ts
|
|
5325
|
+
/**
|
|
5326
|
+
* Match the inner slot scale used by visx BarGroup.
|
|
5327
|
+
* @param keys - Visible primary series keys.
|
|
5328
|
+
* @param bandwidth - Category band width.
|
|
5329
|
+
* @param padding - Padding between slots.
|
|
5330
|
+
* @return The grouped bar scale.
|
|
5331
|
+
*/
|
|
5332
|
+
const createGroupScale = (keys, bandwidth, padding) => scaleBand({
|
|
5333
|
+
domain: keys,
|
|
5334
|
+
range: [0, bandwidth],
|
|
5335
|
+
padding
|
|
5336
|
+
});
|
|
5337
|
+
//#endregion
|
|
5273
5338
|
//#region src/charts/bar-chart/private/comparison-bars-geometry.ts
|
|
5274
5339
|
/**
|
|
5275
5340
|
* Output position of a value scale's baseline: zero if in-domain, else the
|
|
@@ -5342,11 +5407,7 @@ const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizont
|
|
|
5342
5407
|
const valueScale = horizontal ? xScale : yScale;
|
|
5343
5408
|
const bandwidth = bandScale.bandwidth ? bandScale.bandwidth() : 0;
|
|
5344
5409
|
if (!bandwidth) return null;
|
|
5345
|
-
const groupScale =
|
|
5346
|
-
domain: primaryKeys,
|
|
5347
|
-
range: [0, bandwidth],
|
|
5348
|
-
padding: groupPadding
|
|
5349
|
-
});
|
|
5410
|
+
const groupScale = createGroupScale(primaryKeys, bandwidth, groupPadding);
|
|
5350
5411
|
const slotThickness = groupScale.bandwidth();
|
|
5351
5412
|
const baseline = getValueScaleBaseline(valueScale);
|
|
5352
5413
|
const bandAccessor = horizontal ? yAccessor : xAccessor;
|
|
@@ -5398,6 +5459,163 @@ const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizont
|
|
|
5398
5459
|
});
|
|
5399
5460
|
};
|
|
5400
5461
|
//#endregion
|
|
5462
|
+
//#region src/charts/bar-chart/private/band-highlight.tsx
|
|
5463
|
+
/**
|
|
5464
|
+
* Render and report the active band using the chart’s registered scales.
|
|
5465
|
+
* @param root0 - Highlight options.
|
|
5466
|
+
* @param root0.visible - Whether to paint the band.
|
|
5467
|
+
* @param root0.horizontal - Whether categories run vertically.
|
|
5468
|
+
* @param root0.onChange - Receives selected band geometry.
|
|
5469
|
+
* @return The optional band highlight.
|
|
5470
|
+
*/
|
|
5471
|
+
function BandHighlight({ visible, horizontal, onChange }) {
|
|
5472
|
+
const { xScale, yScale, dataRegistry, margin, innerWidth, innerHeight } = useContext(DataContext);
|
|
5473
|
+
const { tooltipOpen, tooltipData } = useContext(TooltipContext);
|
|
5474
|
+
const nearest = tooltipData?.nearestDatum;
|
|
5475
|
+
const selection = useMemo(() => {
|
|
5476
|
+
if (!tooltipOpen || !nearest) return null;
|
|
5477
|
+
const scale = horizontal ? yScale : xScale;
|
|
5478
|
+
const entry = dataRegistry?.get(nearest.key);
|
|
5479
|
+
const accessor = horizontal ? entry?.yAccessor : entry?.xAccessor;
|
|
5480
|
+
if (!scale?.bandwidth || !accessor) return null;
|
|
5481
|
+
const position = scale(accessor(nearest.datum));
|
|
5482
|
+
if (position === void 0 || !Number.isFinite(position)) return null;
|
|
5483
|
+
return {
|
|
5484
|
+
datum: nearest.datum,
|
|
5485
|
+
x: horizontal ? margin?.left ?? 0 : position,
|
|
5486
|
+
y: horizontal ? position : margin?.top ?? 0,
|
|
5487
|
+
width: horizontal ? innerWidth : scale.bandwidth(),
|
|
5488
|
+
height: horizontal ? scale.bandwidth() : innerHeight
|
|
5489
|
+
};
|
|
5490
|
+
}, [
|
|
5491
|
+
tooltipOpen,
|
|
5492
|
+
nearest,
|
|
5493
|
+
horizontal,
|
|
5494
|
+
xScale,
|
|
5495
|
+
yScale,
|
|
5496
|
+
dataRegistry,
|
|
5497
|
+
margin,
|
|
5498
|
+
innerWidth,
|
|
5499
|
+
innerHeight
|
|
5500
|
+
]);
|
|
5501
|
+
const stableSelection = useDeepMemo(selection);
|
|
5502
|
+
const onChangeRef = useRef(onChange);
|
|
5503
|
+
onChangeRef.current = onChange;
|
|
5504
|
+
useEffect(() => {
|
|
5505
|
+
onChangeRef.current?.(stableSelection);
|
|
5506
|
+
}, [stableSelection]);
|
|
5507
|
+
useEffect(() => () => onChangeRef.current?.(null), []);
|
|
5508
|
+
if (!visible || !selection) return null;
|
|
5509
|
+
const { x, y, width, height } = selection;
|
|
5510
|
+
return /* @__PURE__ */ jsx("rect", {
|
|
5511
|
+
x,
|
|
5512
|
+
y,
|
|
5513
|
+
width,
|
|
5514
|
+
height,
|
|
5515
|
+
pointerEvents: "none",
|
|
5516
|
+
fill: CATALOG_POINTERS.surfaceSecondary
|
|
5517
|
+
});
|
|
5518
|
+
}
|
|
5519
|
+
//#endregion
|
|
5520
|
+
//#region src/charts/bar-chart/private/band-tooltip.tsx
|
|
5521
|
+
/**
|
|
5522
|
+
* Find a category by its painted center, including outer padding and reversed ranges.
|
|
5523
|
+
* @param data - Registered series points.
|
|
5524
|
+
* @param accessor - Category accessor.
|
|
5525
|
+
* @param scale - Rendered category band scale.
|
|
5526
|
+
* @param position - Pointer coordinate on the category axis.
|
|
5527
|
+
* @return Index of the nearest category, or -1 when none is registered.
|
|
5528
|
+
*/
|
|
5529
|
+
function nearestBandIndex(data, accessor, scale, position) {
|
|
5530
|
+
let nearest = -1;
|
|
5531
|
+
let distance = Infinity;
|
|
5532
|
+
data.forEach((datum, index) => {
|
|
5533
|
+
const start = scale(accessor(datum));
|
|
5534
|
+
if (start === void 0) return;
|
|
5535
|
+
const candidate = Math.abs(start + scale.bandwidth() / 2 - position);
|
|
5536
|
+
if (candidate < distance) {
|
|
5537
|
+
distance = candidate;
|
|
5538
|
+
nearest = index;
|
|
5539
|
+
}
|
|
5540
|
+
});
|
|
5541
|
+
return nearest;
|
|
5542
|
+
}
|
|
5543
|
+
/**
|
|
5544
|
+
* Correct visx's range-based band inversion, which omits outer padding.
|
|
5545
|
+
* @param root0 - Registered series selection.
|
|
5546
|
+
* @param root0.keys - Visible series keys.
|
|
5547
|
+
* @param root0.groupPadding - Padding between grouped bars.
|
|
5548
|
+
* @param root0.withTooltips - Whether pointer events update the tooltip.
|
|
5549
|
+
* @param root0.onPointerDown - Receives the corrected pointer-down datum.
|
|
5550
|
+
* @param root0.onPointerUp - Receives the corrected pointer-up datum.
|
|
5551
|
+
* @return No visual content.
|
|
5552
|
+
*/
|
|
5553
|
+
function BandTooltip({ keys, groupPadding, withTooltips, onPointerDown, onPointerUp }) {
|
|
5554
|
+
const { xScale, yScale, dataRegistry, horizontal } = useContext(DataContext);
|
|
5555
|
+
const { showTooltip } = useContext(TooltipContext);
|
|
5556
|
+
const scale = horizontal ? yScale : xScale;
|
|
5557
|
+
const bandwidth = scale?.bandwidth?.() ?? 0;
|
|
5558
|
+
const groupScale = useMemo(() => createGroupScale(keys, bandwidth, groupPadding), [
|
|
5559
|
+
keys,
|
|
5560
|
+
bandwidth,
|
|
5561
|
+
groupPadding
|
|
5562
|
+
]);
|
|
5563
|
+
const getSelections = useCallback((params) => {
|
|
5564
|
+
const point = params?.svgPoint;
|
|
5565
|
+
if (!point || !scale?.bandwidth) return [];
|
|
5566
|
+
const selections = [];
|
|
5567
|
+
for (const key of keys) {
|
|
5568
|
+
const entry = dataRegistry?.get(key);
|
|
5569
|
+
if (!entry) continue;
|
|
5570
|
+
const accessor = horizontal ? entry.yAccessor : entry.xAccessor;
|
|
5571
|
+
const index = nearestBandIndex(entry.data, accessor, scale, horizontal ? point.y : point.x);
|
|
5572
|
+
if (index < 0) continue;
|
|
5573
|
+
const datum = entry.data[index];
|
|
5574
|
+
const start = Number(scale(accessor(datum))) + Number(groupScale(key));
|
|
5575
|
+
const end = start + groupScale.step();
|
|
5576
|
+
const position = horizontal ? point.y : point.x;
|
|
5577
|
+
const distance = position >= start && position <= end ? 0 : Math.abs(position - (start + end) / 2);
|
|
5578
|
+
selections.push({
|
|
5579
|
+
event: params.event,
|
|
5580
|
+
key,
|
|
5581
|
+
datum,
|
|
5582
|
+
index,
|
|
5583
|
+
svgPoint: point,
|
|
5584
|
+
distanceX: horizontal ? 0 : distance,
|
|
5585
|
+
distanceY: horizontal ? distance : 0
|
|
5586
|
+
});
|
|
5587
|
+
}
|
|
5588
|
+
return selections;
|
|
5589
|
+
}, [
|
|
5590
|
+
scale,
|
|
5591
|
+
dataRegistry,
|
|
5592
|
+
horizontal,
|
|
5593
|
+
keys,
|
|
5594
|
+
groupScale
|
|
5595
|
+
]);
|
|
5596
|
+
const handlePointer = useCallback((params) => {
|
|
5597
|
+
const selections = getSelections(params);
|
|
5598
|
+
if (withTooltips && params?.event.type !== "pointerup") selections.forEach(showTooltip);
|
|
5599
|
+
const callback = params?.event.type === "pointerdown" ? onPointerDown : onPointerUp;
|
|
5600
|
+
if (params?.event.type === "pointermove" || !callback) return;
|
|
5601
|
+
const nearest = selections.reduce((best, selection) => {
|
|
5602
|
+
const distance = (value) => Math.hypot(value.distanceX, value.distanceY);
|
|
5603
|
+
return !best || distance(selection) <= distance(best) ? selection : best;
|
|
5604
|
+
}, void 0);
|
|
5605
|
+
if (nearest) callback(nearest);
|
|
5606
|
+
}, [
|
|
5607
|
+
getSelections,
|
|
5608
|
+
withTooltips,
|
|
5609
|
+
showTooltip,
|
|
5610
|
+
onPointerDown,
|
|
5611
|
+
onPointerUp
|
|
5612
|
+
]);
|
|
5613
|
+
useEventEmitter("pointermove", withTooltips ? handlePointer : void 0);
|
|
5614
|
+
useEventEmitter("pointerdown", handlePointer);
|
|
5615
|
+
useEventEmitter("pointerup", onPointerUp ? handlePointer : void 0);
|
|
5616
|
+
return null;
|
|
5617
|
+
}
|
|
5618
|
+
//#endregion
|
|
5401
5619
|
//#region src/charts/bar-chart/bar-chart.tsx
|
|
5402
5620
|
const validateData$2 = (data) => {
|
|
5403
5621
|
if (!data?.length) return "No data available";
|
|
@@ -5409,7 +5627,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ jsx("div", {
|
|
|
5409
5627
|
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
5410
5628
|
children: sprintf(__("%1$s: %2$s", "jetpack-charts"), label, value)
|
|
5411
5629
|
});
|
|
5412
|
-
const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
|
|
5630
|
+
const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, tooltipPlacement, tooltipAnchorTop, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, withBandHighlight = false, onBandHighlightChange, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
|
|
5413
5631
|
const legendInteractive = legend.interactive ?? false;
|
|
5414
5632
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
5415
5633
|
const horizontal = orientation === "horizontal";
|
|
@@ -5435,8 +5653,6 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5435
5653
|
}, [height]);
|
|
5436
5654
|
const [selectedIndex, setSelectedIndex] = useState(void 0);
|
|
5437
5655
|
const [isNavigating, setIsNavigating] = useState(false);
|
|
5438
|
-
const primarySeriesForNav = dataWithVisibleZeros.filter((s) => s.options?.type !== "comparison");
|
|
5439
|
-
const totalPoints = Math.max(0, ...primarySeriesForNav.map((s) => s.data?.length || 0)) * primarySeriesForNav.length;
|
|
5440
5656
|
const seriesWithVisibility = useMemo(() => dataWithVisibleZeros.map((series, index) => ({
|
|
5441
5657
|
series,
|
|
5442
5658
|
index,
|
|
@@ -5446,6 +5662,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5446
5662
|
return seriesWithVisibility.every(({ isVisible }) => !isVisible);
|
|
5447
5663
|
}, [seriesWithVisibility]);
|
|
5448
5664
|
const primaryEntries = useMemo(() => seriesWithVisibility.filter(({ isVisible, series }) => isVisible && series.options?.type !== "comparison"), [seriesWithVisibility]);
|
|
5665
|
+
const totalPoints = Math.max(0, ...primaryEntries.map((e) => e.series.data.length)) * primaryEntries.length;
|
|
5449
5666
|
const primaryKeys = useMemo(() => primaryEntries.map(({ series }) => series.label), [primaryEntries]);
|
|
5450
5667
|
const primarySeries = useMemo(() => primaryEntries.map(({ series }) => series), [primaryEntries]);
|
|
5451
5668
|
const activateSelectedBar = useCallback((index) => {
|
|
@@ -5460,6 +5677,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5460
5677
|
key: series.label
|
|
5461
5678
|
});
|
|
5462
5679
|
}, [primaryEntries, onDatumActivate]);
|
|
5680
|
+
const visibleSeriesKey = useMemo(() => JSON.stringify(primaryKeys), [primaryKeys]);
|
|
5463
5681
|
const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
|
|
5464
5682
|
selectedIndex,
|
|
5465
5683
|
setSelectedIndex,
|
|
@@ -5467,7 +5685,8 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5467
5685
|
setIsNavigating,
|
|
5468
5686
|
chartRef,
|
|
5469
5687
|
totalPoints,
|
|
5470
|
-
onActivate: activateSelectedBar
|
|
5688
|
+
onActivate: activateSelectedBar,
|
|
5689
|
+
visibleSeriesKey
|
|
5471
5690
|
});
|
|
5472
5691
|
const comparisonEntries = useMemo(() => {
|
|
5473
5692
|
const primaryByGroup = new Map(primaryEntries.map(({ series, index }) => [series.group, {
|
|
@@ -5530,7 +5749,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5530
5749
|
chartOptions.yScale,
|
|
5531
5750
|
horizontal
|
|
5532
5751
|
]);
|
|
5533
|
-
const getBarBackground = useCallback((index) => () => withPatterns ? `url(#${getPatternId(chartId, index)})` : getElementStyles({
|
|
5752
|
+
const getBarBackground = useCallback((index) => (datum) => withPatterns ? `url(#${getPatternId(chartId, index)})` : datum.color ?? getElementStyles({
|
|
5534
5753
|
data: dataSorted[index],
|
|
5535
5754
|
index
|
|
5536
5755
|
}).color, [
|
|
@@ -5700,13 +5919,13 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5700
5919
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
5701
5920
|
return /* @__PURE__ */ jsx("div", {
|
|
5702
5921
|
role: "grid",
|
|
5922
|
+
ref: chartRef,
|
|
5703
5923
|
"aria-label": __("Bar chart", "jetpack-charts"),
|
|
5704
5924
|
tabIndex: 0,
|
|
5705
5925
|
onKeyDown: onChartKeyDown,
|
|
5706
5926
|
onFocus: onChartFocus,
|
|
5707
5927
|
onBlur: onChartBlur,
|
|
5708
5928
|
children: chartHeight > 0 && /* @__PURE__ */ jsx("div", {
|
|
5709
|
-
ref: chartRef,
|
|
5710
5929
|
className: xy_plot_module_default["xy-plot"],
|
|
5711
5930
|
children: /* @__PURE__ */ jsxs(XYChart, {
|
|
5712
5931
|
theme,
|
|
@@ -5719,15 +5938,24 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5719
5938
|
xScale,
|
|
5720
5939
|
yScale,
|
|
5721
5940
|
horizontal,
|
|
5722
|
-
onPointerDown,
|
|
5723
|
-
onPointerUp,
|
|
5724
5941
|
pointerEventsDataKey: "nearest",
|
|
5725
5942
|
children: [
|
|
5726
|
-
|
|
5943
|
+
withTooltips && (withBandHighlight || onBandHighlightChange) && /* @__PURE__ */ jsx(BandHighlight, {
|
|
5944
|
+
visible: withBandHighlight,
|
|
5945
|
+
horizontal,
|
|
5946
|
+
onChange: onBandHighlightChange
|
|
5947
|
+
}),
|
|
5948
|
+
!allSeriesHidden && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Grid, {
|
|
5727
5949
|
columns: gridVisibility.includes("y"),
|
|
5950
|
+
rows: false,
|
|
5951
|
+
numTicks: 4,
|
|
5952
|
+
tickValues: chartOptions.axis.x.tickValues
|
|
5953
|
+
}), /* @__PURE__ */ jsx(Grid, {
|
|
5954
|
+
columns: false,
|
|
5728
5955
|
rows: gridVisibility.includes("x"),
|
|
5729
|
-
numTicks: 4
|
|
5730
|
-
|
|
5956
|
+
numTicks: 4,
|
|
5957
|
+
tickValues: chartOptions.axis.y.tickValues
|
|
5958
|
+
})] }),
|
|
5731
5959
|
withPatterns && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("defs", { children: dataSorted.map((seriesData, index) => renderPattern(index, getElementStyles({
|
|
5732
5960
|
data: seriesData,
|
|
5733
5961
|
index
|
|
@@ -5763,8 +5991,17 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
5763
5991
|
colorAccessor: getBarBackground(index)
|
|
5764
5992
|
}, seriesData?.label))
|
|
5765
5993
|
}),
|
|
5994
|
+
(withTooltips || onPointerDown || onPointerUp) && /* @__PURE__ */ jsx(BandTooltip, {
|
|
5995
|
+
keys: primaryKeys,
|
|
5996
|
+
groupPadding,
|
|
5997
|
+
withTooltips,
|
|
5998
|
+
onPointerDown,
|
|
5999
|
+
onPointerUp
|
|
6000
|
+
}),
|
|
5766
6001
|
!allSeriesHidden && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Axis, { ...chartOptions.axis.x }), /* @__PURE__ */ jsx(Axis, { ...chartOptions.axis.y })] }),
|
|
5767
6002
|
withTooltips && /* @__PURE__ */ jsx(AccessibleTooltip, {
|
|
6003
|
+
tooltipPlacement,
|
|
6004
|
+
tooltipAnchorTop,
|
|
5768
6005
|
detectBounds: true,
|
|
5769
6006
|
snapTooltipToDatumX: true,
|
|
5770
6007
|
snapTooltipToDatumY: true,
|
|
@@ -6586,8 +6823,11 @@ var heatmap_chart_module_default = {
|
|
|
6586
6823
|
"heatmap-chart__gap-start": "a8ccharts-O3YMOW-heatmap-chart__gap-start",
|
|
6587
6824
|
"heatmap-chart__grid": "a8ccharts-O3YMOW-heatmap-chart__grid",
|
|
6588
6825
|
"heatmap-chart__grid--compact": "a8ccharts-O3YMOW-heatmap-chart__grid--compact",
|
|
6826
|
+
"heatmap-chart__grid--flex-gaps": "a8ccharts-O3YMOW-heatmap-chart__grid--flex-gaps",
|
|
6589
6827
|
"heatmap-chart__grid--height-capped": "a8ccharts-O3YMOW-heatmap-chart__grid--height-capped",
|
|
6828
|
+
"heatmap-chart__group-label": "a8ccharts-O3YMOW-heatmap-chart__group-label",
|
|
6590
6829
|
"heatmap-chart__legend-label": "a8ccharts-O3YMOW-heatmap-chart__legend-label",
|
|
6830
|
+
"heatmap-chart__legend-scale--bar": "a8ccharts-O3YMOW-heatmap-chart__legend-scale--bar",
|
|
6591
6831
|
"heatmap-chart__legend-swatch": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch",
|
|
6592
6832
|
"heatmap-chart__row": "a8ccharts-O3YMOW-heatmap-chart__row",
|
|
6593
6833
|
"heatmap-chart__row-label": "a8ccharts-O3YMOW-heatmap-chart__row-label",
|
|
@@ -6632,290 +6872,267 @@ const getNormalizedValue = (value, extent) => {
|
|
|
6632
6872
|
return Math.min(1, Math.max(0, (value - min) / (max - min)));
|
|
6633
6873
|
};
|
|
6634
6874
|
//#endregion
|
|
6635
|
-
//#region src/charts/heatmap-chart/private/
|
|
6636
|
-
|
|
6637
|
-
const
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
const
|
|
6645
|
-
const
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
*/
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6875
|
+
//#region src/charts/heatmap-chart/private/heatmap-context.ts
|
|
6876
|
+
/** Shared by the chart and legend without importing back from `heatmap-chart.tsx`. */
|
|
6877
|
+
const HeatmapContext = createContext(null);
|
|
6878
|
+
//#endregion
|
|
6879
|
+
//#region src/charts/heatmap-chart/private/heatmap-legend.tsx
|
|
6880
|
+
const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }) => {
|
|
6881
|
+
const context = useContext(HeatmapContext);
|
|
6882
|
+
const { legend } = useGlobalChartsTheme();
|
|
6883
|
+
if (!context) return null;
|
|
6884
|
+
const { primaryColorHex } = context;
|
|
6885
|
+
const labelStyle = legend.labelStyles;
|
|
6886
|
+
return /* @__PURE__ */ jsxs(Stack, {
|
|
6887
|
+
direction: "row",
|
|
6888
|
+
gap: "xs",
|
|
6889
|
+
align: "center",
|
|
6890
|
+
children: [
|
|
6891
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
6892
|
+
variant: "body-sm",
|
|
6893
|
+
className: heatmap_chart_module_default["heatmap-chart__legend-label"],
|
|
6894
|
+
style: labelStyle,
|
|
6895
|
+
children: lessLabel ?? __("Less", "jetpack-charts")
|
|
6896
|
+
}),
|
|
6897
|
+
/* @__PURE__ */ jsx(Stack, {
|
|
6898
|
+
direction: "row",
|
|
6899
|
+
gap: variant === "bar" ? void 0 : "xs",
|
|
6900
|
+
"aria-hidden": "true",
|
|
6901
|
+
className: variant === "bar" ? heatmap_chart_module_default["heatmap-chart__legend-scale--bar"] : void 0,
|
|
6902
|
+
children: Array.from({ length: steps }, (_, index) => {
|
|
6903
|
+
const intensity = steps <= 1 ? 1 : index / (steps - 1);
|
|
6904
|
+
return /* @__PURE__ */ jsx("span", {
|
|
6905
|
+
className: heatmap_chart_module_default["heatmap-chart__legend-swatch"],
|
|
6906
|
+
style: {
|
|
6907
|
+
"--a8c-charts-color-heatmap-primary": primaryColorHex,
|
|
6908
|
+
"--a8c-charts-heatmap-cell-intensity": intensity
|
|
6909
|
+
}
|
|
6910
|
+
}, index);
|
|
6911
|
+
})
|
|
6912
|
+
}),
|
|
6913
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
6914
|
+
variant: "body-sm",
|
|
6915
|
+
className: heatmap_chart_module_default["heatmap-chart__legend-label"],
|
|
6916
|
+
style: labelStyle,
|
|
6917
|
+
children: moreLabel ?? __("More", "jetpack-charts")
|
|
6918
|
+
})
|
|
6919
|
+
]
|
|
6920
|
+
});
|
|
6667
6921
|
};
|
|
6922
|
+
//#endregion
|
|
6923
|
+
//#region src/charts/heatmap-chart/private/column-groups.ts
|
|
6924
|
+
const isSpan = (span) => Number.isInteger(span) && span > 0;
|
|
6668
6925
|
/**
|
|
6669
|
-
*
|
|
6926
|
+
* Validates column groups and lays them over the columns.
|
|
6670
6927
|
*
|
|
6671
|
-
* @param
|
|
6672
|
-
* @
|
|
6928
|
+
* @param groups - Groups as passed to the chart.
|
|
6929
|
+
* @param columnCount - Number of data columns.
|
|
6930
|
+
* @param firstLine - Grid column line of the first data column.
|
|
6931
|
+
* @return Grid column lines for every column and group; no groups when the input was unusable.
|
|
6673
6932
|
*/
|
|
6674
|
-
const
|
|
6675
|
-
const
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6933
|
+
const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
6934
|
+
const ungrouped = () => ({
|
|
6935
|
+
columns: Array.from({ length: columnCount }, (_, index) => ({
|
|
6936
|
+
line: firstLine + index,
|
|
6937
|
+
gapBefore: false
|
|
6938
|
+
})),
|
|
6939
|
+
groups: []
|
|
6940
|
+
});
|
|
6941
|
+
if (!groups || groups.length === 0 || columnCount === 0) return ungrouped();
|
|
6942
|
+
const spans = groups.map((group) => group.span);
|
|
6943
|
+
const total = spans.reduce((sum, span) => sum + span, 0);
|
|
6944
|
+
if (!spans.every(isSpan) || total > columnCount) {
|
|
6945
|
+
warnOnce(`heatmap:columnGroups:${JSON.stringify(spans)}:${columnCount}`, `columnGroups spans ${JSON.stringify(spans)} must be positive integers that fit the ${columnCount} columns, so no groups are drawn.`);
|
|
6946
|
+
return ungrouped();
|
|
6947
|
+
}
|
|
6948
|
+
const columns = [];
|
|
6949
|
+
const laidOut = [];
|
|
6950
|
+
let line = firstLine;
|
|
6951
|
+
groups.forEach((group, groupIndex) => {
|
|
6952
|
+
if (groupIndex > 0) line += 1;
|
|
6953
|
+
laidOut.push({
|
|
6954
|
+
...group,
|
|
6955
|
+
line
|
|
6956
|
+
});
|
|
6957
|
+
for (let offset = 0; offset < group.span; offset++) {
|
|
6958
|
+
columns.push({
|
|
6959
|
+
line,
|
|
6960
|
+
gapBefore: groupIndex > 0 && offset === 0,
|
|
6961
|
+
group: groupIndex
|
|
6962
|
+
});
|
|
6963
|
+
line += 1;
|
|
6964
|
+
}
|
|
6965
|
+
});
|
|
6966
|
+
while (columns.length < columnCount) {
|
|
6967
|
+
columns.push({
|
|
6968
|
+
line,
|
|
6969
|
+
gapBefore: false
|
|
6970
|
+
});
|
|
6971
|
+
line += 1;
|
|
6972
|
+
}
|
|
6973
|
+
return {
|
|
6974
|
+
columns,
|
|
6975
|
+
groups: laidOut
|
|
6976
|
+
};
|
|
6679
6977
|
};
|
|
6978
|
+
//#endregion
|
|
6979
|
+
//#region src/charts/heatmap-chart/private/keyboard-navigation.ts
|
|
6980
|
+
const ARROW_KEYS = [
|
|
6981
|
+
"ArrowLeft",
|
|
6982
|
+
"ArrowRight",
|
|
6983
|
+
"ArrowUp",
|
|
6984
|
+
"ArrowDown"
|
|
6985
|
+
];
|
|
6986
|
+
const PAGE_KEYS = ["PageUp", "PageDown"];
|
|
6987
|
+
const isNavigationKey = (key, mode) => ARROW_KEYS.includes(key) || mode === "calendar" && PAGE_KEYS.includes(key);
|
|
6988
|
+
const inGrid = (grid, { column, row }) => column >= 0 && column < grid.columns && row >= 0 && row < grid.rows;
|
|
6989
|
+
const firstSelectable = (grid, cells) => cells.find((cell) => inGrid(grid, cell) && !grid.isInert(cell.column, cell.row));
|
|
6680
6990
|
/**
|
|
6681
|
-
*
|
|
6991
|
+
* Column-major scan for the first selectable cell.
|
|
6682
6992
|
*
|
|
6683
|
-
* @param
|
|
6684
|
-
* @return
|
|
6993
|
+
* @param grid - The grid.
|
|
6994
|
+
* @return The cell, or undefined when every slot is inert.
|
|
6685
6995
|
*/
|
|
6686
|
-
const
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
});
|
|
6691
|
-
return (date) => {
|
|
6692
|
-
const parts = formatter.formatToParts(date);
|
|
6693
|
-
const read = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
6694
|
-
const key = `${pad(Number(read("year")), 4)}-${read("month")}-${read("day")}`;
|
|
6695
|
-
return civilDate(key) ? key : null;
|
|
6996
|
+
const firstGridCell = (grid) => {
|
|
6997
|
+
for (let column = 0; column < grid.columns; column++) for (let row = 0; row < grid.rows; row++) if (!grid.isInert(column, row)) return {
|
|
6998
|
+
column,
|
|
6999
|
+
row
|
|
6696
7000
|
};
|
|
6697
7001
|
};
|
|
6698
7002
|
/**
|
|
6699
|
-
*
|
|
6700
|
-
*
|
|
6701
|
-
* A `Date`, or a string carrying `Z` or an offset, is an instant read in the host's
|
|
6702
|
-
* zone. Anything else is a wall clock the host wrote, so its date part is the day.
|
|
7003
|
+
* Steps across the grid in the key's direction, past inert slots, staying put at the edge.
|
|
6703
7004
|
*
|
|
6704
|
-
* @param
|
|
6705
|
-
* @param
|
|
6706
|
-
* @
|
|
7005
|
+
* @param grid - The grid.
|
|
7006
|
+
* @param from - The selected cell.
|
|
7007
|
+
* @param key - The arrow key.
|
|
7008
|
+
* @return The next cell, or undefined to keep the selection.
|
|
6707
7009
|
*/
|
|
6708
|
-
const
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
7010
|
+
const stepGridCell = (grid, from, key) => {
|
|
7011
|
+
const step = {
|
|
7012
|
+
ArrowRight: [1, 0],
|
|
7013
|
+
ArrowLeft: [-1, 0],
|
|
7014
|
+
ArrowDown: [0, 1],
|
|
7015
|
+
ArrowUp: [0, -1]
|
|
7016
|
+
}[key];
|
|
7017
|
+
if (!step) return;
|
|
7018
|
+
const [stepColumn, stepRow] = step;
|
|
7019
|
+
let cell = from;
|
|
7020
|
+
do
|
|
7021
|
+
cell = {
|
|
7022
|
+
column: cell.column + stepColumn,
|
|
7023
|
+
row: cell.row + stepRow
|
|
7024
|
+
};
|
|
7025
|
+
while (inGrid(grid, cell) && grid.isInert(cell.column, cell.row));
|
|
7026
|
+
return inGrid(grid, cell) ? cell : void 0;
|
|
7027
|
+
};
|
|
7028
|
+
/**
|
|
7029
|
+
* Every slot of the blocks in reading order: block by block, each a row at a time.
|
|
7030
|
+
*
|
|
7031
|
+
* @param grid - The grid.
|
|
7032
|
+
* @param blocks - The blocks, left to right.
|
|
7033
|
+
* @return The slots in order.
|
|
7034
|
+
*/
|
|
7035
|
+
const readingOrder = (grid, blocks) => blocks.flatMap((block) => Array.from({ length: grid.rows }, (_row, row) => Array.from({ length: block.end - block.start }, (_offset, offset) => ({
|
|
7036
|
+
column: block.start + offset,
|
|
7037
|
+
row
|
|
7038
|
+
}))).flat());
|
|
7039
|
+
const blockOf = (blocks, column) => blocks.findIndex((block) => column >= block.start && column < block.end);
|
|
7040
|
+
/**
|
|
7041
|
+
* The slots after a cell down its column (or before it, going up), continuing at the
|
|
7042
|
+
* same column offset of each following block.
|
|
7043
|
+
*
|
|
7044
|
+
* @param grid - The grid.
|
|
7045
|
+
* @param blocks - The blocks, left to right.
|
|
7046
|
+
* @param from - The selected cell.
|
|
7047
|
+
* @param direction - 1 downwards, -1 upwards.
|
|
7048
|
+
* @return The slots in order.
|
|
7049
|
+
*/
|
|
7050
|
+
const columnOrderFrom = (grid, blocks, from, direction) => {
|
|
7051
|
+
const blockIndex = blockOf(blocks, from.column);
|
|
7052
|
+
if (blockIndex < 0) return [];
|
|
7053
|
+
const offset = from.column - blocks[blockIndex].start;
|
|
7054
|
+
const cells = [];
|
|
7055
|
+
const pushRows = (column, startRow) => {
|
|
7056
|
+
for (let row = startRow; row >= 0 && row < grid.rows; row += direction) cells.push({
|
|
7057
|
+
column,
|
|
7058
|
+
row
|
|
7059
|
+
});
|
|
7060
|
+
};
|
|
7061
|
+
pushRows(from.column, from.row + direction);
|
|
7062
|
+
for (let index = blockIndex + direction; index >= 0 && index < blocks.length; index += direction) {
|
|
7063
|
+
const column = blocks[index].start + offset;
|
|
7064
|
+
if (column < blocks[index].end) pushRows(column, direction === 1 ? 0 : grid.rows - 1);
|
|
6712
7065
|
}
|
|
6713
|
-
|
|
6714
|
-
if (!text) return null;
|
|
6715
|
-
if (!hasTimezone(text)) return writtenDayKey(text);
|
|
6716
|
-
const parsed = parseISO(text);
|
|
6717
|
-
return isNaN(parsed.getTime()) ? null : readInstant(parsed);
|
|
7066
|
+
return cells;
|
|
6718
7067
|
};
|
|
6719
7068
|
/**
|
|
6720
|
-
*
|
|
7069
|
+
* The first selectable cell in calendar reading order.
|
|
6721
7070
|
*
|
|
6722
|
-
* @param
|
|
6723
|
-
* @param
|
|
6724
|
-
* @return The
|
|
7071
|
+
* @param grid - The grid.
|
|
7072
|
+
* @param blocks - The blocks, left to right.
|
|
7073
|
+
* @return The cell, or undefined when every slot is inert.
|
|
6725
7074
|
*/
|
|
6726
|
-
const
|
|
7075
|
+
const firstCalendarCell = (grid, blocks) => firstSelectable(grid, readingOrder(grid, blocks));
|
|
6727
7076
|
/**
|
|
6728
|
-
*
|
|
7077
|
+
* Steps through the blocks as pages of a calendar: Left/Right by one slot in reading
|
|
7078
|
+
* order, Up/Down by one row (into the neighboring block past the edge), Page Up/Down
|
|
7079
|
+
* to the same slot of the neighboring block or its nearest selectable cell.
|
|
6729
7080
|
*
|
|
6730
|
-
* @param
|
|
6731
|
-
* @param
|
|
6732
|
-
* @
|
|
7081
|
+
* @param grid - The grid.
|
|
7082
|
+
* @param blocks - The blocks, left to right.
|
|
7083
|
+
* @param from - The selected cell.
|
|
7084
|
+
* @param key - The navigation key.
|
|
7085
|
+
* @return The next cell, or undefined to keep the selection.
|
|
6733
7086
|
*/
|
|
6734
|
-
const
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
const
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
const
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
/**
|
|
6756
|
-
* Resolve one grid bound: an unparseable or narrowing value falls back to the
|
|
6757
|
-
* series' own bound, so the grid can only ever be widened.
|
|
6758
|
-
*
|
|
6759
|
-
* @param bound - Requested bound as `yyyy-MM-dd`, if any.
|
|
6760
|
-
* @param fallback - The series' own bound on this side.
|
|
6761
|
-
* @param direction - Which way the bound is allowed to move.
|
|
6762
|
-
* @return The day key to draw to.
|
|
6763
|
-
*/
|
|
6764
|
-
const widenTo = (bound, fallback, direction) => {
|
|
6765
|
-
const key = bound ? writtenDayKey(bound) : null;
|
|
6766
|
-
if (!key) {
|
|
6767
|
-
if (bound) warnOnce(`heatmap:gridSpan:${bound}`, `gridSpan.${direction === "earlier" ? "start" : "end"} ${JSON.stringify(bound)} is not a \`yyyy-MM-dd\` day, so the grid is drawn over the series' own span.`);
|
|
6768
|
-
return fallback;
|
|
6769
|
-
}
|
|
6770
|
-
if (direction === "earlier") return key < fallback ? key : fallback;
|
|
6771
|
-
return key > fallback ? key : fallback;
|
|
6772
|
-
};
|
|
6773
|
-
/**
|
|
6774
|
-
* Lay a day-bucketed series out as calendar columns.
|
|
6775
|
-
*
|
|
6776
|
-
* @param series - Points to bucket.
|
|
6777
|
-
* @param options - Grid shape, plus the locale and zone to read days in.
|
|
6778
|
-
* @return Columns and row labels for `HeatmapChart`.
|
|
6779
|
-
*/
|
|
6780
|
-
const buildCalendarHeatmapData = (series, options = {}) => {
|
|
6781
|
-
const weekStartsOn = options.weekStartsOn ?? 1;
|
|
6782
|
-
const hideOutOfRangeDays = options.hideOutOfRangeDays ?? true;
|
|
6783
|
-
const { locale, timeZone } = sanitizeFormatting({
|
|
6784
|
-
locale: options.locale,
|
|
6785
|
-
timeZone: options.timeZone
|
|
6786
|
-
});
|
|
6787
|
-
const readInstant = instantDayReader(timeZone);
|
|
6788
|
-
const valueByDay = /* @__PURE__ */ new Map();
|
|
6789
|
-
let minDayKey;
|
|
6790
|
-
let maxDayKey;
|
|
6791
|
-
for (const point of series) {
|
|
6792
|
-
const key = pointDayKey(point, readInstant);
|
|
6793
|
-
if (!key) {
|
|
6794
|
-
const offending = point.dateString ?? (point.date && String(point.date));
|
|
6795
|
-
warnOnce(`heatmap:unreadableDate:${offending}`, offending ? `${JSON.stringify(offending)} is not a day this can read, so its point is left out of the calendar. A \`dateString\` must start \`yyyy-MM-dd\`.` : "A point carries neither `date` nor `dateString`, so it is left out of the calendar.");
|
|
6796
|
-
continue;
|
|
6797
|
-
}
|
|
6798
|
-
valueByDay.set(key, point.value);
|
|
6799
|
-
if (!minDayKey || key < minDayKey) minDayKey = key;
|
|
6800
|
-
if (!maxDayKey || key > maxDayKey) maxDayKey = key;
|
|
6801
|
-
}
|
|
6802
|
-
if (!minDayKey || !maxDayKey) return {
|
|
6803
|
-
data: [],
|
|
6804
|
-
rowLabels: []
|
|
6805
|
-
};
|
|
6806
|
-
const requestedMinDayKey = widenTo(options.gridSpan?.start, minDayKey, "earlier");
|
|
6807
|
-
const gridMaxDayKey = widenTo(options.gridSpan?.end, maxDayKey, "later");
|
|
6808
|
-
const requestedMinDate = civilDate(requestedMinDayKey);
|
|
6809
|
-
const gridMaxDate = civilDate(gridMaxDayKey);
|
|
6810
|
-
const labelFormatting = {
|
|
6811
|
-
locale,
|
|
6812
|
-
timeZone: "UTC"
|
|
6813
|
-
};
|
|
6814
|
-
const formatWeekday = createDateFormatter({ weekday: "short" }, labelFormatting);
|
|
6815
|
-
const formatMonth = createDateFormatter({ month: "short" }, labelFormatting);
|
|
6816
|
-
const formatDay = createDateFormatter({
|
|
6817
|
-
weekday: "short",
|
|
6818
|
-
month: "short",
|
|
6819
|
-
day: "numeric",
|
|
6820
|
-
year: "numeric"
|
|
6821
|
-
}, labelFormatting);
|
|
6822
|
-
const gridStart = startOfCivilWeek(requestedMinDate, weekStartsOn);
|
|
6823
|
-
const gridMinDayKey = requestedMinDayKey < minDayKey ? civilKey(gridStart) : requestedMinDayKey;
|
|
6824
|
-
const weekCount = civilWeekSpan(gridStart, gridMaxDate, weekStartsOn);
|
|
6825
|
-
const rowLabels = Array.from({ length: 7 }, (_, row) => LABELLED_ROWS.includes(row) ? formatWeekday(addCivilDays(gridStart, row)) : "");
|
|
6826
|
-
const MIN_FIRST_MONTH_WEEKS = 2;
|
|
6827
|
-
const firstMonth = gridStart.getUTCMonth();
|
|
6828
|
-
let firstMonthWeeks = 0;
|
|
6829
|
-
while (firstMonthWeeks < weekCount && addCivilDays(gridStart, firstMonthWeeks * 7).getUTCMonth() === firstMonth) firstMonthWeeks++;
|
|
6830
|
-
const showFirstMonthLabel = !(firstMonthWeeks < weekCount) || firstMonthWeeks >= MIN_FIRST_MONTH_WEEKS;
|
|
6831
|
-
const data = [];
|
|
6832
|
-
let previousMonth = -1;
|
|
6833
|
-
for (let week = 0; week < weekCount; week++) {
|
|
6834
|
-
const columnStart = addCivilDays(gridStart, week * 7);
|
|
6835
|
-
const month = columnStart.getUTCMonth();
|
|
6836
|
-
const label = month !== previousMonth && (week !== 0 || showFirstMonthLabel) ? formatMonth(columnStart) : "";
|
|
6837
|
-
previousMonth = month;
|
|
6838
|
-
const cells = [];
|
|
6839
|
-
for (let row = 0; row < 7; row++) {
|
|
6840
|
-
const day = addCivilDays(gridStart, week * 7 + row);
|
|
6841
|
-
const key = civilKey(day);
|
|
6842
|
-
const cell = {
|
|
6843
|
-
label: formatDay(day),
|
|
6844
|
-
value: valueByDay.has(key) ? valueByDay.get(key) : null
|
|
6845
|
-
};
|
|
6846
|
-
if (key < gridMinDayKey || key > gridMaxDayKey) {
|
|
6847
|
-
if (hideOutOfRangeDays) cell.hidden = true;
|
|
6848
|
-
} else if (key < minDayKey || key > maxDayKey) cell.placeholder = true;
|
|
6849
|
-
cells.push(cell);
|
|
6850
|
-
}
|
|
6851
|
-
data.push({
|
|
6852
|
-
label,
|
|
6853
|
-
data: cells
|
|
6854
|
-
});
|
|
6855
|
-
}
|
|
6856
|
-
return {
|
|
6857
|
-
data,
|
|
6858
|
-
rowLabels
|
|
6859
|
-
};
|
|
6860
|
-
};
|
|
6861
|
-
//#endregion
|
|
6862
|
-
//#region src/charts/heatmap-chart/private/heatmap-context.ts
|
|
6863
|
-
/** Shared by the chart and legend without importing back from `heatmap-chart.tsx`. */
|
|
6864
|
-
const HeatmapContext = createContext(null);
|
|
6865
|
-
//#endregion
|
|
6866
|
-
//#region src/charts/heatmap-chart/private/heatmap-legend.tsx
|
|
6867
|
-
const HeatmapLegend = ({ steps = 5, lessLabel, moreLabel }) => {
|
|
6868
|
-
const context = useContext(HeatmapContext);
|
|
6869
|
-
const { legend } = useGlobalChartsTheme();
|
|
6870
|
-
if (!context) return null;
|
|
6871
|
-
const { primaryColorHex } = context;
|
|
6872
|
-
const labelStyle = legend.labelStyles;
|
|
6873
|
-
return /* @__PURE__ */ jsxs(Stack, {
|
|
6874
|
-
direction: "row",
|
|
6875
|
-
gap: "xs",
|
|
6876
|
-
align: "center",
|
|
6877
|
-
children: [
|
|
6878
|
-
/* @__PURE__ */ jsx(Text$1, {
|
|
6879
|
-
variant: "body-sm",
|
|
6880
|
-
className: heatmap_chart_module_default["heatmap-chart__legend-label"],
|
|
6881
|
-
style: labelStyle,
|
|
6882
|
-
children: lessLabel ?? __("Less", "jetpack-charts")
|
|
6883
|
-
}),
|
|
6884
|
-
/* @__PURE__ */ jsx(Stack, {
|
|
6885
|
-
direction: "row",
|
|
6886
|
-
gap: "xs",
|
|
6887
|
-
children: Array.from({ length: steps }, (_, index) => {
|
|
6888
|
-
const intensity = steps <= 1 ? 1 : index / (steps - 1);
|
|
6889
|
-
return /* @__PURE__ */ jsx("span", {
|
|
6890
|
-
"aria-hidden": "true",
|
|
6891
|
-
className: heatmap_chart_module_default["heatmap-chart__legend-swatch"],
|
|
6892
|
-
style: {
|
|
6893
|
-
"--a8c-charts-color-heatmap-primary": primaryColorHex,
|
|
6894
|
-
"--a8c-charts-heatmap-cell-intensity": intensity
|
|
6895
|
-
}
|
|
6896
|
-
}, index);
|
|
6897
|
-
})
|
|
6898
|
-
}),
|
|
6899
|
-
/* @__PURE__ */ jsx(Text$1, {
|
|
6900
|
-
variant: "body-sm",
|
|
6901
|
-
className: heatmap_chart_module_default["heatmap-chart__legend-label"],
|
|
6902
|
-
style: labelStyle,
|
|
6903
|
-
children: moreLabel ?? __("More", "jetpack-charts")
|
|
6904
|
-
})
|
|
6905
|
-
]
|
|
6906
|
-
});
|
|
7087
|
+
const stepCalendarCell = (grid, blocks, from, key) => {
|
|
7088
|
+
if (key === "ArrowRight" || key === "ArrowLeft") {
|
|
7089
|
+
const order = readingOrder(grid, blocks);
|
|
7090
|
+
const index = order.findIndex((cell) => cell.column === from.column && cell.row === from.row);
|
|
7091
|
+
if (index < 0) return;
|
|
7092
|
+
const ahead = key === "ArrowRight" ? order.slice(index + 1) : order.slice(0, index).reverse();
|
|
7093
|
+
return firstSelectable(grid, ahead);
|
|
7094
|
+
}
|
|
7095
|
+
if (key === "ArrowDown" || key === "ArrowUp") return firstSelectable(grid, columnOrderFrom(grid, blocks, from, key === "ArrowDown" ? 1 : -1));
|
|
7096
|
+
const blockIndex = blockOf(blocks, from.column);
|
|
7097
|
+
const target = blocks[blockIndex + (key === "PageDown" ? 1 : -1)];
|
|
7098
|
+
if (blockIndex < 0 || !target) return;
|
|
7099
|
+
const same = {
|
|
7100
|
+
column: target.start + (from.column - blocks[blockIndex].start),
|
|
7101
|
+
row: from.row
|
|
7102
|
+
};
|
|
7103
|
+
const page = readingOrder(grid, [target]);
|
|
7104
|
+
const at = page.findIndex((cell) => cell.row > same.row || cell.row === same.row && cell.column >= same.column);
|
|
7105
|
+
const after = at === -1 ? [] : page.slice(at);
|
|
7106
|
+
const before = page.slice(0, at === -1 ? page.length : at).reverse();
|
|
7107
|
+
return firstSelectable(grid, after) ?? firstSelectable(grid, before);
|
|
6907
7108
|
};
|
|
6908
7109
|
//#endregion
|
|
6909
7110
|
//#region src/charts/heatmap-chart/heatmap-chart.tsx
|
|
6910
7111
|
const CELL_MIX_FLOOR = .15;
|
|
6911
7112
|
const NO_ROW_LABELS = [];
|
|
6912
|
-
const
|
|
7113
|
+
const TOOLTIP_BOX_STYLES = {
|
|
7114
|
+
light: {
|
|
7115
|
+
...defaultStyles,
|
|
7116
|
+
zIndex: 3
|
|
7117
|
+
},
|
|
7118
|
+
dark: { zIndex: 3 }
|
|
7119
|
+
};
|
|
7120
|
+
const cellName = (info) => info.cellLabel || [
|
|
7121
|
+
info.groupLabel,
|
|
7122
|
+
info.columnLabel,
|
|
7123
|
+
info.rowLabel
|
|
7124
|
+
].filter(Boolean).join(" ");
|
|
7125
|
+
const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, height = 0, className, compact = false, showValues, maxCellWidth, maxCellHeight, minCellWidth, minCellHeight, rowLabels = NO_ROW_LABELS, columnGroups, keyboardNavigation = "grid", ariaLabel, primaryColor, gap = "md", withTooltips = false, renderTooltip, tooltipVariant = "light", tooltipStyle, children }) => {
|
|
6913
7126
|
const chartId = useChartId(providedChartId);
|
|
7127
|
+
const tooltipBoxStyle = tooltipStyle ? {
|
|
7128
|
+
...TOOLTIP_BOX_STYLES[tooltipVariant],
|
|
7129
|
+
...tooltipStyle
|
|
7130
|
+
} : TOOLTIP_BOX_STYLES[tooltipVariant];
|
|
6914
7131
|
const { getElementStyles, theme } = useGlobalChartsContext();
|
|
6915
7132
|
const scopeElement = useChartScopeElement();
|
|
6916
7133
|
const { heatmapChart: heatmapChartSettings } = theme;
|
|
6917
7134
|
const { nonLegendChildren } = useChartChildren(children, "HeatmapChart");
|
|
6918
|
-
const [
|
|
7135
|
+
const [selected, setSelected] = useState();
|
|
6919
7136
|
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, showTooltip, hideTooltip } = useTooltip();
|
|
6920
7137
|
const standaloneScopeClass = useStandaloneScopeClass();
|
|
6921
7138
|
const containerRef = useRef(null);
|
|
@@ -6934,69 +7151,75 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
6934
7151
|
}), [extent, primaryColorHex]);
|
|
6935
7152
|
const columns = data.length;
|
|
6936
7153
|
const rows = Math.max(0, ...data.map((column) => column.data.length));
|
|
6937
|
-
const
|
|
7154
|
+
const groupLayout = useMemo(() => resolveColumnGroups(columnGroups, columns, 2), [columnGroups, columns]);
|
|
7155
|
+
const { compactCellGap, compactCellSize, groupGap } = heatmapChartSettings;
|
|
6938
7156
|
const drawValues = showValues ?? !compact;
|
|
6939
7157
|
const buildTooltipData = useCallback((columnIndex, rowIndex) => {
|
|
6940
7158
|
const cell = data[columnIndex]?.data[rowIndex];
|
|
7159
|
+
const group = groupLayout.columns[columnIndex]?.group;
|
|
6941
7160
|
return {
|
|
6942
7161
|
value: cell?.value ?? null,
|
|
6943
7162
|
rowLabel: rowLabels[rowIndex],
|
|
6944
7163
|
columnLabel: data[columnIndex]?.label,
|
|
7164
|
+
groupLabel: group === void 0 ? void 0 : groupLayout.groups[group]?.label,
|
|
6945
7165
|
cellLabel: cell?.label,
|
|
6946
7166
|
row: rowIndex,
|
|
6947
7167
|
column: columnIndex
|
|
6948
7168
|
};
|
|
6949
|
-
}, [
|
|
7169
|
+
}, [
|
|
7170
|
+
data,
|
|
7171
|
+
rowLabels,
|
|
7172
|
+
groupLayout
|
|
7173
|
+
]);
|
|
6950
7174
|
const onChartBlur = useCallback(() => {
|
|
6951
|
-
|
|
7175
|
+
setSelected(void 0);
|
|
6952
7176
|
hideTooltip();
|
|
6953
7177
|
}, [hideTooltip]);
|
|
6954
7178
|
const isCellInert = useCallback((col, row) => {
|
|
6955
7179
|
const cell = data[col]?.data[row];
|
|
6956
7180
|
return cell?.hidden === true || cell?.placeholder === true;
|
|
6957
7181
|
}, [data]);
|
|
7182
|
+
const blocks = useMemo(() => {
|
|
7183
|
+
const grouped = groupLayout.groups.map((group, index) => {
|
|
7184
|
+
const start = groupLayout.columns.findIndex((column) => column.group === index);
|
|
7185
|
+
return {
|
|
7186
|
+
start,
|
|
7187
|
+
end: start + group.span
|
|
7188
|
+
};
|
|
7189
|
+
});
|
|
7190
|
+
const groupedEnd = grouped.length ? grouped[grouped.length - 1].end : 0;
|
|
7191
|
+
return groupedEnd < columns ? [...grouped, {
|
|
7192
|
+
start: groupedEnd,
|
|
7193
|
+
end: columns
|
|
7194
|
+
}] : grouped;
|
|
7195
|
+
}, [groupLayout, columns]);
|
|
6958
7196
|
const onChartKeyDown = useCallback((event) => {
|
|
6959
|
-
if (![
|
|
6960
|
-
"ArrowLeft",
|
|
6961
|
-
"ArrowRight",
|
|
6962
|
-
"ArrowUp",
|
|
6963
|
-
"ArrowDown",
|
|
6964
|
-
"Escape",
|
|
6965
|
-
"Tab"
|
|
6966
|
-
].includes(event.key)) return;
|
|
6967
7197
|
if (event.key === "Tab" || event.key === "Escape") {
|
|
6968
|
-
|
|
7198
|
+
setSelected(void 0);
|
|
6969
7199
|
hideTooltip();
|
|
6970
7200
|
return;
|
|
6971
7201
|
}
|
|
7202
|
+
if (!isNavigationKey(event.key, keyboardNavigation)) return;
|
|
6972
7203
|
event.preventDefault();
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
7204
|
+
const grid = {
|
|
7205
|
+
columns,
|
|
7206
|
+
rows,
|
|
7207
|
+
isInert: isCellInert
|
|
7208
|
+
};
|
|
7209
|
+
if (selected === void 0) {
|
|
7210
|
+
setSelected(keyboardNavigation === "calendar" ? firstCalendarCell(grid, blocks) : firstGridCell(grid));
|
|
6978
7211
|
return;
|
|
6979
7212
|
}
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
if (event.key === "ArrowRight") stepCol = 1;
|
|
6983
|
-
else if (event.key === "ArrowLeft") stepCol = -1;
|
|
6984
|
-
else if (event.key === "ArrowDown") stepRow = 1;
|
|
6985
|
-
else if (event.key === "ArrowUp") stepRow = -1;
|
|
6986
|
-
let col = Math.floor(selectedIndex / rows);
|
|
6987
|
-
let row = selectedIndex % rows;
|
|
6988
|
-
do {
|
|
6989
|
-
col += stepCol;
|
|
6990
|
-
row += stepRow;
|
|
6991
|
-
} while (col >= 0 && col < columns && row >= 0 && row < rows && isCellInert(col, row));
|
|
6992
|
-
if (col < 0 || col >= columns || row < 0 || row >= rows) return;
|
|
6993
|
-
setSelectedIndex(col * rows + row);
|
|
7213
|
+
const next = keyboardNavigation === "calendar" ? stepCalendarCell(grid, blocks, selected, event.key) : stepGridCell(grid, selected, event.key);
|
|
7214
|
+
if (next) setSelected(next);
|
|
6994
7215
|
}, [
|
|
6995
7216
|
rows,
|
|
6996
7217
|
columns,
|
|
6997
|
-
|
|
7218
|
+
selected,
|
|
6998
7219
|
hideTooltip,
|
|
6999
|
-
isCellInert
|
|
7220
|
+
isCellInert,
|
|
7221
|
+
keyboardNavigation,
|
|
7222
|
+
blocks
|
|
7000
7223
|
]);
|
|
7001
7224
|
const handleCellMouseMove = useCallback((event) => {
|
|
7002
7225
|
if (!withTooltips) return;
|
|
@@ -7016,35 +7239,47 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7016
7239
|
buildTooltipData,
|
|
7017
7240
|
getTooltipOrigin
|
|
7018
7241
|
]);
|
|
7242
|
+
const getCellElement = useCallback((col, row) => typeof document !== "undefined" ? document.getElementById(`${chartId}-cell-${col}-${row}`) : null, [chartId]);
|
|
7019
7243
|
const handleCellMouseLeave = useCallback(() => {
|
|
7020
|
-
if (withTooltips &&
|
|
7244
|
+
if (withTooltips && selected === void 0) hideTooltip();
|
|
7021
7245
|
}, [
|
|
7022
7246
|
withTooltips,
|
|
7023
|
-
|
|
7247
|
+
selected,
|
|
7024
7248
|
hideTooltip
|
|
7025
7249
|
]);
|
|
7026
7250
|
useEffect(() => {
|
|
7027
|
-
if (
|
|
7251
|
+
if (selected && (selected.column >= columns || selected.row >= rows)) setSelected(void 0);
|
|
7252
|
+
}, [
|
|
7253
|
+
selected,
|
|
7254
|
+
columns,
|
|
7255
|
+
rows
|
|
7256
|
+
]);
|
|
7257
|
+
useEffect(() => {
|
|
7258
|
+
if (selected === void 0) return;
|
|
7259
|
+
getCellElement(selected.column, selected.row)?.scrollIntoView?.({
|
|
7260
|
+
block: "nearest",
|
|
7261
|
+
inline: "nearest"
|
|
7262
|
+
});
|
|
7263
|
+
}, [selected, getCellElement]);
|
|
7264
|
+
useEffect(() => {
|
|
7265
|
+
if (!withTooltips || selected === void 0) return;
|
|
7028
7266
|
const origin = getTooltipOrigin();
|
|
7029
7267
|
if (!origin) return;
|
|
7030
|
-
const
|
|
7031
|
-
const row = selectedIndex % rows;
|
|
7032
|
-
const rect = (typeof document !== "undefined" ? document.getElementById(`${chartId}-cell-${col}-${row}`) : null)?.getBoundingClientRect();
|
|
7268
|
+
const rect = getCellElement(selected.column, selected.row)?.getBoundingClientRect();
|
|
7033
7269
|
showTooltip({
|
|
7034
7270
|
tooltipLeft: rect ? rect.left + rect.width / 2 - origin.left : 0,
|
|
7035
7271
|
tooltipTop: rect ? rect.top + rect.height / 2 - origin.top : 0,
|
|
7036
|
-
tooltipData: buildTooltipData(
|
|
7272
|
+
tooltipData: buildTooltipData(selected.column, selected.row)
|
|
7037
7273
|
});
|
|
7038
7274
|
}, [
|
|
7039
|
-
|
|
7275
|
+
selected,
|
|
7040
7276
|
withTooltips,
|
|
7041
|
-
|
|
7042
|
-
chartId,
|
|
7277
|
+
getCellElement,
|
|
7043
7278
|
buildTooltipData,
|
|
7044
7279
|
showTooltip,
|
|
7045
7280
|
getTooltipOrigin
|
|
7046
7281
|
]);
|
|
7047
|
-
const defaultRenderTooltip = useCallback((info) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("strong", { children: info
|
|
7282
|
+
const defaultRenderTooltip = useCallback((info) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("strong", { children: cellName(info) }), /* @__PURE__ */ jsx("div", { children: info.value === null ? __("No data", "jetpack-charts") : formatNumber(info.value) })] }), []);
|
|
7048
7283
|
if (!columns || !rows) return /* @__PURE__ */ jsx(Center, {
|
|
7049
7284
|
className: clsx("heatmap-chart", heatmap_chart_module_default["heatmap-chart"], className),
|
|
7050
7285
|
style: {
|
|
@@ -7058,10 +7293,16 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7058
7293
|
});
|
|
7059
7294
|
const columnTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellWidth ?? 0}px, ${maxCellWidth ? `${maxCellWidth}px` : "1fr"})`;
|
|
7060
7295
|
const rowTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellHeight ?? 0}px, ${maxCellHeight ? `${maxCellHeight}px` : "1fr"})`;
|
|
7296
|
+
const hasColumnLabels = data.some((column) => Boolean(column.label));
|
|
7297
|
+
const hasGroups = groupLayout.groups.length > 0;
|
|
7298
|
+
const columnLine = (columnIndex) => groupLayout.columns[columnIndex].line;
|
|
7299
|
+
const firstDataRow = hasColumnLabels ? 2 : 1;
|
|
7300
|
+
const dataTrack = (column) => column.summary ? "minmax(auto, max-content)" : columnTrack;
|
|
7301
|
+
const gapTrack = compact ? `minmax(${groupGap}px, 1fr)` : `${groupGap}px`;
|
|
7061
7302
|
const gridStyle = {
|
|
7062
7303
|
"--a8c-charts-color-heatmap-primary": primaryColorHex,
|
|
7063
|
-
gridTemplateColumns: `auto ${data.
|
|
7064
|
-
gridTemplateRows:
|
|
7304
|
+
gridTemplateColumns: `auto ${data.map((column, columnIndex) => groupLayout.columns[columnIndex].gapBefore ? `${gapTrack} ${dataTrack(column)}` : dataTrack(column)).join(" ")}`,
|
|
7305
|
+
gridTemplateRows: `${hasColumnLabels ? "auto " : ""}repeat(${rows}, ${rowTrack})${hasGroups ? " auto" : ""}`
|
|
7065
7306
|
};
|
|
7066
7307
|
if (compact) {
|
|
7067
7308
|
gridStyle["--a8c-charts-dimension-heatmap-cell-gap"] = `${compactCellGap}px`;
|
|
@@ -7074,7 +7315,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7074
7315
|
[heatmap_chart_module_default["heatmap-chart__gap-end"]]: columnIndex < columns - 1 && !data[columnIndex + 1]?.summary
|
|
7075
7316
|
};
|
|
7076
7317
|
};
|
|
7077
|
-
const activeDescendant =
|
|
7318
|
+
const activeDescendant = selected ? `${chartId}-cell-${selected.column}-${selected.row}` : void 0;
|
|
7078
7319
|
const heightCapped = !compact && Boolean(maxCellHeight);
|
|
7079
7320
|
return /* @__PURE__ */ jsx(HeatmapContext.Provider, {
|
|
7080
7321
|
value: heatmapContext,
|
|
@@ -7094,7 +7335,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7094
7335
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
7095
7336
|
ref: containerRef,
|
|
7096
7337
|
role: "grid",
|
|
7097
|
-
"aria-label": __("Heatmap chart", "jetpack-charts"),
|
|
7338
|
+
"aria-label": ariaLabel ?? __("Heatmap chart", "jetpack-charts"),
|
|
7098
7339
|
"aria-rowcount": rows,
|
|
7099
7340
|
"aria-colcount": columns,
|
|
7100
7341
|
"aria-activedescendant": activeDescendant,
|
|
@@ -7103,76 +7344,115 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7103
7344
|
onKeyDown: onChartKeyDown,
|
|
7104
7345
|
className: clsx(heatmap_chart_module_default["heatmap-chart__grid"], {
|
|
7105
7346
|
[heatmap_chart_module_default["heatmap-chart__grid--compact"]]: compact,
|
|
7347
|
+
[heatmap_chart_module_default["heatmap-chart__grid--flex-gaps"]]: compact && hasGroups,
|
|
7106
7348
|
[heatmap_chart_module_default["heatmap-chart__grid--height-capped"]]: heightCapped
|
|
7107
7349
|
}),
|
|
7108
7350
|
style: gridStyle,
|
|
7109
|
-
children: [
|
|
7110
|
-
|
|
7111
|
-
"aria-hidden": "true",
|
|
7112
|
-
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
7113
|
-
children: [/* @__PURE__ */ jsx("span", {}), data.map((column, columnIndex) => /* @__PURE__ */ jsx("span", {
|
|
7114
|
-
className: clsx(heatmap_chart_module_default["heatmap-chart__col-label"], {
|
|
7115
|
-
[heatmap_chart_module_default["heatmap-chart__col-label--summary"]]: column.summary,
|
|
7116
|
-
...summaryGaps(columnIndex)
|
|
7117
|
-
}),
|
|
7118
|
-
children: column.label
|
|
7119
|
-
}, `col-${columnIndex}`))]
|
|
7120
|
-
}), Array.from({ length: rows }).map((_row, rowIndex) => {
|
|
7121
|
-
const labelVisible = !compact || rowIndex % 2 === 0;
|
|
7122
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
7351
|
+
children: [
|
|
7352
|
+
hasColumnLabels && /* @__PURE__ */ jsxs("div", {
|
|
7123
7353
|
role: "row",
|
|
7124
|
-
"aria-
|
|
7354
|
+
"aria-hidden": "true",
|
|
7125
7355
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
7126
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7356
|
+
children: [/* @__PURE__ */ jsx("span", { style: {
|
|
7357
|
+
gridColumn: 1,
|
|
7358
|
+
gridRow: 1
|
|
7359
|
+
} }), data.map((column, columnIndex) => /* @__PURE__ */ jsx("span", {
|
|
7360
|
+
style: {
|
|
7361
|
+
gridColumn: columnLine(columnIndex),
|
|
7362
|
+
gridRow: 1
|
|
7363
|
+
},
|
|
7364
|
+
className: clsx(heatmap_chart_module_default["heatmap-chart__col-label"], {
|
|
7365
|
+
[heatmap_chart_module_default["heatmap-chart__col-label--summary"]]: column.summary,
|
|
7366
|
+
...summaryGaps(columnIndex)
|
|
7367
|
+
}),
|
|
7368
|
+
children: column.label
|
|
7369
|
+
}, `col-${columnIndex}`))]
|
|
7370
|
+
}),
|
|
7371
|
+
Array.from({ length: rows }).map((_row, rowIndex) => {
|
|
7372
|
+
const labelVisible = !compact || rowIndex % 2 === 0;
|
|
7373
|
+
const gridRow = firstDataRow + rowIndex;
|
|
7374
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7375
|
+
role: "row",
|
|
7376
|
+
"aria-rowindex": rowIndex + 1,
|
|
7377
|
+
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
7378
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
7137
7379
|
"aria-hidden": "true",
|
|
7138
|
-
className:
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
[heatmap_chart_module_default["heatmap-chart__cell--
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7380
|
+
className: heatmap_chart_module_default["heatmap-chart__row-label"],
|
|
7381
|
+
style: {
|
|
7382
|
+
gridColumn: 1,
|
|
7383
|
+
gridRow
|
|
7384
|
+
},
|
|
7385
|
+
children: labelVisible ? rowLabels[rowIndex] ?? "" : ""
|
|
7386
|
+
}), data.map((column, columnIndex) => {
|
|
7387
|
+
const cell = column.data[rowIndex];
|
|
7388
|
+
const placement = {
|
|
7389
|
+
gridColumn: columnLine(columnIndex),
|
|
7390
|
+
gridRow
|
|
7391
|
+
};
|
|
7392
|
+
if (cell?.hidden) return /* @__PURE__ */ jsx("div", {
|
|
7393
|
+
"aria-hidden": "true",
|
|
7394
|
+
style: placement,
|
|
7395
|
+
className: clsx(heatmap_chart_module_default["heatmap-chart__cell"], heatmap_chart_module_default["heatmap-chart__cell--hidden"])
|
|
7396
|
+
}, `cell-${columnIndex}-${rowIndex}`);
|
|
7397
|
+
if (cell?.placeholder) return /* @__PURE__ */ jsx("div", {
|
|
7398
|
+
"aria-hidden": "true",
|
|
7399
|
+
style: placement,
|
|
7400
|
+
className: clsx(heatmap_chart_module_default["heatmap-chart__cell"], heatmap_chart_module_default["heatmap-chart__cell--placeholder"])
|
|
7401
|
+
}, `cell-${columnIndex}-${rowIndex}`);
|
|
7402
|
+
const value = cell?.value ?? null;
|
|
7403
|
+
const present = isPresent(value);
|
|
7404
|
+
const filled = present && !column.summary;
|
|
7405
|
+
const normalized = filled ? getNormalizedValue(value, extent) : 0;
|
|
7406
|
+
const info = buildTooltipData(columnIndex, rowIndex);
|
|
7407
|
+
const accessibleLabel = `${cellName(info)}: ${info.value === null ? __("No data", "jetpack-charts") : formatNumber(info.value)}`;
|
|
7408
|
+
return /* @__PURE__ */ jsx("div", {
|
|
7409
|
+
id: `${chartId}-cell-${columnIndex}-${rowIndex}`,
|
|
7410
|
+
role: "gridcell",
|
|
7411
|
+
tabIndex: -1,
|
|
7412
|
+
"aria-colindex": columnIndex + 1,
|
|
7413
|
+
"aria-label": accessibleLabel,
|
|
7414
|
+
"data-column": columnIndex,
|
|
7415
|
+
"data-row": rowIndex,
|
|
7416
|
+
className: clsx(heatmap_chart_module_default["heatmap-chart__cell"], {
|
|
7417
|
+
[heatmap_chart_module_default["heatmap-chart__cell--filled"]]: filled,
|
|
7418
|
+
[heatmap_chart_module_default["heatmap-chart__cell--strong"]]: filled && cellHasLightText(normalized),
|
|
7419
|
+
[heatmap_chart_module_default["heatmap-chart__cell--summary"]]: column.summary,
|
|
7420
|
+
...summaryGaps(columnIndex),
|
|
7421
|
+
[heatmap_chart_module_default["heatmap-chart__cell--selected"]]: selected?.column === columnIndex && selected?.row === rowIndex
|
|
7422
|
+
}),
|
|
7423
|
+
style: {
|
|
7424
|
+
...placement,
|
|
7425
|
+
...filled ? { "--a8c-charts-heatmap-cell-intensity": normalized } : {}
|
|
7426
|
+
},
|
|
7427
|
+
onMouseMove: handleCellMouseMove,
|
|
7428
|
+
onMouseLeave: handleCellMouseLeave,
|
|
7429
|
+
children: (drawValues || column.summary) && present && /* @__PURE__ */ jsx("span", {
|
|
7430
|
+
className: heatmap_chart_module_default["heatmap-chart__cell-value"],
|
|
7431
|
+
children: formatNumberCompact(value)
|
|
7432
|
+
})
|
|
7433
|
+
}, `cell-${columnIndex}-${rowIndex}`);
|
|
7434
|
+
})]
|
|
7435
|
+
}, `row-${rowIndex}`);
|
|
7436
|
+
}),
|
|
7437
|
+
hasGroups && /* @__PURE__ */ jsx("div", {
|
|
7438
|
+
role: "row",
|
|
7439
|
+
"aria-hidden": "true",
|
|
7440
|
+
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
7441
|
+
children: groupLayout.groups.map((group, groupIndex) => /* @__PURE__ */ jsx("span", {
|
|
7442
|
+
className: heatmap_chart_module_default["heatmap-chart__group-label"],
|
|
7443
|
+
style: {
|
|
7444
|
+
gridColumn: `${group.line} / span ${group.span}`,
|
|
7445
|
+
gridRow: firstDataRow + rows
|
|
7446
|
+
},
|
|
7447
|
+
children: group.label
|
|
7448
|
+
}, `group-${groupIndex}`))
|
|
7449
|
+
})
|
|
7450
|
+
]
|
|
7173
7451
|
}), withTooltips && tooltipOpen && tooltipData && /* @__PURE__ */ jsx(BoundedTooltip, {
|
|
7174
7452
|
top: tooltipTop,
|
|
7175
7453
|
left: tooltipLeft,
|
|
7454
|
+
className: tooltipVariant === "dark" ? base_tooltip_module_default.surface : void 0,
|
|
7455
|
+
style: tooltipBoxStyle,
|
|
7176
7456
|
children: /* @__PURE__ */ jsx("div", {
|
|
7177
7457
|
className: standaloneScopeClass,
|
|
7178
7458
|
role: "tooltip",
|
|
@@ -7198,6 +7478,342 @@ const HeatmapChartResponsiveInner = (props) => /* @__PURE__ */ jsx(HeatmapChartW
|
|
|
7198
7478
|
HeatmapChartResponsiveInner.displayName = "HeatmapChart";
|
|
7199
7479
|
const HeatmapChartResponsive = attachSubComponents(withResponsive(HeatmapChartResponsiveInner), { Legend: HeatmapLegend });
|
|
7200
7480
|
//#endregion
|
|
7481
|
+
//#region src/charts/heatmap-chart/private/civil-day.ts
|
|
7482
|
+
const DAY_MS = 864e5;
|
|
7483
|
+
const KEY_OPTIONS = {
|
|
7484
|
+
calendar: "gregory",
|
|
7485
|
+
numberingSystem: "latn",
|
|
7486
|
+
year: "numeric",
|
|
7487
|
+
month: "2-digit",
|
|
7488
|
+
day: "2-digit"
|
|
7489
|
+
};
|
|
7490
|
+
const DATE_PREFIX = /^(\d{4})-(\d{2})-(\d{2})/;
|
|
7491
|
+
/**
|
|
7492
|
+
* Label formatters for UTC proxies, so both calendar layouts name a day alike.
|
|
7493
|
+
*
|
|
7494
|
+
* `gregory` keeps a locale whose default calendar is not Gregorian (fa-IR) from
|
|
7495
|
+
* splitting one grid month across two names.
|
|
7496
|
+
*
|
|
7497
|
+
* @param locale - BCP 47 locale.
|
|
7498
|
+
* @return Weekday, month and full-day formatters.
|
|
7499
|
+
*/
|
|
7500
|
+
const civilLabelFormatters = (locale) => {
|
|
7501
|
+
const formatting = {
|
|
7502
|
+
locale,
|
|
7503
|
+
timeZone: "UTC"
|
|
7504
|
+
};
|
|
7505
|
+
return {
|
|
7506
|
+
formatWeekday: createDateFormatter({
|
|
7507
|
+
weekday: "short",
|
|
7508
|
+
calendar: "gregory"
|
|
7509
|
+
}, formatting),
|
|
7510
|
+
formatMonth: createDateFormatter({
|
|
7511
|
+
month: "short",
|
|
7512
|
+
calendar: "gregory"
|
|
7513
|
+
}, formatting),
|
|
7514
|
+
formatMonthYear: createDateFormatter({
|
|
7515
|
+
month: "short",
|
|
7516
|
+
year: "numeric",
|
|
7517
|
+
calendar: "gregory"
|
|
7518
|
+
}, formatting),
|
|
7519
|
+
formatDay: createDateFormatter({
|
|
7520
|
+
weekday: "short",
|
|
7521
|
+
month: "short",
|
|
7522
|
+
day: "numeric",
|
|
7523
|
+
year: "numeric",
|
|
7524
|
+
calendar: "gregory"
|
|
7525
|
+
}, formatting)
|
|
7526
|
+
};
|
|
7527
|
+
};
|
|
7528
|
+
const pad = (value, length) => String(value).padStart(length, "0");
|
|
7529
|
+
/**
|
|
7530
|
+
* The day a UTC proxy stands for.
|
|
7531
|
+
*
|
|
7532
|
+
* @param date - UTC proxy.
|
|
7533
|
+
* @return Its day key.
|
|
7534
|
+
*/
|
|
7535
|
+
const civilKey = (date) => `${pad(date.getUTCFullYear(), 4)}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}`;
|
|
7536
|
+
/**
|
|
7537
|
+
* A day key as a UTC-midnight proxy. UTC has no DST, so every step below is exactly
|
|
7538
|
+
* `DAY_MS`.
|
|
7539
|
+
*
|
|
7540
|
+
* @param key - Day key.
|
|
7541
|
+
* @return The proxy, or null when the key names no real day.
|
|
7542
|
+
*/
|
|
7543
|
+
const civilDate = (key) => {
|
|
7544
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(key);
|
|
7545
|
+
if (!match) return null;
|
|
7546
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
7547
|
+
date.setUTCFullYear(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
|
|
7548
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
7549
|
+
return civilKey(date) === key ? date : null;
|
|
7550
|
+
};
|
|
7551
|
+
/**
|
|
7552
|
+
* The day a written date names, ignoring any time and zone it carries.
|
|
7553
|
+
*
|
|
7554
|
+
* @param text - `yyyy-MM-dd`, optionally followed by a time.
|
|
7555
|
+
* @return Its day key, or null.
|
|
7556
|
+
*/
|
|
7557
|
+
const writtenDayKey = (text) => {
|
|
7558
|
+
const match = DATE_PREFIX.exec(text);
|
|
7559
|
+
if (!match) return null;
|
|
7560
|
+
const key = `${match[1]}-${match[2]}-${match[3]}`;
|
|
7561
|
+
return civilDate(key) ? key : null;
|
|
7562
|
+
};
|
|
7563
|
+
/**
|
|
7564
|
+
* Reads the day an instant falls on in a zone.
|
|
7565
|
+
*
|
|
7566
|
+
* @param timeZone - IANA zone name; absent leaves the runtime's own.
|
|
7567
|
+
* @return Reader taking a `Date`, null for a day no key can hold.
|
|
7568
|
+
*/
|
|
7569
|
+
const instantDayReader = (timeZone) => {
|
|
7570
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
7571
|
+
...KEY_OPTIONS,
|
|
7572
|
+
timeZone
|
|
7573
|
+
});
|
|
7574
|
+
return (date) => {
|
|
7575
|
+
const parts = formatter.formatToParts(date);
|
|
7576
|
+
const read = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
7577
|
+
const key = `${pad(Number(read("year")), 4)}-${read("month")}-${read("day")}`;
|
|
7578
|
+
return civilDate(key) ? key : null;
|
|
7579
|
+
};
|
|
7580
|
+
};
|
|
7581
|
+
/**
|
|
7582
|
+
* The day a series point belongs to.
|
|
7583
|
+
*
|
|
7584
|
+
* A `Date`, or a string carrying `Z` or an offset, is an instant read in the host's
|
|
7585
|
+
* zone. Anything else is a wall clock the host wrote, so its date part is the day.
|
|
7586
|
+
*
|
|
7587
|
+
* @param point - Series point.
|
|
7588
|
+
* @param readInstant - Reader from `instantDayReader`.
|
|
7589
|
+
* @return Its day key, or null when the point carries no usable date.
|
|
7590
|
+
*/
|
|
7591
|
+
const pointDayKey = (point, readInstant) => {
|
|
7592
|
+
if (point.date instanceof Date && !isNaN(point.date.getTime())) {
|
|
7593
|
+
const key = readInstant(point.date);
|
|
7594
|
+
if (key) return key;
|
|
7595
|
+
}
|
|
7596
|
+
const text = point.dateString;
|
|
7597
|
+
if (!text) return null;
|
|
7598
|
+
if (!hasTimezone(text)) return writtenDayKey(text);
|
|
7599
|
+
const parsed = parseISO(text);
|
|
7600
|
+
return isNaN(parsed.getTime()) ? null : readInstant(parsed);
|
|
7601
|
+
};
|
|
7602
|
+
/**
|
|
7603
|
+
* Steps a proxy by whole days.
|
|
7604
|
+
*
|
|
7605
|
+
* @param date - UTC proxy.
|
|
7606
|
+
* @param days - Days to add; may be negative.
|
|
7607
|
+
* @return The shifted proxy.
|
|
7608
|
+
*/
|
|
7609
|
+
const addCivilDays = (date, days) => new Date(date.getTime() + days * DAY_MS);
|
|
7610
|
+
/**
|
|
7611
|
+
* Rounds a proxy down to its week.
|
|
7612
|
+
*
|
|
7613
|
+
* @param date - UTC proxy.
|
|
7614
|
+
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
7615
|
+
* @return The proxy for that week's first day.
|
|
7616
|
+
*/
|
|
7617
|
+
const startOfCivilWeek = (date, weekStartsOn) => {
|
|
7618
|
+
const daysSinceWeekStart = (date.getUTCDay() - weekStartsOn + 7) % 7;
|
|
7619
|
+
return addCivilDays(date, -daysSinceWeekStart);
|
|
7620
|
+
};
|
|
7621
|
+
/**
|
|
7622
|
+
* Counts the columns a span needs.
|
|
7623
|
+
*
|
|
7624
|
+
* @param from - Earlier UTC proxy.
|
|
7625
|
+
* @param to - Later UTC proxy.
|
|
7626
|
+
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
7627
|
+
* @return Columns needed to cover the span, inclusive.
|
|
7628
|
+
*/
|
|
7629
|
+
const civilWeekSpan = (from, to, weekStartsOn) => Math.floor((startOfCivilWeek(to, weekStartsOn).getTime() - startOfCivilWeek(from, weekStartsOn).getTime()) / (7 * DAY_MS)) + 1;
|
|
7630
|
+
//#endregion
|
|
7631
|
+
//#region src/charts/heatmap-chart/build-calendar-data.ts
|
|
7632
|
+
/** Rows that get a weekday label (Mon, Wed, Fri with a Monday week start). */
|
|
7633
|
+
const LABELLED_ROWS = [
|
|
7634
|
+
0,
|
|
7635
|
+
2,
|
|
7636
|
+
4
|
|
7637
|
+
];
|
|
7638
|
+
/**
|
|
7639
|
+
* Resolve one grid bound: an unparseable or narrowing value falls back to the
|
|
7640
|
+
* series' own bound, so the grid can only ever be widened.
|
|
7641
|
+
*
|
|
7642
|
+
* @param bound - Requested bound as `yyyy-MM-dd`, if any.
|
|
7643
|
+
* @param fallback - The series' own bound on this side.
|
|
7644
|
+
* @param direction - Which way the bound is allowed to move.
|
|
7645
|
+
* @return The day key to draw to.
|
|
7646
|
+
*/
|
|
7647
|
+
const widenTo = (bound, fallback, direction) => {
|
|
7648
|
+
const key = bound ? writtenDayKey(bound) : null;
|
|
7649
|
+
if (!key) {
|
|
7650
|
+
if (bound) warnOnce(`heatmap:gridSpan:${bound}`, `gridSpan.${direction === "earlier" ? "start" : "end"} ${JSON.stringify(bound)} is not a \`yyyy-MM-dd\` day, so the grid is drawn over the series' own span.`);
|
|
7651
|
+
return fallback;
|
|
7652
|
+
}
|
|
7653
|
+
if (direction === "earlier") return key < fallback ? key : fallback;
|
|
7654
|
+
return key > fallback ? key : fallback;
|
|
7655
|
+
};
|
|
7656
|
+
/**
|
|
7657
|
+
* Lay a day-bucketed series out as calendar columns.
|
|
7658
|
+
*
|
|
7659
|
+
* @param series - Points to bucket.
|
|
7660
|
+
* @param options - Grid shape, plus the locale and zone to read days in.
|
|
7661
|
+
* @return Columns and row labels for `HeatmapChart`.
|
|
7662
|
+
*/
|
|
7663
|
+
const buildCalendarHeatmapData = (series, options = {}) => {
|
|
7664
|
+
const weekStartsOn = options.weekStartsOn ?? 1;
|
|
7665
|
+
const hideOutOfRangeDays = options.hideOutOfRangeDays ?? true;
|
|
7666
|
+
const { locale, timeZone } = sanitizeFormatting({
|
|
7667
|
+
locale: options.locale,
|
|
7668
|
+
timeZone: options.timeZone
|
|
7669
|
+
});
|
|
7670
|
+
const readInstant = instantDayReader(timeZone);
|
|
7671
|
+
const valueByDay = /* @__PURE__ */ new Map();
|
|
7672
|
+
let minDayKey;
|
|
7673
|
+
let maxDayKey;
|
|
7674
|
+
for (const point of series) {
|
|
7675
|
+
const key = pointDayKey(point, readInstant);
|
|
7676
|
+
if (!key) {
|
|
7677
|
+
const offending = point.dateString ?? (point.date && String(point.date));
|
|
7678
|
+
warnOnce(`heatmap:unreadableDate:${offending}`, offending ? `${JSON.stringify(offending)} is not a day this can read, so its point is left out of the calendar. A \`dateString\` must start \`yyyy-MM-dd\`.` : "A point carries neither `date` nor `dateString`, so it is left out of the calendar.");
|
|
7679
|
+
continue;
|
|
7680
|
+
}
|
|
7681
|
+
valueByDay.set(key, point.value);
|
|
7682
|
+
if (!minDayKey || key < minDayKey) minDayKey = key;
|
|
7683
|
+
if (!maxDayKey || key > maxDayKey) maxDayKey = key;
|
|
7684
|
+
}
|
|
7685
|
+
if (!minDayKey || !maxDayKey) return {
|
|
7686
|
+
data: [],
|
|
7687
|
+
rowLabels: []
|
|
7688
|
+
};
|
|
7689
|
+
const requestedMinDayKey = widenTo(options.gridSpan?.start, minDayKey, "earlier");
|
|
7690
|
+
const gridMaxDayKey = widenTo(options.gridSpan?.end, maxDayKey, "later");
|
|
7691
|
+
const requestedMinDate = civilDate(requestedMinDayKey);
|
|
7692
|
+
const gridMaxDate = civilDate(gridMaxDayKey);
|
|
7693
|
+
const { formatWeekday, formatMonth, formatDay } = civilLabelFormatters(locale);
|
|
7694
|
+
const gridStart = startOfCivilWeek(requestedMinDate, weekStartsOn);
|
|
7695
|
+
const gridMinDayKey = requestedMinDayKey < minDayKey ? civilKey(gridStart) : requestedMinDayKey;
|
|
7696
|
+
const weekCount = civilWeekSpan(gridStart, gridMaxDate, weekStartsOn);
|
|
7697
|
+
const rowLabels = Array.from({ length: 7 }, (_, row) => LABELLED_ROWS.includes(row) ? formatWeekday(addCivilDays(gridStart, row)) : "");
|
|
7698
|
+
const MIN_FIRST_MONTH_WEEKS = 2;
|
|
7699
|
+
const firstMonth = gridStart.getUTCMonth();
|
|
7700
|
+
let firstMonthWeeks = 0;
|
|
7701
|
+
while (firstMonthWeeks < weekCount && addCivilDays(gridStart, firstMonthWeeks * 7).getUTCMonth() === firstMonth) firstMonthWeeks++;
|
|
7702
|
+
const showFirstMonthLabel = !(firstMonthWeeks < weekCount) || firstMonthWeeks >= MIN_FIRST_MONTH_WEEKS;
|
|
7703
|
+
const data = [];
|
|
7704
|
+
let previousMonth = -1;
|
|
7705
|
+
for (let week = 0; week < weekCount; week++) {
|
|
7706
|
+
const columnStart = addCivilDays(gridStart, week * 7);
|
|
7707
|
+
const month = columnStart.getUTCMonth();
|
|
7708
|
+
const label = month !== previousMonth && (week !== 0 || showFirstMonthLabel) ? formatMonth(columnStart) : "";
|
|
7709
|
+
previousMonth = month;
|
|
7710
|
+
const cells = [];
|
|
7711
|
+
for (let row = 0; row < 7; row++) {
|
|
7712
|
+
const day = addCivilDays(gridStart, week * 7 + row);
|
|
7713
|
+
const key = civilKey(day);
|
|
7714
|
+
const cell = {
|
|
7715
|
+
label: formatDay(day),
|
|
7716
|
+
value: valueByDay.has(key) ? valueByDay.get(key) : null
|
|
7717
|
+
};
|
|
7718
|
+
if (key < gridMinDayKey || key > gridMaxDayKey) {
|
|
7719
|
+
if (hideOutOfRangeDays) cell.hidden = true;
|
|
7720
|
+
} else if (key < minDayKey || key > maxDayKey) cell.placeholder = true;
|
|
7721
|
+
cells.push(cell);
|
|
7722
|
+
}
|
|
7723
|
+
data.push({
|
|
7724
|
+
label,
|
|
7725
|
+
data: cells
|
|
7726
|
+
});
|
|
7727
|
+
}
|
|
7728
|
+
return {
|
|
7729
|
+
data,
|
|
7730
|
+
rowLabels
|
|
7731
|
+
};
|
|
7732
|
+
};
|
|
7733
|
+
//#endregion
|
|
7734
|
+
//#region src/charts/heatmap-chart/build-month-calendar-data.ts
|
|
7735
|
+
/** Week rows per month, fixed so every month block is the same height. */
|
|
7736
|
+
const MONTH_ROWS = 6;
|
|
7737
|
+
const DAYS_PER_WEEK = 7;
|
|
7738
|
+
const startOfCivilMonth = (date) => {
|
|
7739
|
+
const first = new Date(date.getTime());
|
|
7740
|
+
first.setUTCDate(1);
|
|
7741
|
+
return first;
|
|
7742
|
+
};
|
|
7743
|
+
const startOfNextCivilMonth = (date) => {
|
|
7744
|
+
const next = startOfCivilMonth(date);
|
|
7745
|
+
next.setUTCMonth(next.getUTCMonth() + 1);
|
|
7746
|
+
return next;
|
|
7747
|
+
};
|
|
7748
|
+
/**
|
|
7749
|
+
* Lay a day-keyed map out as one month calendar per month, weekdays across and
|
|
7750
|
+
* weeks down, for `HeatmapChart` with `columnGroups`.
|
|
7751
|
+
*
|
|
7752
|
+
* @param valueByDay - Value per `yyyy-MM-dd`. A missing day is `null`.
|
|
7753
|
+
* @param range - The measured days; every month from `start`'s through `end`'s is drawn.
|
|
7754
|
+
* @param options - Week start and label locale.
|
|
7755
|
+
* @return Columns and one group per month; empty for an invalid or reversed range.
|
|
7756
|
+
*/
|
|
7757
|
+
const buildMonthCalendarHeatmapData = (valueByDay, range, options = {}) => {
|
|
7758
|
+
const start = civilDate(range.start);
|
|
7759
|
+
const end = civilDate(range.end);
|
|
7760
|
+
if (!start || !end || start.getTime() > end.getTime()) {
|
|
7761
|
+
warnOnce(`heatmap:monthRange:${range.start}:${range.end}`, `range ${JSON.stringify(range)} must be two \`yyyy-MM-dd\` days with start on or before end, so the calendar is empty.`);
|
|
7762
|
+
return {
|
|
7763
|
+
data: [],
|
|
7764
|
+
columnGroups: []
|
|
7765
|
+
};
|
|
7766
|
+
}
|
|
7767
|
+
const startKey = civilKey(start);
|
|
7768
|
+
const endKey = civilKey(end);
|
|
7769
|
+
const weekStartsOn = options.weekStartsOn ?? 1;
|
|
7770
|
+
const { locale } = sanitizeFormatting({ locale: options.locale });
|
|
7771
|
+
for (const key of Object.keys(valueByDay)) if (!civilDate(key)) warnOnce(`heatmap:monthKey:${key}`, `${JSON.stringify(key)} is not a \`yyyy-MM-dd\` day, so its value is left out of the calendar.`);
|
|
7772
|
+
const readValue = (key) => {
|
|
7773
|
+
const value = valueByDay[key];
|
|
7774
|
+
return isPresent(value) ? value : null;
|
|
7775
|
+
};
|
|
7776
|
+
const { formatMonth, formatMonthYear, formatDay } = civilLabelFormatters(locale);
|
|
7777
|
+
const data = [];
|
|
7778
|
+
const columnGroups = [];
|
|
7779
|
+
const lastMonthStart = startOfCivilMonth(end);
|
|
7780
|
+
const formatGroup = (lastMonthStart.getUTCFullYear() - start.getUTCFullYear()) * 12 + lastMonthStart.getUTCMonth() - start.getUTCMonth() + 1 > 12 ? formatMonthYear : formatMonth;
|
|
7781
|
+
for (let monthStart = startOfCivilMonth(start); monthStart.getTime() <= lastMonthStart.getTime(); monthStart = startOfNextCivilMonth(monthStart)) {
|
|
7782
|
+
const monthStartKey = civilKey(monthStart);
|
|
7783
|
+
const monthEndKey = civilKey(addCivilDays(startOfNextCivilMonth(monthStart), -1));
|
|
7784
|
+
const gridStart = startOfCivilWeek(monthStart, weekStartsOn);
|
|
7785
|
+
for (let weekday = 0; weekday < DAYS_PER_WEEK; weekday++) {
|
|
7786
|
+
const cells = [];
|
|
7787
|
+
for (let week = 0; week < MONTH_ROWS; week++) {
|
|
7788
|
+
const day = addCivilDays(gridStart, week * DAYS_PER_WEEK + weekday);
|
|
7789
|
+
const key = civilKey(day);
|
|
7790
|
+
if (key < monthStartKey || key > monthEndKey) cells.push({
|
|
7791
|
+
value: null,
|
|
7792
|
+
hidden: true
|
|
7793
|
+
});
|
|
7794
|
+
else if (key < startKey || key > endKey) cells.push({
|
|
7795
|
+
label: formatDay(day),
|
|
7796
|
+
value: null,
|
|
7797
|
+
placeholder: true
|
|
7798
|
+
});
|
|
7799
|
+
else cells.push({
|
|
7800
|
+
label: formatDay(day),
|
|
7801
|
+
value: readValue(key)
|
|
7802
|
+
});
|
|
7803
|
+
}
|
|
7804
|
+
data.push({ data: cells });
|
|
7805
|
+
}
|
|
7806
|
+
columnGroups.push({
|
|
7807
|
+
label: formatGroup(monthStart),
|
|
7808
|
+
span: DAYS_PER_WEEK
|
|
7809
|
+
});
|
|
7810
|
+
}
|
|
7811
|
+
return {
|
|
7812
|
+
data,
|
|
7813
|
+
columnGroups
|
|
7814
|
+
};
|
|
7815
|
+
};
|
|
7816
|
+
//#endregion
|
|
7201
7817
|
//#region src/charts/heatmap-chart/use-calendar-heatmap-data.ts
|
|
7202
7818
|
/**
|
|
7203
7819
|
* `buildCalendarHeatmapData` with the locale and zone taken from
|
|
@@ -7234,6 +7850,36 @@ const useCalendarHeatmapData = (series, options = {}) => {
|
|
|
7234
7850
|
]);
|
|
7235
7851
|
};
|
|
7236
7852
|
//#endregion
|
|
7853
|
+
//#region src/charts/heatmap-chart/use-month-calendar-heatmap-data.ts
|
|
7854
|
+
/**
|
|
7855
|
+
* `buildMonthCalendarHeatmapData` with the locale taken from `GlobalChartsProvider`
|
|
7856
|
+
* where the caller names none.
|
|
7857
|
+
*
|
|
7858
|
+
* @param valueByDay - Value per `yyyy-MM-dd`. Held by reference, so a caller that rebuilds it each render defeats the memo.
|
|
7859
|
+
* @param range - As for `buildMonthCalendarHeatmapData`.
|
|
7860
|
+
* @param options - As for `buildMonthCalendarHeatmapData`; `locale` wins over the provider.
|
|
7861
|
+
* @return Columns and groups for `HeatmapChart`.
|
|
7862
|
+
*/
|
|
7863
|
+
const useMonthCalendarHeatmapData = (valueByDay, range, options = {}) => {
|
|
7864
|
+
const formatting = useChartFormatting();
|
|
7865
|
+
const locale = options.locale ?? formatting.locale;
|
|
7866
|
+
const { weekStartsOn } = options;
|
|
7867
|
+
const { start, end } = range;
|
|
7868
|
+
return useMemo(() => buildMonthCalendarHeatmapData(valueByDay, {
|
|
7869
|
+
start,
|
|
7870
|
+
end
|
|
7871
|
+
}, {
|
|
7872
|
+
locale,
|
|
7873
|
+
weekStartsOn
|
|
7874
|
+
}), [
|
|
7875
|
+
valueByDay,
|
|
7876
|
+
start,
|
|
7877
|
+
end,
|
|
7878
|
+
locale,
|
|
7879
|
+
weekStartsOn
|
|
7880
|
+
]);
|
|
7881
|
+
};
|
|
7882
|
+
//#endregion
|
|
7237
7883
|
//#region ../../../node_modules/.pnpm/is-plain-object@5.1.0/node_modules/is-plain-object/dist/is-plain-object.mjs
|
|
7238
7884
|
/*!
|
|
7239
7885
|
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
|
@@ -7301,7 +7947,24 @@ function paramCase(input, options) {
|
|
|
7301
7947
|
return dotCase(input, __assign({ delimiter: "-" }, options));
|
|
7302
7948
|
}
|
|
7303
7949
|
//#endregion
|
|
7304
|
-
//#region ../../../node_modules/.pnpm/@wordpress+
|
|
7950
|
+
//#region ../../../node_modules/.pnpm/@wordpress+warning@3.55.0/node_modules/@wordpress/warning/build-module/utils.mjs
|
|
7951
|
+
var logged = /* @__PURE__ */ new Set();
|
|
7952
|
+
//#endregion
|
|
7953
|
+
//#region ../../../node_modules/.pnpm/@wordpress+warning@3.55.0/node_modules/@wordpress/warning/build-module/index.mjs
|
|
7954
|
+
function isDev() {
|
|
7955
|
+
return globalThis.SCRIPT_DEBUG === true;
|
|
7956
|
+
}
|
|
7957
|
+
function warning(message) {
|
|
7958
|
+
if (!isDev()) return;
|
|
7959
|
+
if (logged.has(message)) return;
|
|
7960
|
+
console.warn(message);
|
|
7961
|
+
try {
|
|
7962
|
+
throw Error(message);
|
|
7963
|
+
} catch {}
|
|
7964
|
+
logged.add(message);
|
|
7965
|
+
}
|
|
7966
|
+
//#endregion
|
|
7967
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/hooks/use-update-effect.mjs
|
|
7305
7968
|
function useUpdateEffect(effect, deps) {
|
|
7306
7969
|
const mountedRef = useRef$1(false);
|
|
7307
7970
|
useEffect$1(() => {
|
|
@@ -8871,7 +9534,7 @@ _createEmotion.css;
|
|
|
8871
9534
|
_createEmotion.sheet;
|
|
8872
9535
|
_createEmotion.cache;
|
|
8873
9536
|
//#endregion
|
|
8874
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9537
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/hooks/use-cx.mjs
|
|
8875
9538
|
var isSerializedStyles = (o) => typeof o !== "undefined" && o !== null && ["name", "styles"].every((p) => typeof o[p] !== "undefined");
|
|
8876
9539
|
var useCx = () => {
|
|
8877
9540
|
const cache = __unsafe_useEmotionCache();
|
|
@@ -8978,7 +9641,7 @@ function memize(fn, options) {
|
|
|
8978
9641
|
return memoized;
|
|
8979
9642
|
}
|
|
8980
9643
|
//#endregion
|
|
8981
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9644
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/colors-values.mjs
|
|
8982
9645
|
var white = "#fff";
|
|
8983
9646
|
var GRAY = {
|
|
8984
9647
|
900: "#1e1e1e",
|
|
@@ -9028,8 +9691,8 @@ var UI = {
|
|
|
9028
9691
|
border: THEME.gray[600],
|
|
9029
9692
|
borderHover: THEME.gray[700],
|
|
9030
9693
|
borderFocus: THEME.accent,
|
|
9031
|
-
borderDisabled:
|
|
9032
|
-
textDisabled:
|
|
9694
|
+
borderDisabled: `var(--wpds-color-stroke-interactive-neutral-disabled, #dbdbdb)`,
|
|
9695
|
+
textDisabled: `var(--wpds-color-foreground-interactive-neutral-disabled, #8d8d8d)`,
|
|
9033
9696
|
darkGrayPlaceholder: `color-mix(in srgb, ${THEME.foreground}, transparent 38%)`,
|
|
9034
9697
|
lightGrayPlaceholder: `color-mix(in srgb, ${THEME.background}, transparent 35%)`
|
|
9035
9698
|
};
|
|
@@ -9057,7 +9720,7 @@ var COLORS = Object.freeze({
|
|
|
9057
9720
|
ui: UI
|
|
9058
9721
|
});
|
|
9059
9722
|
//#endregion
|
|
9060
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9723
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/config-values.mjs
|
|
9061
9724
|
var CONTROL_HEIGHT = "36px";
|
|
9062
9725
|
var CONTROL_PROPS = {
|
|
9063
9726
|
controlPaddingX: 12,
|
|
@@ -9111,8 +9774,8 @@ var config_values_default = Object.assign({}, CONTROL_PROPS, {
|
|
|
9111
9774
|
transitionTimingFunctionControl: "cubic-bezier(0.12, 0.8, 0.32, 1)"
|
|
9112
9775
|
});
|
|
9113
9776
|
//#endregion
|
|
9114
|
-
//#region ../../../node_modules/.pnpm
|
|
9115
|
-
var
|
|
9777
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
|
|
9778
|
+
var import_es6 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
9116
9779
|
module.exports = function equal(a, b) {
|
|
9117
9780
|
if (a === b) return true;
|
|
9118
9781
|
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
@@ -9156,31 +9819,8 @@ var require_es6 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9156
9819
|
}
|
|
9157
9820
|
return a !== a && b !== b;
|
|
9158
9821
|
};
|
|
9159
|
-
}));
|
|
9160
|
-
|
|
9161
|
-
//#region ../../../node_modules/.pnpm/@wordpress+warning@3.54.0/node_modules/@wordpress/warning/build-module/utils.mjs
|
|
9162
|
-
var logged = /* @__PURE__ */ new Set();
|
|
9163
|
-
//#endregion
|
|
9164
|
-
//#region ../../../node_modules/.pnpm/@wordpress+warning@3.54.0/node_modules/@wordpress/warning/build-module/index.mjs
|
|
9165
|
-
function isDev() {
|
|
9166
|
-
return globalThis.SCRIPT_DEBUG === true;
|
|
9167
|
-
}
|
|
9168
|
-
function warning(message) {
|
|
9169
|
-
if (!isDev()) return;
|
|
9170
|
-
if (logged.has(message)) return;
|
|
9171
|
-
console.warn(message);
|
|
9172
|
-
try {
|
|
9173
|
-
throw Error(message);
|
|
9174
|
-
} catch {}
|
|
9175
|
-
logged.add(message);
|
|
9176
|
-
}
|
|
9177
|
-
//#endregion
|
|
9178
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.0.0_@date-fns+tz@1.4.1_@types+react-dom@18.3.7_@types+react@18_4546240ebdf94d561ebf2fde285113fe/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
|
|
9179
|
-
var import_es6 = /* @__PURE__ */ __toESM(require_es6(), 1);
|
|
9180
|
-
var ComponentsContext = createContext$1(
|
|
9181
|
-
/** @type {Record<string, any>} */
|
|
9182
|
-
{}
|
|
9183
|
-
);
|
|
9822
|
+
})))(), 1);
|
|
9823
|
+
var ComponentsContext = createContext$1({});
|
|
9184
9824
|
ComponentsContext.displayName = "ComponentsContext";
|
|
9185
9825
|
var useComponentsContext = () => useContext$1(ComponentsContext);
|
|
9186
9826
|
function useContextSystemBridge({ value }) {
|
|
@@ -9202,18 +9842,18 @@ var BaseContextSystemProvider = ({ children, value }) => {
|
|
|
9202
9842
|
};
|
|
9203
9843
|
memo(BaseContextSystemProvider);
|
|
9204
9844
|
//#endregion
|
|
9205
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9845
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/constants.mjs
|
|
9206
9846
|
var COMPONENT_NAMESPACE = "data-wp-component";
|
|
9207
9847
|
var CONNECTED_NAMESPACE = "data-wp-c16t";
|
|
9208
9848
|
var CONNECT_STATIC_NAMESPACE = "__contextSystemKey__";
|
|
9209
9849
|
//#endregion
|
|
9210
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9850
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/get-styled-class-name-from-key.mjs
|
|
9211
9851
|
function getStyledClassName(namespace) {
|
|
9212
9852
|
return `components-${paramCase(namespace)}`;
|
|
9213
9853
|
}
|
|
9214
9854
|
var getStyledClassNameFromKey = memize(getStyledClassName);
|
|
9215
9855
|
//#endregion
|
|
9216
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9856
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/context-connect.mjs
|
|
9217
9857
|
function contextConnect(Component, namespace) {
|
|
9218
9858
|
return _contextConnect(Component, namespace, { forwardsRef: true });
|
|
9219
9859
|
}
|
|
@@ -9230,7 +9870,7 @@ function _contextConnect(Component, namespace, options) {
|
|
|
9230
9870
|
});
|
|
9231
9871
|
}
|
|
9232
9872
|
//#endregion
|
|
9233
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9873
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/utils.mjs
|
|
9234
9874
|
function getNamespace(componentName) {
|
|
9235
9875
|
return { [COMPONENT_NAMESPACE]: componentName };
|
|
9236
9876
|
}
|
|
@@ -9238,7 +9878,7 @@ function getConnectedNamespace() {
|
|
|
9238
9878
|
return { [CONNECTED_NAMESPACE]: true };
|
|
9239
9879
|
}
|
|
9240
9880
|
//#endregion
|
|
9241
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9881
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/context/use-context-system.mjs
|
|
9242
9882
|
function useContextSystem(props, namespace) {
|
|
9243
9883
|
const contextSystemProps = useComponentsContext();
|
|
9244
9884
|
if (typeof namespace === "undefined") globalThis.SCRIPT_DEBUG === true && warning("useContextSystem: Please provide a namespace");
|
|
@@ -9247,10 +9887,12 @@ function useContextSystem(props, namespace) {
|
|
|
9247
9887
|
...getConnectedNamespace(),
|
|
9248
9888
|
...getNamespace(namespace)
|
|
9249
9889
|
};
|
|
9250
|
-
const { _overrides
|
|
9890
|
+
const { _overrides, ...otherContextProps } = contextProps;
|
|
9891
|
+
const overrideProps = _overrides;
|
|
9251
9892
|
const initialMergedProps = Object.entries(otherContextProps).length ? Object.assign({}, otherContextProps, props) : props;
|
|
9893
|
+
const propsWithChildren = initialMergedProps;
|
|
9252
9894
|
const classes = useCx()(getStyledClassNameFromKey(namespace), props.className);
|
|
9253
|
-
const rendered = typeof
|
|
9895
|
+
const rendered = typeof propsWithChildren.renderChildren === "function" ? propsWithChildren.renderChildren(initialMergedProps) : propsWithChildren.children;
|
|
9254
9896
|
for (const key in initialMergedProps) finalComponentProps[key] = initialMergedProps[key];
|
|
9255
9897
|
for (const key in overrideProps) finalComponentProps[key] = overrideProps[key];
|
|
9256
9898
|
if (rendered !== void 0) finalComponentProps.children = rendered;
|
|
@@ -9258,7 +9900,7 @@ function useContextSystem(props, namespace) {
|
|
|
9258
9900
|
return finalComponentProps;
|
|
9259
9901
|
}
|
|
9260
9902
|
//#endregion
|
|
9261
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9903
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/visually-hidden/styles.mjs
|
|
9262
9904
|
var visuallyHidden = {
|
|
9263
9905
|
border: 0,
|
|
9264
9906
|
clip: "rect(1px, 1px, 1px, 1px)",
|
|
@@ -9274,7 +9916,7 @@ var visuallyHidden = {
|
|
|
9274
9916
|
wordBreak: "normal"
|
|
9275
9917
|
};
|
|
9276
9918
|
//#endregion
|
|
9277
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
9919
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/polymorphic-element.mjs
|
|
9278
9920
|
var customAttributeRegExp = /^(data|aria|x)-/i;
|
|
9279
9921
|
var eventHandlerRegExp = /^on[A-Z]/;
|
|
9280
9922
|
var svgElementNames = new Set(`animate animateMotion animateTransform circle clipPath defs desc ellipse
|
|
@@ -9364,7 +10006,7 @@ function UnforwardedPolymorphicElement({ as, ...props }, ref) {
|
|
|
9364
10006
|
}
|
|
9365
10007
|
var PolymorphicElement = forwardRef$1(UnforwardedPolymorphicElement);
|
|
9366
10008
|
//#endregion
|
|
9367
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10009
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/view/component.mjs
|
|
9368
10010
|
function UnforwardedView({ css, ...restProps }, ref) {
|
|
9369
10011
|
return /* @__PURE__ */ jsx(PolymorphicElement, {
|
|
9370
10012
|
ref,
|
|
@@ -9373,7 +10015,7 @@ function UnforwardedView({ css, ...restProps }, ref) {
|
|
|
9373
10015
|
}
|
|
9374
10016
|
var component_default$2 = Object.assign(forwardRef$1(UnforwardedView), { selector: ".components-view" });
|
|
9375
10017
|
//#endregion
|
|
9376
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10018
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/visually-hidden/component.mjs
|
|
9377
10019
|
function UnconnectedVisuallyHidden(props, forwardedRef) {
|
|
9378
10020
|
const { style: styleProp, ...contextProps } = useContextSystem(props, "VisuallyHidden");
|
|
9379
10021
|
return /* @__PURE__ */ jsx(component_default$2, {
|
|
@@ -9388,7 +10030,7 @@ function UnconnectedVisuallyHidden(props, forwardedRef) {
|
|
|
9388
10030
|
}
|
|
9389
10031
|
var component_default$1 = contextConnect(UnconnectedVisuallyHidden, "VisuallyHidden");
|
|
9390
10032
|
//#endregion
|
|
9391
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10033
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/utils/use-responsive-value.mjs
|
|
9392
10034
|
var breakpoints = [
|
|
9393
10035
|
"40em",
|
|
9394
10036
|
"52em",
|
|
@@ -9422,7 +10064,7 @@ function useResponsiveValue(values, options = {}) {
|
|
|
9422
10064
|
return array[index >= array.length ? array.length - 1 : index];
|
|
9423
10065
|
}
|
|
9424
10066
|
//#endregion
|
|
9425
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10067
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/grid/utils.mjs
|
|
9426
10068
|
var ALIGNMENTS = {
|
|
9427
10069
|
bottom: {
|
|
9428
10070
|
alignItems: "flex-end",
|
|
@@ -9470,7 +10112,7 @@ function getAlignmentProps(alignment) {
|
|
|
9470
10112
|
return alignment ? ALIGNMENTS[alignment] : {};
|
|
9471
10113
|
}
|
|
9472
10114
|
//#endregion
|
|
9473
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10115
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/grid/hook.mjs
|
|
9474
10116
|
function useGrid(props) {
|
|
9475
10117
|
const { align, alignment, className, columnGap, columns = 2, gap = 3, isInline = false, justify, rowGap, rows, templateColumns, templateRows, ...otherProps } = useContextSystem(props, "Grid");
|
|
9476
10118
|
const column = useResponsiveValue(Array.isArray(columns) ? columns : [columns]);
|
|
@@ -9512,7 +10154,7 @@ function useGrid(props) {
|
|
|
9512
10154
|
};
|
|
9513
10155
|
}
|
|
9514
10156
|
//#endregion
|
|
9515
|
-
//#region ../../../node_modules/.pnpm/@wordpress+components@40.
|
|
10157
|
+
//#region ../../../node_modules/.pnpm/@wordpress+components@40.1.0_@date-fns+tz@1.5.0_@types+react-dom@18.3.7_@types+react@18_c300d25e93ed6b8d3659e83df7c1508a/node_modules/@wordpress/components/build-module/grid/component.mjs
|
|
9516
10158
|
function UnconnectedGrid(props, forwardedRef) {
|
|
9517
10159
|
const gridProps = useGrid(props);
|
|
9518
10160
|
return /* @__PURE__ */ jsx(component_default$2, {
|
|
@@ -10768,6 +11410,6 @@ function TrendIndicator({ direction, value, className, style, showIcon = true })
|
|
|
10768
11410
|
});
|
|
10769
11411
|
}
|
|
10770
11412
|
//#endregion
|
|
10771
|
-
export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, GoogleDataTableColumnRoleType, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TrendIndicator, buildCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getBucketInfo, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, prefersLightText, relativeLuminance, resolveCssVariable, useCalendarHeatmapData, useChartFormatting, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, validateHexColor };
|
|
11413
|
+
export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, GoogleDataTableColumnRoleType, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TrendIndicator, buildCalendarHeatmapData, buildMonthCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getBucketInfo, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, prefersLightText, relativeLuminance, resolveCssVariable, useCalendarHeatmapData, useChartFormatting, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, useMonthCalendarHeatmapData, validateHexColor };
|
|
10772
11414
|
|
|
10773
11415
|
//# sourceMappingURL=index.js.map
|