@kind-ui/charts 0.1.1 → 0.3.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 +32 -0
- package/README.md +683 -1
- package/dist/activity-rings.d.ts +2 -1
- package/dist/activity-rings.js +6 -3
- package/dist/animation.d.ts +11 -3
- package/dist/animation.js +18 -10
- package/dist/area-chart.d.ts +3 -1
- package/dist/area-chart.js +15 -10
- package/dist/area-series.d.ts +9 -1
- package/dist/area-series.js +35 -8
- package/dist/bar-chart.d.ts +10 -3
- package/dist/bar-chart.js +17 -4
- package/dist/bar-material.js +2 -3
- package/dist/bar-series.d.ts +11 -1
- package/dist/bar-series.js +65 -13
- package/dist/box-plot.js +2 -2
- package/dist/category-cells.d.ts +7 -1
- package/dist/category-cells.js +32 -2
- package/dist/chart-background-pattern.d.ts +23 -0
- package/dist/chart-background-pattern.js +31 -0
- package/dist/chart-context.d.ts +6 -2
- package/dist/chart-interaction.d.ts +94 -0
- package/dist/chart-interaction.js +224 -0
- package/dist/combo-chart.d.ts +8 -5
- package/dist/combo-chart.js +14 -12
- package/dist/configured-line-chart.d.ts +5 -1
- package/dist/configured-line-chart.js +8 -5
- package/dist/emphasis.d.ts +5 -2
- package/dist/emphasis.js +18 -4
- package/dist/fill-pattern.d.ts +25 -0
- package/dist/fill-pattern.js +23 -0
- package/dist/heatmap.d.ts +4 -2
- package/dist/heatmap.js +34 -12
- package/dist/histogram-chart.js +10 -3
- package/dist/histogram-material.js +1 -2
- package/dist/index.d.ts +12 -3
- package/dist/index.js +8 -1
- package/dist/legend.d.ts +2 -0
- package/dist/legend.js +28 -7
- package/dist/line-chart.d.ts +13 -3
- package/dist/line-chart.js +54 -34
- package/dist/line-dash.d.ts +8 -0
- package/dist/line-dash.js +18 -0
- package/dist/line-material.d.ts +1 -1
- package/dist/line-material.js +1 -1
- package/dist/line-series.d.ts +9 -1
- package/dist/line-series.js +37 -11
- package/dist/loading-cartesian-designs.d.ts +6 -0
- package/dist/loading-cartesian-designs.js +123 -0
- package/dist/loading-motion.d.ts +37 -0
- package/dist/loading-motion.js +88 -0
- package/dist/loading-polar-designs.d.ts +6 -0
- package/dist/loading-polar-designs.js +95 -0
- package/dist/loading-skeleton.d.ts +29 -0
- package/dist/loading-skeleton.js +143 -0
- package/dist/loading-standalone-designs.d.ts +5 -0
- package/dist/loading-standalone-designs.js +126 -0
- package/dist/percent-stack.d.ts +18 -0
- package/dist/percent-stack.js +33 -0
- package/dist/pie-chart.d.ts +7 -3
- package/dist/pie-chart.js +37 -6
- package/dist/pie-material.js +1 -1
- package/dist/pie-pin-identity.d.ts +4 -0
- package/dist/pie-pin-identity.js +10 -0
- package/dist/pie-series.d.ts +4 -0
- package/dist/pie-series.js +138 -15
- package/dist/pie-tooltip-pin.d.ts +4 -0
- package/dist/pie-tooltip-pin.js +52 -0
- package/dist/point-marker.d.ts +19 -0
- package/dist/point-marker.js +19 -0
- package/dist/polar-chart.d.ts +14 -5
- package/dist/polar-chart.js +41 -10
- package/dist/polar-material.js +1 -1
- package/dist/polar-series.js +68 -22
- package/dist/radar-interaction.js +10 -4
- package/dist/radial-category.d.ts +2 -0
- package/dist/reveal-clip.d.ts +16 -0
- package/dist/reveal-clip.js +18 -0
- package/dist/root.d.ts +5 -9
- package/dist/root.js +46 -11
- package/dist/sankey-chart.d.ts +5 -1
- package/dist/sankey-chart.js +64 -13
- package/dist/sankey-colors.d.ts +3 -0
- package/dist/sankey-finish.d.ts +1 -1
- package/dist/sankey-finish.js +1 -1
- package/dist/sankey-interaction.d.ts +8 -0
- package/dist/sankey-interaction.js +32 -0
- package/dist/sankey-legend.d.ts +2 -1
- package/dist/sankey-legend.js +18 -3
- package/dist/sankey-node-label.d.ts +22 -0
- package/dist/sankey-node-label.js +34 -0
- package/dist/scatter-chart.d.ts +5 -3
- package/dist/scatter-chart.js +14 -4
- package/dist/scatter-material.js +1 -1
- package/dist/scatter-series.js +5 -3
- package/dist/series-color.d.ts +10 -0
- package/dist/series-color.js +48 -0
- package/dist/series-interaction.d.ts +12 -0
- package/dist/series-interaction.js +82 -0
- package/dist/series-label.d.ts +7 -0
- package/dist/series-label.js +18 -0
- package/dist/series-paint.d.ts +8 -0
- package/dist/series-paint.js +27 -0
- package/dist/styles.css +151 -6
- package/dist/stylesheet-warning.d.ts +2 -0
- package/dist/stylesheet-warning.js +86 -0
- package/dist/surface-material.js +1 -1
- package/dist/tooltip-content.d.ts +8 -1
- package/dist/tooltip-content.js +15 -4
- package/dist/tooltip.d.ts +3 -1
- package/dist/tooltip.js +8 -5
- package/dist/types.d.ts +11 -2
- package/dist/waterfall-chart.d.ts +4 -0
- package/dist/waterfall-chart.js +7 -0
- package/package.json +2 -2
- package/dist/bar-paper.d.ts +0 -2
- package/dist/bar-paper.js +0 -6
package/dist/activity-rings.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { type RadialBarChartProps } from "./polar-chart.js";
|
|
|
6
6
|
import { type RadialBarSeriesProps } from "./polar-series.js";
|
|
7
7
|
import { type RootProps } from "./root.js";
|
|
8
8
|
import type { SeriesConfig } from "./types.js";
|
|
9
|
+
type ActivityRootProps = RootProps extends infer Props ? Props extends object ? Omit<Props, "config" | "children"> : never : never;
|
|
9
10
|
export type ActivityRing = {
|
|
10
11
|
/** Stable metadata identity in config. Array order controls ring order. */
|
|
11
12
|
key: string;
|
|
@@ -40,7 +41,7 @@ export type ActivityRingsProps = Omit<RadialBarChartProps<ActivityRingDatum>, "d
|
|
|
40
41
|
legend?: false | LegendProps;
|
|
41
42
|
/** Custom content receives native payload with original value and normalized progress. */
|
|
42
43
|
tooltip?: false | TooltipProps;
|
|
43
|
-
rootProps?:
|
|
44
|
+
rootProps?: ActivityRootProps;
|
|
44
45
|
};
|
|
45
46
|
/** A narrow progress recipe; native RadialBarChart remains the full composition escape hatch. */
|
|
46
47
|
export declare function ActivityRings({ rings, config, domain, series, labels, legend, tooltip, rootProps, width, height, style, className, responsive, accessibilityLayer, ...chartProps }: ActivityRingsProps): import("react").JSX.Element;
|
package/dist/activity-rings.js
CHANGED
|
@@ -5,10 +5,11 @@ import { Cell, LabelList, PolarAngleAxis, PolarRadiusAxis } from "recharts";
|
|
|
5
5
|
import { Tooltip } from "./animation.js";
|
|
6
6
|
import { ChartContext } from "./chart-context.js";
|
|
7
7
|
import { Legend } from "./legend.js";
|
|
8
|
-
import {
|
|
8
|
+
import { RadialBarChartFrame } from "./polar-chart.js";
|
|
9
9
|
import { RadialBarSeries } from "./polar-series.js";
|
|
10
10
|
import { RadialBarLabel } from "./radial-bar-label.js";
|
|
11
11
|
import { Root } from "./root.js";
|
|
12
|
+
import { resolveSeriesLabel } from "./series-label.js";
|
|
12
13
|
import { TooltipContent } from "./tooltip-content.js";
|
|
13
14
|
/** A narrow progress recipe; native RadialBarChart remains the full composition escape hatch. */
|
|
14
15
|
export function ActivityRings({ rings, config, domain = [0, 100], series, labels = false, legend, tooltip, rootProps, width, height, style, className, responsive = true, accessibilityLayer = true, ...chartProps }) {
|
|
@@ -33,7 +34,7 @@ export function ActivityRings({ rings, config, domain = [0, 100], series, labels
|
|
|
33
34
|
return {
|
|
34
35
|
...ring,
|
|
35
36
|
// biome-ignore lint/style/noNonNullAssertion: Object.hasOwn above rejects ring keys absent from config.
|
|
36
|
-
label: config[ring.key].label,
|
|
37
|
+
label: resolveSeriesLabel(ring.key, config[ring.key].label),
|
|
37
38
|
rawValue: ring.value,
|
|
38
39
|
progress: Math.max(0, Math.min(100, ((ring.value - min) / (max - min)) * 100)),
|
|
39
40
|
};
|
|
@@ -41,7 +42,9 @@ export function ActivityRings({ rings, config, domain = [0, 100], series, labels
|
|
|
41
42
|
// biome-ignore lint/style/noNonNullAssertion: Every key was validated against config while constructing data.
|
|
42
43
|
const activeConfig = Object.fromEntries(keys.map((key) => [key, config[key]]));
|
|
43
44
|
const describedBy = [chartProps["aria-describedby"], descriptionId].filter(Boolean).join(" ");
|
|
44
|
-
return (_jsxs(Root, { ...rootProps, config: activeConfig, children: [_jsx("dl", { id: descriptionId, "data-kind-ui": "chart-instructions", children: data.map((ring) => (_jsxs("div", { children: [_jsx("dt", { children: ring.label }), _jsx("dd", { children: config[ring.key].formatValue?.(ring.rawValue) ?? ring.rawValue })] }, ring.key))) }), _jsxs(
|
|
45
|
+
return (_jsxs(Root, { ...rootProps, config: activeConfig, children: [_jsx("dl", { id: descriptionId, "data-kind-ui": "chart-instructions", "aria-hidden": chartProps.loading || undefined, children: data.map((ring) => (_jsxs("div", { children: [_jsx("dt", { children: ring.label }), _jsx("dd", { children: config[ring.key].formatValue?.(ring.rawValue) ?? ring.rawValue })] }, ring.key))) }), _jsxs(RadialBarChartFrame, { skeletonFamily: "activity-rings", innerRadius: "30%", outerRadius: "90%", startAngle: 90, endAngle: -270, barCategoryGap: "15%", ...chartProps, "aria-describedby": describedBy, data: data, categoryKey: "key", ...(rootProps?.interaction?.kind === "category"
|
|
46
|
+
? { interactionBinding: "root" }
|
|
47
|
+
: {}), layout: "radial", accessibilityLayer: accessibilityLayer, responsive: responsive, ...(width !== undefined ? { width } : {}), ...(height !== undefined ? { height } : {}), className: ["kind-ui-activity-rings", className].filter(Boolean).join(" "), style: { width: width ?? "100%", height: height ?? 300, ...style }, children: [_jsx(PolarAngleAxis, { type: "number", domain: [0, 100], tick: false, axisLine: false }), _jsx(PolarRadiusAxis, { type: "category", dataKey: "key", tick: false, axisLine: false }), _jsxs(RadialBarSeries, { background: true, cornerRadius: "50%", ...series, dataKey: "progress", children: [data.some((ring) => ring.cellProps !== undefined) &&
|
|
45
48
|
data.map((ring) => _jsx(Cell, { ...ring.cellProps }, ring.key)), labels !== false && (_jsx(LabelList, { content: _jsx(RadialBarLabel, {}), ...labels, dataKey: "label" }))] }), tooltip !== false && (_jsx(Tooltip, { content: (native) => (_jsx(TooltipContent, { tooltip: {
|
|
46
49
|
...native,
|
|
47
50
|
payload: native.payload.map((entry) => {
|
package/dist/animation.d.ts
CHANGED
|
@@ -3,12 +3,18 @@ import { type ReactElement } from "react";
|
|
|
3
3
|
import { type DotProps } from "recharts";
|
|
4
4
|
import { type LineChartProps as StaticLineChartProps } from "./line-chart.js";
|
|
5
5
|
import { type LineSeriesProps as StaticLineSeriesProps } from "./line-series.js";
|
|
6
|
+
import { type PointStyle } from "./point-marker.js";
|
|
7
|
+
import { type RevealDirection } from "./reveal-clip.js";
|
|
6
8
|
import { type TooltipProps } from "./tooltip.js";
|
|
7
|
-
export type
|
|
9
|
+
export type BaseAnimation = {
|
|
8
10
|
revealDurationMs?: number;
|
|
9
11
|
revealEasing?: Transition["ease"];
|
|
10
12
|
hoverTransition?: Transition;
|
|
11
13
|
};
|
|
14
|
+
export type LineAnimation = BaseAnimation & {
|
|
15
|
+
/** Physical horizontal entrance direction, independent of native chart layout. */
|
|
16
|
+
revealDirection?: RevealDirection;
|
|
17
|
+
};
|
|
12
18
|
type DefaultLineDataKey = Extract<StaticLineSeriesProps["dataKey"], (row: never) => unknown>;
|
|
13
19
|
export type LineSeriesProps<DataPoint = Parameters<DefaultLineDataKey>[0], Value = ReturnType<DefaultLineDataKey>> = Omit<StaticLineSeriesProps<DataPoint, Value>, "isAnimationActive">;
|
|
14
20
|
export type LineChartProps = StaticLineChartProps & {
|
|
@@ -19,8 +25,10 @@ export declare const MotionContext: import("react").Context<{
|
|
|
19
25
|
transition: Transition;
|
|
20
26
|
}>;
|
|
21
27
|
/** Motion owns the shared entrance clip and default active marks. */
|
|
22
|
-
export declare function LineChart({ animate, children, ...props }: LineChartProps): import("react").JSX.Element;
|
|
23
|
-
export declare function ActiveMarker({ cx, cy, fill, stroke }: DotProps
|
|
28
|
+
export declare function LineChart({ animate, loading, loadingLabel, children, ...props }: LineChartProps): import("react").JSX.Element;
|
|
29
|
+
export declare function ActiveMarker({ cx, cy, fill, stroke, variant, }: DotProps & {
|
|
30
|
+
variant?: PointStyle | undefined;
|
|
31
|
+
}): import("react").JSX.Element | null;
|
|
24
32
|
export declare function LineSeries<DataPoint = Parameters<DefaultLineDataKey>[0], Value = ReturnType<DefaultLineDataKey>>(props: LineSeriesProps<DataPoint, Value>): ReactElement;
|
|
25
33
|
export declare function LineSeries(props: LineSeriesProps): ReactElement;
|
|
26
34
|
export declare function Tooltip(props: TooltipProps): import("react").JSX.Element;
|
package/dist/animation.js
CHANGED
|
@@ -6,6 +6,9 @@ import { DefaultZIndexes, LineChart as EngineLineChart, ZIndexLayer, } from "rec
|
|
|
6
6
|
import { useChart } from "./chart-context.js";
|
|
7
7
|
import { LineChartFrame, useLineInteraction, } from "./line-chart.js";
|
|
8
8
|
import { LineSeries as StaticLineSeries, } from "./line-series.js";
|
|
9
|
+
import { registerPiePinComponent } from "./pie-pin-identity.js";
|
|
10
|
+
import { markerPaint } from "./point-marker.js";
|
|
11
|
+
import { RevealClip } from "./reveal-clip.js";
|
|
9
12
|
import { TooltipBase } from "./tooltip.js";
|
|
10
13
|
const defaultHover = { type: "spring", stiffness: 210, damping: 28, mass: 0.8 };
|
|
11
14
|
export const MotionContext = createContext({ enabled: false, transition: defaultHover });
|
|
@@ -18,19 +21,23 @@ function subscribe(change) {
|
|
|
18
21
|
const snapshot = () => window.matchMedia(query).matches;
|
|
19
22
|
const serverSnapshot = () => true;
|
|
20
23
|
/** Motion owns the shared entrance clip and default active marks. */
|
|
21
|
-
export function LineChart({ animate = false, children, ...props }) {
|
|
24
|
+
export function LineChart({ animate = false, loading, loadingLabel, children, ...props }) {
|
|
22
25
|
const id = useId();
|
|
23
26
|
const reduced = useSyncExternalStore(subscribe, snapshot, serverSnapshot);
|
|
24
27
|
const [interacted, setInteracted] = useState(false);
|
|
25
28
|
const options = typeof animate === "object" ? animate : {};
|
|
26
|
-
const enabled = animate !== false && !reduced;
|
|
27
|
-
const interrupt = useCallback(() =>
|
|
29
|
+
const enabled = animate !== false && !reduced && !loading;
|
|
30
|
+
const interrupt = useCallback(() => {
|
|
31
|
+
if (!loading)
|
|
32
|
+
setInteracted(true);
|
|
33
|
+
}, [loading]);
|
|
34
|
+
useLayoutEffect(() => {
|
|
35
|
+
if (loading)
|
|
36
|
+
setInteracted(false);
|
|
37
|
+
}, [loading]);
|
|
28
38
|
const reveal = enabled && !interacted;
|
|
29
39
|
const transition = options.hoverTransition ?? defaultHover;
|
|
30
|
-
return (_jsx(MotionContext, { value: { enabled, transition }, children: _jsxs(LineChartFrame, { chartProps: props, engine: EngineLineChart, motionEnabled: enabled, interrupt: interrupt, ...(reveal ? { clip: `url(#${id}-reveal)` } : {}), children: [reveal && (_jsx(
|
|
31
|
-
duration: Math.max(0, options.revealDurationMs ?? 1000) / 1000,
|
|
32
|
-
ease: options.revealEasing ?? [0.25, 0.1, 0.25, 1],
|
|
33
|
-
} }) }) })), children] }) }));
|
|
40
|
+
return (_jsx(MotionContext, { value: { enabled, transition }, children: _jsxs(LineChartFrame, { chartProps: props, loading: loading, loadingLabel: loadingLabel, loadingSkeleton: "line", loadingAnimation: options, engine: EngineLineChart, motionEnabled: enabled, interrupt: interrupt, ...(reveal ? { clip: `url(#${id}-reveal)` } : {}), children: [reveal && (_jsx(RevealClip, { id: `${id}-reveal`, options: options, ...(options.revealDirection === undefined ? {} : { finish: interrupt }) })), children] }) }));
|
|
34
41
|
}
|
|
35
42
|
// Stop the previous target before retargeting or snapping, without remounting consumer DOM.
|
|
36
43
|
function useAnimatedCoordinate(target, enabled, transition) {
|
|
@@ -45,7 +52,7 @@ function useAnimatedCoordinate(target, enabled, transition) {
|
|
|
45
52
|
}, [value, target, enabled, transition]);
|
|
46
53
|
return value;
|
|
47
54
|
}
|
|
48
|
-
export function ActiveMarker({ cx, cy, fill, stroke }) {
|
|
55
|
+
export function ActiveMarker({ cx, cy, fill, stroke, variant = "default", }) {
|
|
49
56
|
const { enabled, transition } = use(MotionContext);
|
|
50
57
|
const { motionReady } = useLineInteraction();
|
|
51
58
|
const animate = enabled && motionReady;
|
|
@@ -53,7 +60,7 @@ export function ActiveMarker({ cx, cy, fill, stroke }) {
|
|
|
53
60
|
const y = useAnimatedCoordinate(cy ?? 0, animate, transition);
|
|
54
61
|
if (cx == null || cy == null)
|
|
55
62
|
return null;
|
|
56
|
-
return (_jsx(motion.circle, { "data-kind-ui": "active-marker", initial: false, cx: x, cy: y, r: 5, fill: fill ?? stroke, stroke: "var(--card, white)", strokeWidth: 2, strokeDasharray: "none", pointerEvents: "none" }));
|
|
63
|
+
return (_jsx(motion.circle, { "data-kind-ui": "active-marker", initial: false, cx: x, cy: y, r: 5, fill: fill ?? stroke, stroke: "var(--card, white)", strokeWidth: 2, strokeDasharray: "none", ...markerPaint(variant, fill ?? stroke), "data-point-style": variant, pointerEvents: "none" }));
|
|
57
64
|
}
|
|
58
65
|
export function LineSeries(props) {
|
|
59
66
|
const { enabled } = use(MotionContext);
|
|
@@ -87,7 +94,7 @@ export function LineSeries(props) {
|
|
|
87
94
|
});
|
|
88
95
|
return () => controls.stop();
|
|
89
96
|
}, [visible, enabled, opacity]);
|
|
90
|
-
return (_jsx(ZIndexLayer, { zIndex: props.zIndex ?? DefaultZIndexes.line, children: _jsx(motion.g, { initial: false, style: { opacity }, pointerEvents: visible ? undefined : "none", "aria-hidden": visible ? undefined : true, children: _jsx(StaticLineSeries, { ...props, activeDot: visible ? (props.activeDot ?? _jsx(ActiveMarker, {})) : false, zIndex: 0, renderWhileHidden: enabled && drawn, isAnimationActive: false }) }) }));
|
|
97
|
+
return (_jsx(ZIndexLayer, { zIndex: props.zIndex ?? DefaultZIndexes.line, children: _jsx(motion.g, { initial: false, style: { opacity }, pointerEvents: visible ? undefined : "none", "aria-hidden": visible ? undefined : true, children: _jsx(StaticLineSeries, { ...props, activeDot: visible ? (props.activeDot ?? _jsx(ActiveMarker, { variant: props.activePointStyle })) : false, zIndex: 0, renderWhileHidden: enabled && drawn, isAnimationActive: false }) }) }));
|
|
91
98
|
}
|
|
92
99
|
function MovingFrame({ x, y, maxX, maxY, ref, style, frameProps, children }) {
|
|
93
100
|
const { enabled, transition } = use(MotionContext);
|
|
@@ -100,3 +107,4 @@ function MovingFrame({ x, y, maxX, maxY, ref, style, frameProps, children }) {
|
|
|
100
107
|
export function Tooltip(props) {
|
|
101
108
|
return _jsx(TooltipBase, { ...props, Frame: MovingFrame });
|
|
102
109
|
}
|
|
110
|
+
registerPiePinComponent(Tooltip, "tooltip");
|
package/dist/area-chart.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { type LineAnimation } from "./animation.js";
|
|
|
4
4
|
export type AreaAnimation = LineAnimation;
|
|
5
5
|
export type AreaChartProps = ComponentProps<typeof EngineAreaChart> & {
|
|
6
6
|
animate?: boolean | AreaAnimation | undefined;
|
|
7
|
+
loading?: boolean | undefined;
|
|
8
|
+
loadingLabel?: string | undefined;
|
|
7
9
|
};
|
|
8
10
|
/** Native Recharts geometry and composition with a shared Motion entrance and tooltip. */
|
|
9
|
-
export declare function AreaChart({ animate, children, ...props }: AreaChartProps): import("react").JSX.Element;
|
|
11
|
+
export declare function AreaChart({ animate, loading, loadingLabel, children, ...props }: AreaChartProps): import("react").JSX.Element;
|
package/dist/area-chart.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { useCallback, useId, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { useCallback, useId, useLayoutEffect, useState, useSyncExternalStore, } from "react";
|
|
5
4
|
import { AreaChart as EngineAreaChart } from "recharts";
|
|
6
5
|
import { MotionContext } from "./animation.js";
|
|
7
6
|
import { LineChartFrame } from "./line-chart.js";
|
|
7
|
+
import { CartesianLoadingDesign } from "./loading-cartesian-designs.js";
|
|
8
|
+
import { RevealClip } from "./reveal-clip.js";
|
|
8
9
|
const defaultHover = { type: "spring", stiffness: 210, damping: 28, mass: 0.8 };
|
|
9
10
|
const query = "(prefers-reduced-motion: reduce)";
|
|
10
11
|
function subscribe(change) {
|
|
@@ -15,19 +16,23 @@ function subscribe(change) {
|
|
|
15
16
|
const snapshot = () => window.matchMedia(query).matches;
|
|
16
17
|
const serverSnapshot = () => true;
|
|
17
18
|
/** Native Recharts geometry and composition with a shared Motion entrance and tooltip. */
|
|
18
|
-
export function AreaChart({ animate = false, children, ...props }) {
|
|
19
|
+
export function AreaChart({ animate = false, loading, loadingLabel, children, ...props }) {
|
|
19
20
|
const id = useId();
|
|
20
21
|
const reduced = useSyncExternalStore(subscribe, snapshot, serverSnapshot);
|
|
21
22
|
const [interacted, setInteracted] = useState(false);
|
|
22
23
|
const options = typeof animate === "object" ? animate : {};
|
|
23
|
-
const enabled = animate !== false && reduced === false;
|
|
24
|
-
const interrupt = useCallback(() =>
|
|
24
|
+
const enabled = animate !== false && reduced === false && !loading;
|
|
25
|
+
const interrupt = useCallback(() => {
|
|
26
|
+
if (!loading)
|
|
27
|
+
setInteracted(true);
|
|
28
|
+
}, [loading]);
|
|
29
|
+
useLayoutEffect(() => {
|
|
30
|
+
if (loading)
|
|
31
|
+
setInteracted(false);
|
|
32
|
+
}, [loading]);
|
|
25
33
|
const reveal = enabled && !interacted;
|
|
26
|
-
return (_jsx(MotionContext, { value: { enabled, transition: options.hoverTransition ?? defaultHover }, children: _jsxs(LineChartFrame, { chartProps: {
|
|
34
|
+
return (_jsx(MotionContext, { value: { enabled, transition: options.hoverTransition ?? defaultHover }, children: _jsxs(LineChartFrame, { loading: loading, loadingLabel: loadingLabel, loadingSkeleton: "area", loadingDesign: (seed) => _jsx(CartesianLoadingDesign, { family: "area", seed: seed }), loadingAnimation: options, chartProps: {
|
|
27
35
|
...props,
|
|
28
36
|
className: ["kind-ui-area-chart", props.className].filter(Boolean).join(" "),
|
|
29
|
-
}, engine: EngineAreaChart, motionEnabled: enabled, interrupt: interrupt, ...(reveal ? { clip: `url(#${id}-area-reveal)` } : {}), children: [reveal && (_jsx(
|
|
30
|
-
duration: Math.max(0, options.revealDurationMs ?? 1000) / 1000,
|
|
31
|
-
ease: options.revealEasing ?? [0.25, 0.1, 0.25, 1],
|
|
32
|
-
} }) }) })), children] }) }));
|
|
37
|
+
}, engine: EngineAreaChart, motionEnabled: enabled, interrupt: interrupt, ...(reveal ? { clip: `url(#${id}-area-reveal)` } : {}), children: [reveal && (_jsx(RevealClip, { id: `${id}-area-reveal`, family: "area", options: options, finish: interrupt })), children] }) }));
|
|
33
38
|
}
|
package/dist/area-series.d.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { type ComponentProps } from "react";
|
|
2
2
|
import { Area } from "recharts";
|
|
3
3
|
import { type AreaMaterial } from "./area-material.js";
|
|
4
|
+
import { type FillPattern } from "./fill-pattern.js";
|
|
5
|
+
import { type PointStyle } from "./point-marker.js";
|
|
4
6
|
export type AreaSeriesProps<DataPoint = unknown, Value = unknown> = Omit<ComponentProps<typeof Area<DataPoint, Value>>, "isAnimationActive"> & {
|
|
5
7
|
/** Metadata/visibility key, required only for function or numeric data keys. */
|
|
6
8
|
seriesKey?: string;
|
|
9
|
+
/** Optional point paint; explicit native dot takes precedence. */
|
|
10
|
+
pointStyle?: PointStyle;
|
|
11
|
+
/** Independent active point paint; explicit native activeDot takes precedence. */
|
|
12
|
+
activePointStyle?: PointStyle;
|
|
7
13
|
/** Finish on the native area; explicit shape/filter retain consumer ownership. */
|
|
8
14
|
material?: AreaMaterial;
|
|
15
|
+
/** Static fill encoding; false opts out of configured patterns. Native paint/shape wins. */
|
|
16
|
+
pattern?: FillPattern | false | undefined;
|
|
9
17
|
};
|
|
10
18
|
/** A registered Recharts Area with Root colors and controlled visibility. */
|
|
11
|
-
export declare function AreaSeries<DataPoint = unknown, Value = unknown>({ seriesKey, material, hide, stroke, fill, className, ...props }: AreaSeriesProps<DataPoint, Value>): import("react").JSX.Element;
|
|
19
|
+
export declare function AreaSeries<DataPoint = unknown, Value = unknown>({ seriesKey, pointStyle, activePointStyle, material, pattern, hide, stroke, fill, className, ...props }: AreaSeriesProps<DataPoint, Value>): import("react").JSX.Element;
|
package/dist/area-series.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useId, useLayoutEffect, useRef } from "react";
|
|
4
|
-
import { Area } from "recharts";
|
|
4
|
+
import { Area, DefaultZIndexes, ZIndexLayer } from "recharts";
|
|
5
5
|
import { ActiveMarker } from "./animation.js";
|
|
6
6
|
import { MaterialArea } from "./area-material.js";
|
|
7
7
|
import { useChart } from "./chart-context.js";
|
|
8
|
+
import { FillPatternDefinition, patternResourceId } from "./fill-pattern.js";
|
|
8
9
|
import { useLineInteraction } from "./line-chart.js";
|
|
10
|
+
import { PointMarker } from "./point-marker.js";
|
|
11
|
+
import { SeriesInteractionLayer, useSeriesInteraction } from "./series-interaction.js";
|
|
9
12
|
/** A registered Recharts Area with Root colors and controlled visibility. */
|
|
10
|
-
export function AreaSeries({ seriesKey, material = "plain", hide, stroke, fill, className, ...props }) {
|
|
11
|
-
|
|
13
|
+
export function AreaSeries({ seriesKey, pointStyle = "default", activePointStyle = "default", material = "plain", pattern, hide, stroke, fill, className, ...props }) {
|
|
14
|
+
// Diagnose unsupported JavaScript/spread input without adding it to the public Area API.
|
|
15
|
+
const { dashAnimation, ...nativeProps } = props;
|
|
16
|
+
useLayoutEffect(() => {
|
|
17
|
+
if (dashAnimation !== undefined && process.env.NODE_ENV === "development")
|
|
18
|
+
console.warn("AreaSeries does not support dashAnimation. Remove it or use LineSeries with strokeDasharray for animated dashes.");
|
|
19
|
+
}, [dashAnimation]);
|
|
20
|
+
const { config, paints, visibleSeries } = useChart();
|
|
12
21
|
const { registerSeries, invalidate } = useLineInteraction();
|
|
13
22
|
const generatedId = useId();
|
|
14
23
|
const id = props.id || generatedId;
|
|
@@ -27,8 +36,26 @@ export function AreaSeries({ seriesKey, material = "plain", hide, stroke, fill,
|
|
|
27
36
|
}, [id, key, registerSeries]);
|
|
28
37
|
if (key === undefined && visibleSeries !== undefined)
|
|
29
38
|
throw new Error("AreaSeries requires seriesKey for controlled non-string dataKey");
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
const configuredPattern = key && Object.hasOwn(config, key) ? config[key]?.pattern : undefined;
|
|
40
|
+
const resolvedPattern = pattern === false ? undefined : (pattern ?? configuredPattern);
|
|
41
|
+
const patternId = patternResourceId(generatedId);
|
|
42
|
+
const patterned = resolvedPattern !== undefined &&
|
|
43
|
+
fill === undefined &&
|
|
44
|
+
props.style?.fill === undefined &&
|
|
45
|
+
props.shape === undefined;
|
|
46
|
+
const interaction = useSeriesInteraction(key, effectiveHide, hide === true, props.data, props.onClick);
|
|
47
|
+
const color = stroke ?? (key && Object.hasOwn(config, key) ? paints[key] : undefined);
|
|
48
|
+
return (_jsxs(_Fragment, { children: [patterned && (_jsx("defs", { pointerEvents: "none", children: _jsx(FillPatternDefinition, { id: patternId, pattern: resolvedPattern, baseColor: stroke ?? (key && Object.hasOwn(config, key) ? `var(--color-${key})` : "currentColor") }) })), _jsx(ZIndexLayer, { zIndex: props.zIndex ?? DefaultZIndexes.area, children: _jsx(SeriesInteractionLayer, { seriesKey: key, hidden: effectiveHide, children: _jsx(Area, { activeDot: _jsx(ActiveMarker, { variant: activePointStyle }), ...nativeProps, ...(props.dot === undefined && pointStyle !== "default"
|
|
49
|
+
? { dot: _jsx(PointMarker, { variant: pointStyle }) }
|
|
50
|
+
: {}), ...(interaction.onClick !== undefined ? { onClick: interaction.onClick } : {}), ...(material !== "plain" && props.shape === undefined && props.filter === undefined
|
|
51
|
+
? {
|
|
52
|
+
shape: (_jsx(MaterialArea, { material: material, filterId: `${generatedId}-area-material` })),
|
|
53
|
+
}
|
|
54
|
+
: {}), isAnimationActive: false, id: id, zIndex: 0, hide: effectiveHide, ...(color !== undefined ? { stroke: color } : {}), ...(fill !== undefined
|
|
55
|
+
? { fill }
|
|
56
|
+
: patterned
|
|
57
|
+
? { fill: `url(#${patternId})` }
|
|
58
|
+
: color !== undefined
|
|
59
|
+
? { fill: color }
|
|
60
|
+
: {}), className: ["kind-ui-area-series", className].filter(Boolean).join(" ") }) }) })] }));
|
|
34
61
|
}
|
package/dist/bar-chart.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type ComponentProps } from "react";
|
|
2
2
|
import { BarChart as EngineBarChart } from "recharts";
|
|
3
|
-
import { type
|
|
4
|
-
export type BarAnimation =
|
|
3
|
+
import { type BaseAnimation } from "./animation.js";
|
|
4
|
+
export type BarAnimation = BaseAnimation;
|
|
5
5
|
export type BarChartProps = ComponentProps<typeof EngineBarChart> & {
|
|
6
6
|
animate?: boolean | BarAnimation | undefined;
|
|
7
|
+
loading?: boolean | undefined;
|
|
8
|
+
loadingLabel?: string | undefined;
|
|
7
9
|
/** Opt in only for complete native category comparisons; any unsafe visible peer falls back. */
|
|
8
10
|
emphasis?: "none" | "category" | undefined;
|
|
9
11
|
};
|
|
@@ -14,4 +16,9 @@ export declare const BarMotion: import("react").Context<{
|
|
|
14
16
|
}>;
|
|
15
17
|
export declare function BarLifecycle({ layout, barGap, barCategoryGap, barSize, stackOffset, reverseStackOrder, }: BarChartProps): null;
|
|
16
18
|
/** Native Recharts composition with Kind interaction and optional Motion. */
|
|
17
|
-
export declare function
|
|
19
|
+
export declare function BarChartImplementation({ chartProps, family, }: {
|
|
20
|
+
chartProps: BarChartProps;
|
|
21
|
+
family: "bar" | "waterfall" | "histogram" | "box-plot";
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/** Native bar composition with a deterministic loading silhouette. */
|
|
24
|
+
export declare function BarChart(props: BarChartProps): import("react").JSX.Element;
|
package/dist/bar-chart.js
CHANGED
|
@@ -5,6 +5,7 @@ import { BarChart as EngineBarChart } from "recharts";
|
|
|
5
5
|
import { MotionContext } from "./animation.js";
|
|
6
6
|
import { BarCategoryBoundary } from "./bar-category.js";
|
|
7
7
|
import { LineChartFrame, useLineInteraction } from "./line-chart.js";
|
|
8
|
+
import { CartesianLoadingDesign } from "./loading-cartesian-designs.js";
|
|
8
9
|
export const BarMotion = createContext({
|
|
9
10
|
reveal: false,
|
|
10
11
|
options: {},
|
|
@@ -32,11 +33,23 @@ export function BarLifecycle({ layout, barGap, barCategoryGap, barSize, stackOff
|
|
|
32
33
|
return null;
|
|
33
34
|
}
|
|
34
35
|
/** Native Recharts composition with Kind interaction and optional Motion. */
|
|
35
|
-
export function
|
|
36
|
+
export function BarChartImplementation({ chartProps, family, }) {
|
|
37
|
+
const { animate = false, loading, loadingLabel, emphasis = "none", children, ...props } = chartProps;
|
|
36
38
|
const reduced = useSyncExternalStore(subscribe, snapshot, serverSnapshot);
|
|
37
39
|
const [interacted, setInteracted] = useState(false);
|
|
38
|
-
const finish = useCallback(() =>
|
|
39
|
-
|
|
40
|
+
const finish = useCallback(() => {
|
|
41
|
+
if (!loading)
|
|
42
|
+
setInteracted(true);
|
|
43
|
+
}, [loading]);
|
|
44
|
+
useLayoutEffect(() => {
|
|
45
|
+
if (loading)
|
|
46
|
+
setInteracted(false);
|
|
47
|
+
}, [loading]);
|
|
48
|
+
const enabled = animate !== false && !reduced && !loading;
|
|
40
49
|
const options = typeof animate === "object" ? animate : {};
|
|
41
|
-
return (_jsx(MotionContext, { value: { enabled, transition: options.hoverTransition ?? defaultHover }, children: _jsx(BarMotion, { value: { reveal: enabled && !interacted, options, finish }, children: _jsx(BarCategoryBoundary, { children: _jsxs(LineChartFrame, { chartProps: props, categoryEmphasis: emphasis === "category", engine: EngineBarChart, motionEnabled: enabled, interrupt: finish, children: [_jsx(BarLifecycle, { ...props }), children] }) }) }) }));
|
|
50
|
+
return (_jsx(MotionContext, { value: { enabled, transition: options.hoverTransition ?? defaultHover }, children: _jsx(BarMotion, { value: { reveal: enabled && !interacted, options, finish }, children: _jsx(BarCategoryBoundary, { children: _jsxs(LineChartFrame, { chartProps: props, loadingSkeleton: family, loadingDesign: (seed) => _jsx(CartesianLoadingDesign, { family: family, seed: seed }), loadingAnimation: { ...options, ...(props.layout ? { layout: props.layout } : {}) }, loading: loading, loadingLabel: loadingLabel, categoryEmphasis: emphasis === "category", engine: EngineBarChart, motionEnabled: enabled, interrupt: finish, children: [_jsx(BarLifecycle, { ...props }), children] }) }) }) }));
|
|
51
|
+
}
|
|
52
|
+
/** Native bar composition with a deterministic loading silhouette. */
|
|
53
|
+
export function BarChart(props) {
|
|
54
|
+
return _jsx(BarChartImplementation, { chartProps: props, family: "bar" });
|
|
42
55
|
}
|
package/dist/bar-material.js
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { cloneElement } from "react";
|
|
4
4
|
import { BarClay } from "./bar-clay.js";
|
|
5
|
-
import { BarPaper } from "./bar-paper.js";
|
|
6
5
|
import { SurfaceMaterialFilter } from "./surface-material.js";
|
|
7
6
|
/** Native rectangles apply this filter independently to their own object bounds. */
|
|
8
7
|
export function BarMaterialFilter({ material, id, horizontal, }) {
|
|
9
|
-
if (material
|
|
10
|
-
return (_jsx("filter", { id: id, filterUnits: "objectBoundingBox", primitiveUnits: "userSpaceOnUse", x: -0.5, y: -0.5, width: 2, height: 2, colorInterpolationFilters: "sRGB", children:
|
|
8
|
+
if (material === "clay")
|
|
9
|
+
return (_jsx("filter", { id: id, filterUnits: "objectBoundingBox", primitiveUnits: "userSpaceOnUse", x: -0.5, y: -0.5, width: 2, height: 2, colorInterpolationFilters: "sRGB", children: _jsx(BarClay, { horizontal: horizontal }) }));
|
|
11
10
|
// The shared pure helper returns a native filter. Only bar coordinate units change;
|
|
12
11
|
// pixel-sized primitives and the area's user-space bounds retain their semantics.
|
|
13
12
|
return cloneElement(SurfaceMaterialFilter({
|
package/dist/bar-series.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type ComponentProps } from "react";
|
|
2
2
|
import { Bar } from "recharts";
|
|
3
3
|
import { type BarMaterial } from "./bar-material.js";
|
|
4
|
+
import { type FillPattern } from "./fill-pattern.js";
|
|
5
|
+
/** Caller-owned identity selection; this component never computes forecast values. */
|
|
6
|
+
export type BarProjection<DataPoint> = {
|
|
7
|
+
isProjected: (datum: DataPoint) => boolean;
|
|
8
|
+
pattern: FillPattern;
|
|
9
|
+
};
|
|
4
10
|
export type BarSeriesProps<DataPoint = unknown, Value = unknown> = Omit<ComponentProps<typeof Bar<DataPoint, Value>>, "isAnimationActive"> & {
|
|
5
11
|
/** Metadata/visibility key, required for controlled function or numeric data keys. */
|
|
6
12
|
seriesKey?: string;
|
|
@@ -8,6 +14,10 @@ export type BarSeriesProps<DataPoint = unknown, Value = unknown> = Omit<Componen
|
|
|
8
14
|
emphasisKey?: ((payload: unknown) => string | number | undefined) | undefined;
|
|
9
15
|
/** Finish on native rectangles; custom shapes and filters retain ownership. */
|
|
10
16
|
material?: BarMaterial | undefined;
|
|
17
|
+
/** Static encoding for implicit fills; explicit fills/Cells/custom shapes retain ownership. */
|
|
18
|
+
pattern?: FillPattern | false | undefined;
|
|
19
|
+
/** Pattern selected rows; selection remains caller-owned. */
|
|
20
|
+
projection?: BarProjection<DataPoint> | undefined;
|
|
11
21
|
};
|
|
12
22
|
/** A registered native Bar; axes, shape, cells, labels and handlers stay consumer-owned. */
|
|
13
|
-
export declare function BarSeries<DataPoint = unknown, Value = unknown>({ seriesKey, emphasisKey, hide, fill, className, style, material, ...props }: BarSeriesProps<DataPoint, Value>): import("react").JSX.Element;
|
|
23
|
+
export declare function BarSeries<DataPoint = unknown, Value = unknown>({ seriesKey, emphasisKey, hide, fill, className, style, material, pattern, projection, children, ...props }: BarSeriesProps<DataPoint, Value>): import("react").JSX.Element;
|
package/dist/bar-series.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { motion } from "motion/react";
|
|
4
|
-
import { use, useCallback, useId, useLayoutEffect, useRef } from "react";
|
|
5
|
-
import { Bar, Rectangle, useActiveTooltipDataPoints, useActiveTooltipLabel, useChartLayout, useIsTooltipActive, usePlotArea, useXAxisDomain, useXAxisScale, useYAxisDomain, useYAxisScale, } from "recharts";
|
|
4
|
+
import { Children, isValidElement, use, useCallback, useId, useLayoutEffect, useRef, } from "react";
|
|
5
|
+
import { Bar, Cell, DefaultZIndexes, Rectangle, useActiveTooltipDataPoints, useActiveTooltipLabel, useChartLayout, useIsTooltipActive, usePlotArea, useXAxisDomain, useXAxisScale, useYAxisDomain, useYAxisScale, ZIndexLayer, } from "recharts";
|
|
6
6
|
import { useBarCategoryHover } from "./bar-category.js";
|
|
7
7
|
import { BarMotion } from "./bar-chart.js";
|
|
8
8
|
import { BarMaterialFilter } from "./bar-material.js";
|
|
9
9
|
import { useChart } from "./chart-context.js";
|
|
10
10
|
import { useEmphasis } from "./emphasis.js";
|
|
11
|
+
import { FillPatternDefinition, patternResourceId } from "./fill-pattern.js";
|
|
11
12
|
import { useChartKeyboard, useLineInteraction } from "./line-chart.js";
|
|
13
|
+
import { SeriesInteractionLayer, useSeriesInteraction } from "./series-interaction.js";
|
|
12
14
|
/** A registered native Bar; axes, shape, cells, labels and handlers stay consumer-owned. */
|
|
13
|
-
export function BarSeries({ seriesKey, emphasisKey, hide, fill, className, style, material = "plain", ...props }) {
|
|
14
|
-
const { config, visibleSeries } = useChart();
|
|
15
|
+
export function BarSeries({ seriesKey, emphasisKey, hide, fill, className, style, material = "plain", pattern, projection, children, ...props }) {
|
|
16
|
+
const { config, paints, visibleSeries } = useChart();
|
|
15
17
|
const { registerSeries, invalidate, data, categoryEmphasis, registerCategoryEligibility } = useLineInteraction();
|
|
16
18
|
const { reveal, options, finish } = use(BarMotion);
|
|
17
19
|
const generatedId = useId();
|
|
@@ -102,7 +104,28 @@ export function BarSeries({ seriesKey, emphasisKey, hide, fill, className, style
|
|
|
102
104
|
}, [id, key, registerSeries]);
|
|
103
105
|
if (key === undefined && visibleSeries !== undefined)
|
|
104
106
|
throw new Error("BarSeries requires seriesKey for controlled non-string dataKey");
|
|
105
|
-
const
|
|
107
|
+
const configuredPattern = key && Object.hasOwn(config, key) ? config[key]?.pattern : undefined;
|
|
108
|
+
const resolvedPattern = pattern === false ? undefined : (pattern ?? configuredPattern);
|
|
109
|
+
const patternId = patternResourceId(generatedId);
|
|
110
|
+
const patterned = resolvedPattern !== undefined &&
|
|
111
|
+
fill === undefined &&
|
|
112
|
+
style?.fill === undefined &&
|
|
113
|
+
props.shape === undefined &&
|
|
114
|
+
(props.activeBar === undefined || typeof props.activeBar === "boolean");
|
|
115
|
+
const interaction = useSeriesInteraction(key, effectiveHide, hide === true, undefined, props.onClick);
|
|
116
|
+
const projectionId = `${patternId}-projection`;
|
|
117
|
+
// Explicit Cell composition owns per-datum paint, including nested native Cells.
|
|
118
|
+
// Do not override consumer Cells or flatten their markup.
|
|
119
|
+
const hasCells = (nodes) => Children.toArray(nodes).some((node) => isValidElement(node) &&
|
|
120
|
+
(node.type === Cell || hasCells(node.props.children)));
|
|
121
|
+
const projectionPaint = projection !== undefined &&
|
|
122
|
+
pattern !== false &&
|
|
123
|
+
fill === undefined &&
|
|
124
|
+
style?.fill === undefined &&
|
|
125
|
+
props.shape === undefined &&
|
|
126
|
+
(props.activeBar === undefined || typeof props.activeBar === "boolean") &&
|
|
127
|
+
!hasCells(children);
|
|
128
|
+
const color = fill ?? (key && Object.hasOwn(config, key) ? paints[key] : undefined);
|
|
106
129
|
const nativeRows = (!("data" in props) &&
|
|
107
130
|
data?.every((row) => {
|
|
108
131
|
if (typeof props.dataKey !== "string" ||
|
|
@@ -130,18 +153,47 @@ export function BarSeries({ seriesKey, emphasisKey, hide, fill, className, style
|
|
|
130
153
|
props.shape === undefined &&
|
|
131
154
|
(props.activeBar === undefined || typeof props.activeBar === "boolean");
|
|
132
155
|
useLayoutEffect(() => registerCategoryEligibility(id, eligible, effectiveHide), [id, eligible, effectiveHide, registerCategoryEligibility]);
|
|
133
|
-
const categoryShape = useCallback((shapeProps) =>
|
|
156
|
+
const categoryShape = useCallback((shapeProps) => {
|
|
157
|
+
// Select the actual displayed payload, not the Cell index: native Brush
|
|
158
|
+
// slices and missing-value filtering must not shift projection identity.
|
|
159
|
+
const datum = shapeProps.payload;
|
|
160
|
+
const datumPaint = typeof datum === "object" && datum !== null
|
|
161
|
+
? datum
|
|
162
|
+
: undefined;
|
|
163
|
+
const projected = projectionPaint &&
|
|
164
|
+
datum != null &&
|
|
165
|
+
projection.isProjected(datum) &&
|
|
166
|
+
datumPaint?.fill === undefined &&
|
|
167
|
+
datumPaint?.style?.fill === undefined;
|
|
168
|
+
const nativeProps = projected ? { ...shapeProps, fill: `url(#${projectionId})` } : shapeProps;
|
|
169
|
+
return categoryEmphasis && eligible ? (_jsx(CategoryBar, { ...nativeProps, seriesKey: key, emphasisKey: emphasisKey, axisId: horizontal ? props.yAxisId : props.xAxisId })) : (_jsx(Rectangle, { ...nativeProps }));
|
|
170
|
+
}, [
|
|
171
|
+
key,
|
|
172
|
+
emphasisKey,
|
|
173
|
+
horizontal,
|
|
174
|
+
props.xAxisId,
|
|
175
|
+
props.yAxisId,
|
|
176
|
+
projectionPaint,
|
|
177
|
+
projection,
|
|
178
|
+
projectionId,
|
|
179
|
+
categoryEmphasis,
|
|
180
|
+
eligible,
|
|
181
|
+
]);
|
|
134
182
|
const clipped = reveal && !effectiveHide && usablePlot;
|
|
135
183
|
return (_jsxs(_Fragment, { children: [_jsx("style", { children: `.${selector} { --kind-ui-bar-clip: ${clipped ? `url(#${clipId})` : "none"}; }` }), clipped && (_jsx("defs", { children: _jsx("clipPath", { id: clipId, clipPathUnits: "userSpaceOnUse", children: _jsx(motion.rect, { "data-kind-ui": "bar-reveal", initial: horizontal
|
|
136
184
|
? { x: zero, y: area.y, width: 0, height: area.height }
|
|
137
185
|
: { x: area.x, y: zero, height: 0, width: area.width }, animate: { x: area.x, y: area.y, width: area.width, height: area.height }, transition: {
|
|
138
186
|
duration: Math.max(0, options.revealDurationMs ?? 1000) / 1000,
|
|
139
187
|
ease: options.revealEasing ?? [0.25, 0.1, 0.25, 1],
|
|
140
|
-
}, onAnimationComplete: finish }, geometry) }) })), materialized && (_jsx("defs", { "data-kind-ui": "bar-material", "data-material": material, pointerEvents: "none", children: _jsx(BarMaterialFilter, { material: material, id: filterId, horizontal: horizontal }) })), _jsx(Bar, { ...props, ...(categoryEmphasis && eligible
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
188
|
+
}, onAnimationComplete: finish }, geometry) }) })), patterned && (_jsx("defs", { pointerEvents: "none", children: _jsx(FillPatternDefinition, { id: patternId, pattern: resolvedPattern, baseColor: key && Object.hasOwn(config, key) ? `var(--color-${key})` : (color ?? "currentColor") }) })), projectionPaint && (_jsx("defs", { pointerEvents: "none", children: _jsx(FillPatternDefinition, { id: projectionId, pattern: projection.pattern, baseColor: key && Object.hasOwn(config, key) ? `var(--color-${key})` : (color ?? "currentColor") }) })), materialized && (_jsx("defs", { "data-kind-ui": "bar-material", "data-material": material, pointerEvents: "none", children: _jsx(BarMaterialFilter, { material: material, id: filterId, horizontal: horizontal }) })), _jsx(ZIndexLayer, { zIndex: props.zIndex ?? DefaultZIndexes.bar, children: _jsx(SeriesInteractionLayer, { seriesKey: key, hidden: effectiveHide, children: _jsx(Bar, { ...props, ...(interaction.onClick !== undefined ? { onClick: interaction.onClick } : {}), ...(projectionPaint || (categoryEmphasis && eligible)
|
|
189
|
+
? {
|
|
190
|
+
shape: categoryShape,
|
|
191
|
+
}
|
|
192
|
+
: {}), ...(materialized ? { filter: `url(#${filterId})` } : {}), id: id, zIndex: 0, hide: effectiveHide, ...(patterned
|
|
193
|
+
? { fill: `url(#${patternId})` }
|
|
194
|
+
: color !== undefined
|
|
195
|
+
? { fill: color }
|
|
196
|
+
: {}), className: ["kind-ui-bar-series", selector, className].filter(Boolean).join(" "), style: style, isAnimationActive: false, children: children }) }) })] }));
|
|
145
197
|
}
|
|
146
198
|
function CategoryBar({ seriesKey, emphasisKey, axisId, ...props }) {
|
|
147
199
|
const { emphasisScope, pointer } = useLineInteraction();
|
|
@@ -163,7 +215,7 @@ function CategoryBar({ seriesKey, emphasisKey, axisId, ...props }) {
|
|
|
163
215
|
key: String(semantic),
|
|
164
216
|
scope: `${emphasisScope}/${String(axisId ?? 0)}`,
|
|
165
217
|
seriesKey,
|
|
166
|
-
}, eligible);
|
|
218
|
+
}, eligible, false);
|
|
167
219
|
// Native axis inspection owns the category, including whitespace above and between bars.
|
|
168
220
|
// A painted mark's leave must not clear a category while the cursor remains in its band.
|
|
169
221
|
useLayoutEffect(() => {
|
|
@@ -174,5 +226,5 @@ function CategoryBar({ seriesKey, emphasisKey, axisId, ...props }) {
|
|
|
174
226
|
else if (!hover || (pointer && !active))
|
|
175
227
|
emphasis.leave("pointer");
|
|
176
228
|
}, [active, keyboard, pointer, hover, emphasis.enter, emphasis.leave]);
|
|
177
|
-
return (_jsx("g", { "data-kind-ui": "emphasis-mark", "data-emphasis": emphasis.dimmed ? "dimmed" : "baseline", children: _jsx("g", { "data-kind-ui": "emphasis-paint", style: { opacity: emphasis.factor }, children: _jsx(Rectangle, { ...props }) }) }));
|
|
229
|
+
return (_jsx("g", { "data-kind-ui": "emphasis-mark", "data-emphasis": emphasis.dimmed ? "dimmed" : "baseline", children: _jsx("g", { "data-kind-ui": "emphasis-paint", style: { opacity: emphasis.active?.kind === "series" ? 1 : emphasis.factor }, children: _jsx(Rectangle, { ...props }) }) }));
|
|
178
230
|
}
|
package/dist/box-plot.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
4
4
|
import { useChartLayout, useXAxisScale, useYAxisScale } from "recharts";
|
|
5
|
-
import {
|
|
5
|
+
import { BarChartImplementation } from "./bar-chart.js";
|
|
6
6
|
import { BarSeries } from "./bar-series.js";
|
|
7
7
|
import { BoxMaterialFilter } from "./box-material.js";
|
|
8
8
|
const fields = ["lowerWhisker", "q1", "median", "q3", "upperWhisker"];
|
|
@@ -48,7 +48,7 @@ export function boxPlotExtent(summary) {
|
|
|
48
48
|
}
|
|
49
49
|
/** Public Bar composition; Recharts owns axes, layout, domains and keyboard selection. */
|
|
50
50
|
export function BoxPlotChart(props) {
|
|
51
|
-
return _jsx(
|
|
51
|
+
return _jsx(BarChartImplementation, { chartProps: props, family: "box-plot" });
|
|
52
52
|
}
|
|
53
53
|
/** A reusable SVG mark. Zero IQR remains a line; no minimum numeric extent is invented. */
|
|
54
54
|
export function BoxPlotMark({ coordinates: c, center, size, orientation = "vertical", outlierRadius = 3, strokeWidth = 1.5, material = "plain", ...props }) {
|
package/dist/category-cells.d.ts
CHANGED
|
@@ -3,4 +3,10 @@ import type { SeriesConfig } from "./types.js";
|
|
|
3
3
|
/** Category identity is an own field or an accessor, never an array position. */
|
|
4
4
|
export type CategoryKey<Row> = (keyof Row & string) | ((row: Row) => string);
|
|
5
5
|
/** Only Pie and Radial category mode use this native Cell defaulting seam. */
|
|
6
|
-
export declare function categoryCells<Row>(data: readonly Row[] | undefined, categoryKey: CategoryKey<Row>, config: SeriesConfig, children: ReactNode, fill: string | undefined): ReactNode;
|
|
6
|
+
export declare function categoryCells<Row>(data: readonly Row[] | undefined, categoryKey: CategoryKey<Row>, config: SeriesConfig, paints: Readonly<Record<string, string>>, children: ReactNode, fill: string | undefined): ReactNode;
|
|
7
|
+
/** Filter original rows and positional Cells together before native geometry is computed. */
|
|
8
|
+
export declare function filterCategoryRows<Row>(data: readonly Row[], categoryKey: CategoryKey<Row>, visible: readonly string[] | undefined, children: ReactNode): {
|
|
9
|
+
data: Row[];
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
keyOf: (row: Row) => string;
|
|
12
|
+
};
|