@kind-ui/charts 0.1.1 → 0.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 +26 -0
- package/README.md +674 -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-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 +3 -1
- package/dist/heatmap.js +34 -12
- package/dist/histogram-chart.js +10 -3
- 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-series.d.ts +9 -1
- package/dist/line-series.js +38 -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-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 +137 -14
- 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-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-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-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 -1
- package/dist/stylesheet-warning.d.ts +2 -0
- package/dist/stylesheet-warning.js +86 -0
- 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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type ChartBackgroundPatternRenderProps = {
|
|
3
|
+
size: number;
|
|
4
|
+
color: string;
|
|
5
|
+
/** Scope any custom SVG resources with this prefix; never use global IDs. */
|
|
6
|
+
idPrefix: string;
|
|
7
|
+
};
|
|
8
|
+
export type ChartBackgroundPatternDefinition = Readonly<{
|
|
9
|
+
render: (props: ChartBackgroundPatternRenderProps) => ReactNode;
|
|
10
|
+
}>;
|
|
11
|
+
/** Register a reusable, consumer-owned definition without mutating global state. */
|
|
12
|
+
export declare function defineChartBackgroundPattern(render: ChartBackgroundPatternDefinition["render"]): ChartBackgroundPatternDefinition;
|
|
13
|
+
export type ChartBackgroundPatternProps = {
|
|
14
|
+
pattern: "pinpoints" | "crossings" | "waves" | ChartBackgroundPatternDefinition;
|
|
15
|
+
/** CSS paint, including variables/system colors. Defaults to the chart grid token. */
|
|
16
|
+
color?: string;
|
|
17
|
+
/** Opacity in [0, 1], default 0.15. */
|
|
18
|
+
opacity?: number;
|
|
19
|
+
/** Positive tile size in SVG user units, default 16; does not stretch on resize. */
|
|
20
|
+
size?: number;
|
|
21
|
+
};
|
|
22
|
+
/** Decorative plot chrome, independent of series paint and interactions. */
|
|
23
|
+
export declare function ChartBackgroundPattern({ pattern, color, opacity, size, }: ChartBackgroundPatternProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { DefaultZIndexes, usePlotArea, ZIndexLayer } from "recharts";
|
|
5
|
+
/** Register a reusable, consumer-owned definition without mutating global state. */
|
|
6
|
+
export function defineChartBackgroundPattern(render) {
|
|
7
|
+
if (typeof render !== "function")
|
|
8
|
+
throw new Error("defineChartBackgroundPattern requires a render function");
|
|
9
|
+
return Object.freeze({ render });
|
|
10
|
+
}
|
|
11
|
+
/** Decorative plot chrome, independent of series paint and interactions. */
|
|
12
|
+
export function ChartBackgroundPattern({ pattern, color = "var(--kind-ui-chart-grid, CanvasText)", opacity = 0.15, size = 16, }) {
|
|
13
|
+
const area = usePlotArea();
|
|
14
|
+
const identity = useId();
|
|
15
|
+
const encodedId = Array.from(identity, (char) => char.codePointAt(0)?.toString(16)).join("-");
|
|
16
|
+
const id = `kind-ui-background-${encodedId}`;
|
|
17
|
+
if (!Number.isFinite(size) ||
|
|
18
|
+
size <= 0 ||
|
|
19
|
+
!Number.isFinite(opacity) ||
|
|
20
|
+
opacity < 0 ||
|
|
21
|
+
opacity > 1)
|
|
22
|
+
throw new Error("ChartBackgroundPattern requires positive finite size and opacity in [0, 1]");
|
|
23
|
+
if (typeof pattern === "string"
|
|
24
|
+
? !["pinpoints", "crossings", "waves"].includes(pattern)
|
|
25
|
+
: !pattern || typeof pattern.render !== "function")
|
|
26
|
+
throw new Error("ChartBackgroundPattern requires a preset or a custom definition");
|
|
27
|
+
if (!area || area.width <= 0 || area.height <= 0)
|
|
28
|
+
return null;
|
|
29
|
+
const tile = typeof pattern !== "string" ? (pattern.render({ size, color, idPrefix: `${id}-custom` })) : pattern === "pinpoints" ? (_jsx("circle", { cx: size / 2, cy: size / 2, r: size / 16, fill: color })) : pattern === "crossings" ? (_jsx("path", { d: `M${size / 2} ${size / 4}v${size / 2} M${size / 4} ${size / 2}h${size / 2}`, stroke: color, fill: "none" })) : (_jsx("path", { d: `M0 ${size / 2}Q${size / 4} 0 ${size / 2} ${size / 2}T${size} ${size / 2}`, stroke: color, fill: "none" }));
|
|
30
|
+
return (_jsx(ZIndexLayer, { zIndex: DefaultZIndexes.grid - 1, children: _jsxs("g", { "data-kind-ui": "chart-background-pattern", "aria-hidden": "true", focusable: "false", pointerEvents: "none", clipPath: `url(#${id}-clip)`, opacity: opacity, children: [_jsxs("defs", { children: [_jsx("clipPath", { id: `${id}-clip`, children: _jsx("rect", { x: area.x, y: area.y, width: area.width, height: area.height }) }), _jsx("pattern", { id: id, x: area.x, y: area.y, width: size, height: size, patternUnits: "userSpaceOnUse", children: tile })] }), _jsx("rect", { x: area.x, y: area.y, width: area.width, height: area.height, fill: `url(#${id})` })] }) }));
|
|
31
|
+
}
|
package/dist/chart-context.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ColorStops } from "./series-color.js";
|
|
2
|
+
import type { ResolvedSeriesConfig } from "./series-label.js";
|
|
2
3
|
type Visibility = {
|
|
3
4
|
visibleSeries?: readonly string[];
|
|
4
5
|
onVisibleSeriesChange?: (next: string[]) => void;
|
|
5
6
|
};
|
|
6
7
|
export type ChartContextValue = Visibility & {
|
|
7
|
-
config:
|
|
8
|
+
config: ResolvedSeriesConfig;
|
|
9
|
+
colorId: string;
|
|
10
|
+
colorStops: Readonly<Record<string, ColorStops>>;
|
|
11
|
+
paints: Readonly<Record<string, string>>;
|
|
8
12
|
};
|
|
9
13
|
export declare const ChartContext: import("react").Context<ChartContextValue | null>;
|
|
10
14
|
export declare function useChart(): ChartContextValue;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type ReactNode, type SyntheticEvent } from "react";
|
|
2
|
+
import type { SeriesConfig } from "./types.js";
|
|
3
|
+
export type ChartIdentity = {
|
|
4
|
+
kind: "series" | "category" | "node";
|
|
5
|
+
key: string;
|
|
6
|
+
};
|
|
7
|
+
export type ChartInteractionEvent = SyntheticEvent<Element> | null;
|
|
8
|
+
export type ChartInteractionRequest = {
|
|
9
|
+
identity: ChartIdentity | null;
|
|
10
|
+
source: "legend" | "mark" | "reset";
|
|
11
|
+
mode: "visibility" | "focus";
|
|
12
|
+
event: ChartInteractionEvent;
|
|
13
|
+
};
|
|
14
|
+
export type ChartInteractionConfig = {
|
|
15
|
+
/** Explicit binding between this Root's legend and participating chart identities. */
|
|
16
|
+
markActivation?: "none" | "matching-legend";
|
|
17
|
+
/** Settled data identities, including hidden items and zero values. */
|
|
18
|
+
eligibleKeys: readonly string[];
|
|
19
|
+
onBeforeInteraction?: (request: ChartInteractionRequest) => boolean | void;
|
|
20
|
+
} & ({
|
|
21
|
+
kind: "series" | "category";
|
|
22
|
+
mode?: "visibility";
|
|
23
|
+
selected?: never;
|
|
24
|
+
defaultSelected?: never;
|
|
25
|
+
onSelectionChange?: never;
|
|
26
|
+
} | ({
|
|
27
|
+
kind: "series" | "category" | "node";
|
|
28
|
+
mode: "focus";
|
|
29
|
+
} & ({
|
|
30
|
+
selected?: undefined;
|
|
31
|
+
defaultSelected?: string | null;
|
|
32
|
+
onSelectionChange?: (next: string | null) => void;
|
|
33
|
+
} | {
|
|
34
|
+
selected: string | null;
|
|
35
|
+
defaultSelected?: never;
|
|
36
|
+
onSelectionChange: (next: string | null) => void;
|
|
37
|
+
})));
|
|
38
|
+
export type ChartVisibilityProps = {
|
|
39
|
+
visibleSeries?: undefined;
|
|
40
|
+
defaultVisibleSeries?: undefined;
|
|
41
|
+
onVisibleSeriesChange?: never;
|
|
42
|
+
} | {
|
|
43
|
+
visibleSeries?: undefined;
|
|
44
|
+
defaultVisibleSeries: readonly string[];
|
|
45
|
+
onVisibleSeriesChange?: (next: string[]) => void;
|
|
46
|
+
} | {
|
|
47
|
+
visibleSeries: readonly string[];
|
|
48
|
+
defaultVisibleSeries?: never;
|
|
49
|
+
onVisibleSeriesChange?: (next: string[]) => void;
|
|
50
|
+
};
|
|
51
|
+
type Interaction = {
|
|
52
|
+
configured: boolean;
|
|
53
|
+
mode: "visibility" | "focus";
|
|
54
|
+
kind: ChartIdentity["kind"];
|
|
55
|
+
markActivation: boolean;
|
|
56
|
+
interactive: boolean;
|
|
57
|
+
selected: string | null;
|
|
58
|
+
eligible: readonly string[];
|
|
59
|
+
visible: readonly string[] | undefined;
|
|
60
|
+
activate: (identity: ChartIdentity, source: "legend" | "mark", event?: ChartInteractionEvent) => boolean;
|
|
61
|
+
reset: (event?: ChartInteractionEvent) => boolean;
|
|
62
|
+
announcement: {
|
|
63
|
+
text: string;
|
|
64
|
+
sequence: number;
|
|
65
|
+
};
|
|
66
|
+
registerUnavailable: (owner: string, key: string | undefined, unavailable: boolean) => () => void;
|
|
67
|
+
register: (owner: string, keys: readonly string[]) => () => void;
|
|
68
|
+
};
|
|
69
|
+
export declare function useOptionalChartInteraction(): Interaction | null;
|
|
70
|
+
export declare function useChartInteraction(): {
|
|
71
|
+
reset: (event?: ChartInteractionEvent) => boolean;
|
|
72
|
+
configured: boolean;
|
|
73
|
+
mode: "visibility" | "focus";
|
|
74
|
+
kind: ChartIdentity["kind"];
|
|
75
|
+
markActivation: boolean;
|
|
76
|
+
interactive: boolean;
|
|
77
|
+
selected: string | null;
|
|
78
|
+
eligible: readonly string[];
|
|
79
|
+
visible: readonly string[] | undefined;
|
|
80
|
+
activate: (identity: ChartIdentity, source: "legend" | "mark", event?: ChartInteractionEvent) => boolean;
|
|
81
|
+
};
|
|
82
|
+
export declare function ChartInteractionProvider({ config, children, ...props }: {
|
|
83
|
+
interaction?: ChartInteractionConfig;
|
|
84
|
+
} & ChartVisibilityProps & {
|
|
85
|
+
config: SeriesConfig;
|
|
86
|
+
children: (visible: readonly string[] | undefined, change: ((next: string[]) => void) | undefined) => ReactNode;
|
|
87
|
+
}): import("react").JSX.Element;
|
|
88
|
+
export declare function ChartInteractionStatus(): import("react").JSX.Element;
|
|
89
|
+
/** Native series registration preserves hidden eligibility; callers may supply a stricter snapshot. */
|
|
90
|
+
export declare function useInteractionRegistration(keys: readonly string[]): void;
|
|
91
|
+
export declare function useInteractionAvailability(key: string | undefined, unavailable: boolean): void;
|
|
92
|
+
/** Retain the focused data identity when native layout replaces a sector node. */
|
|
93
|
+
export declare function useInteractionFocus(key: string | undefined, enabled: boolean): (node: SVGGElement | null) => void;
|
|
94
|
+
export {};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { useOptionalEmphasisActions } from "./emphasis.js";
|
|
5
|
+
const Context = createContext(null);
|
|
6
|
+
/** The single state/action owner shared by native adapters and custom controls. */
|
|
7
|
+
function useInteractionOwner() {
|
|
8
|
+
const value = use(Context);
|
|
9
|
+
if (!value)
|
|
10
|
+
throw new Error("useChartInteraction requires Root");
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
export function useOptionalChartInteraction() {
|
|
14
|
+
return use(Context);
|
|
15
|
+
}
|
|
16
|
+
export function useChartInteraction() {
|
|
17
|
+
const { register: _register, registerUnavailable: _registerUnavailable, announcement: _announcement, ...publicValue } = useInteractionOwner();
|
|
18
|
+
const emphasis = useOptionalEmphasisActions();
|
|
19
|
+
return {
|
|
20
|
+
...publicValue,
|
|
21
|
+
reset: (event = null) => {
|
|
22
|
+
if (!publicValue.reset(event))
|
|
23
|
+
return false;
|
|
24
|
+
emphasis?.reset();
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function ChartInteractionProvider({ config, children, ...props }) {
|
|
30
|
+
const options = props.interaction;
|
|
31
|
+
const mode = options?.mode ?? "visibility";
|
|
32
|
+
const kind = options?.kind ?? "series";
|
|
33
|
+
const controlled = options?.selected;
|
|
34
|
+
const onChange = options?.onSelectionChange;
|
|
35
|
+
const initial = options?.defaultSelected;
|
|
36
|
+
const [internal, setInternal] = useState(initial ?? null);
|
|
37
|
+
const [internalVisible, setInternalVisible] = useState(props.defaultVisibleSeries);
|
|
38
|
+
const [unavailable, setUnavailable] = useState(() => new Map());
|
|
39
|
+
const registerUnavailable = useCallback((owner, key, blocked) => {
|
|
40
|
+
setUnavailable((old) => {
|
|
41
|
+
const next = new Map(old);
|
|
42
|
+
if (key !== undefined)
|
|
43
|
+
next.set(owner, { key, unavailable: blocked });
|
|
44
|
+
else
|
|
45
|
+
next.delete(owner);
|
|
46
|
+
return JSON.stringify([...old]) === JSON.stringify([...next]) ? old : next;
|
|
47
|
+
});
|
|
48
|
+
return () => setUnavailable((old) => {
|
|
49
|
+
if (!old.has(owner))
|
|
50
|
+
return old;
|
|
51
|
+
const next = new Map(old);
|
|
52
|
+
next.delete(owner);
|
|
53
|
+
return next;
|
|
54
|
+
});
|
|
55
|
+
}, []);
|
|
56
|
+
const [registrations, setRegistrations] = useState(() => new Map());
|
|
57
|
+
const [announcement, setAnnouncement] = useState({ text: "", sequence: 0 });
|
|
58
|
+
const ownership = useRef(mode === "focus" ? controlled !== undefined : undefined);
|
|
59
|
+
if (mode === "focus" && ownership.current === undefined)
|
|
60
|
+
ownership.current = controlled !== undefined;
|
|
61
|
+
if (options?.kind === "node" && mode !== "focus")
|
|
62
|
+
throw new Error("Node interaction only supports focus");
|
|
63
|
+
if (mode === "focus" && ownership.current !== (controlled !== undefined))
|
|
64
|
+
throw new Error("Root selection ownership cannot change during a mount");
|
|
65
|
+
if (controlled !== undefined && !onChange)
|
|
66
|
+
throw new Error("Controlled Root selection requires its change callback");
|
|
67
|
+
if (controlled !== undefined && initial !== undefined)
|
|
68
|
+
throw new Error("Root selection cannot be both controlled and defaulted");
|
|
69
|
+
if (props.visibleSeries !== undefined && props.defaultVisibleSeries !== undefined)
|
|
70
|
+
throw new Error("Root visibility cannot be both controlled and defaulted");
|
|
71
|
+
if (props.onVisibleSeriesChange &&
|
|
72
|
+
props.visibleSeries === undefined &&
|
|
73
|
+
props.defaultVisibleSeries === undefined)
|
|
74
|
+
throw new Error("Root requires visibleSeries or defaultVisibleSeries with onVisibleSeriesChange");
|
|
75
|
+
const register = useCallback((owner, keys) => {
|
|
76
|
+
setRegistrations((old) => {
|
|
77
|
+
if (JSON.stringify(old.get(owner)) === JSON.stringify(keys))
|
|
78
|
+
return old;
|
|
79
|
+
return new Map(old).set(owner, keys);
|
|
80
|
+
});
|
|
81
|
+
return () => setRegistrations((old) => {
|
|
82
|
+
if (!old.has(owner))
|
|
83
|
+
return old;
|
|
84
|
+
const next = new Map(old);
|
|
85
|
+
next.delete(owner);
|
|
86
|
+
return next;
|
|
87
|
+
});
|
|
88
|
+
}, []);
|
|
89
|
+
const eligible = useMemo(() => [
|
|
90
|
+
...new Set(options?.eligibleKeys ??
|
|
91
|
+
(registrations.size ? [...registrations.values()].flat() : Object.keys(config))),
|
|
92
|
+
].filter((key) => Object.hasOwn(config, key) &&
|
|
93
|
+
![...unavailable.values()].some((item) => item.key === key &&
|
|
94
|
+
item.unavailable &&
|
|
95
|
+
[...unavailable.values()]
|
|
96
|
+
.filter((peer) => peer.key === key)
|
|
97
|
+
.every((peer) => peer.unavailable))), [options?.eligibleKeys, registrations, config, unavailable]);
|
|
98
|
+
const visible = props.visibleSeries ?? internalVisible;
|
|
99
|
+
const requested = controlled === undefined ? internal : controlled;
|
|
100
|
+
const selected = mode === "focus" &&
|
|
101
|
+
requested !== null &&
|
|
102
|
+
eligible.includes(requested) &&
|
|
103
|
+
(visible === undefined || visible.includes(requested))
|
|
104
|
+
? requested
|
|
105
|
+
: null;
|
|
106
|
+
// Registration settles in layout effects; never turn an invalid controlled ID into an owner write.
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (controlled === undefined && internal !== null && selected === null)
|
|
109
|
+
setInternal(null);
|
|
110
|
+
}, [controlled, internal, selected]);
|
|
111
|
+
const announce = (text) => setAnnouncement((old) => ({ text, sequence: old.sequence + 1 }));
|
|
112
|
+
const changeVisibility = (next) => {
|
|
113
|
+
if (props.visibleSeries === undefined)
|
|
114
|
+
setInternalVisible(next);
|
|
115
|
+
props.onVisibleSeriesChange?.(next);
|
|
116
|
+
};
|
|
117
|
+
const interactive = mode === "focus" ||
|
|
118
|
+
props.onVisibleSeriesChange !== undefined ||
|
|
119
|
+
props.defaultVisibleSeries !== undefined;
|
|
120
|
+
const permitted = (request) => {
|
|
121
|
+
if (request.event?.defaultPrevented)
|
|
122
|
+
return false;
|
|
123
|
+
const allowed = options?.onBeforeInteraction?.(request) !== false;
|
|
124
|
+
return allowed && !request.event?.defaultPrevented;
|
|
125
|
+
};
|
|
126
|
+
const change = (next) => {
|
|
127
|
+
if (controlled === undefined)
|
|
128
|
+
setInternal(next);
|
|
129
|
+
onChange?.(next);
|
|
130
|
+
announce(next === null ? "Highlight cleared." : `Highlighted ${config[next]?.label ?? next}.`);
|
|
131
|
+
};
|
|
132
|
+
const activate = (identity, source, event = null) => {
|
|
133
|
+
if (!interactive ||
|
|
134
|
+
identity.kind !== kind ||
|
|
135
|
+
!eligible.includes(identity.key) ||
|
|
136
|
+
(source === "mark" && options?.markActivation !== "matching-legend"))
|
|
137
|
+
return false;
|
|
138
|
+
if (!permitted({ identity, source, mode, event }))
|
|
139
|
+
return false;
|
|
140
|
+
if (mode === "focus") {
|
|
141
|
+
if (visible !== undefined && !visible.includes(identity.key))
|
|
142
|
+
return false;
|
|
143
|
+
change(selected === identity.key ? null : identity.key);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const current = visible ?? eligible;
|
|
147
|
+
const hiding = current.includes(identity.key);
|
|
148
|
+
if (hiding && !eligible.some((key) => key !== identity.key && current.includes(key))) {
|
|
149
|
+
announce("At least one item must remain visible.");
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
changeVisibility(hiding ? current.filter((key) => key !== identity.key) : [...current, identity.key]);
|
|
153
|
+
announce(`${hiding ? "Hidden" : "Shown"} ${config[identity.key]?.label ?? identity.key}.`);
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
};
|
|
157
|
+
const reset = (event = null) => {
|
|
158
|
+
if (!permitted({ identity: null, source: "reset", mode, event }))
|
|
159
|
+
return false;
|
|
160
|
+
if (mode === "focus" && requested !== null)
|
|
161
|
+
change(null);
|
|
162
|
+
return true;
|
|
163
|
+
};
|
|
164
|
+
return (_jsx(Context, { value: {
|
|
165
|
+
configured: options !== undefined,
|
|
166
|
+
mode,
|
|
167
|
+
kind,
|
|
168
|
+
selected,
|
|
169
|
+
eligible,
|
|
170
|
+
visible,
|
|
171
|
+
interactive,
|
|
172
|
+
markActivation: options?.markActivation === "matching-legend",
|
|
173
|
+
activate,
|
|
174
|
+
reset,
|
|
175
|
+
register,
|
|
176
|
+
registerUnavailable,
|
|
177
|
+
announcement,
|
|
178
|
+
}, children: children(visible, interactive ? changeVisibility : undefined) }));
|
|
179
|
+
}
|
|
180
|
+
export function ChartInteractionStatus() {
|
|
181
|
+
const { announcement } = useInteractionOwner();
|
|
182
|
+
return (_jsx("span", { "aria-live": "polite", "aria-atomic": "true", "data-kind-ui": "chart-interaction-status", style: {
|
|
183
|
+
position: "absolute",
|
|
184
|
+
width: 1,
|
|
185
|
+
height: 1,
|
|
186
|
+
padding: 0,
|
|
187
|
+
margin: -1,
|
|
188
|
+
overflow: "hidden",
|
|
189
|
+
clipPath: "inset(50%)",
|
|
190
|
+
whiteSpace: "nowrap",
|
|
191
|
+
border: 0,
|
|
192
|
+
}, children: _jsx("span", { children: announcement.text }, announcement.sequence) }));
|
|
193
|
+
}
|
|
194
|
+
/** Native series registration preserves hidden eligibility; callers may supply a stricter snapshot. */
|
|
195
|
+
export function useInteractionRegistration(keys) {
|
|
196
|
+
const { register } = useInteractionOwner();
|
|
197
|
+
const owner = useId();
|
|
198
|
+
const encoded = JSON.stringify(keys);
|
|
199
|
+
useLayoutEffect(() => register(owner, JSON.parse(encoded)), [register, owner, encoded]);
|
|
200
|
+
}
|
|
201
|
+
export function useInteractionAvailability(key, unavailable) {
|
|
202
|
+
const { registerUnavailable } = useInteractionOwner();
|
|
203
|
+
const owner = useId();
|
|
204
|
+
useLayoutEffect(() => registerUnavailable(owner, key, unavailable), [registerUnavailable, owner, key, unavailable]);
|
|
205
|
+
}
|
|
206
|
+
/** Retain the focused data identity when native layout replaces a sector node. */
|
|
207
|
+
export function useInteractionFocus(key, enabled) {
|
|
208
|
+
const current = useRef(null);
|
|
209
|
+
return useCallback((node) => {
|
|
210
|
+
const previous = current.current;
|
|
211
|
+
if (!node && enabled && previous === document.activeElement) {
|
|
212
|
+
const root = previous?.closest('[data-kind-ui="chart"]');
|
|
213
|
+
const plot = previous?.closest('[data-kind-ui="line-frame"]') ?? root;
|
|
214
|
+
queueMicrotask(() => {
|
|
215
|
+
if (!root?.isConnected || !plot?.isConnected || document.activeElement !== document.body)
|
|
216
|
+
return;
|
|
217
|
+
const replacement = Array.from(plot.querySelectorAll("[data-interaction-focus-key]")).find((item) => item.dataset.interactionFocusKey === key &&
|
|
218
|
+
item.closest('[data-kind-ui="chart"]') === root);
|
|
219
|
+
replacement?.focus({ preventScroll: true });
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
current.current = node;
|
|
223
|
+
}, [key, enabled]);
|
|
224
|
+
}
|
package/dist/combo-chart.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { type ComponentProps } from "react";
|
|
2
2
|
import { ComposedChart as EngineComposedChart } from "recharts";
|
|
3
|
-
import { type LineAnimation } from "./animation.js";
|
|
4
|
-
type Reveal = Pick<
|
|
3
|
+
import { type BaseAnimation, type LineAnimation } from "./animation.js";
|
|
4
|
+
type Reveal = Pick<BaseAnimation, "revealDurationMs" | "revealEasing">;
|
|
5
|
+
type DirectionalReveal = Reveal & Pick<LineAnimation, "revealDirection">;
|
|
5
6
|
/** Shared hover Motion, with independently configured family entrances. */
|
|
6
7
|
export type ComboAnimation = LineAnimation & {
|
|
7
|
-
lineReveal?: false |
|
|
8
|
-
areaReveal?: false |
|
|
8
|
+
lineReveal?: false | DirectionalReveal;
|
|
9
|
+
areaReveal?: false | DirectionalReveal;
|
|
9
10
|
barReveal?: false | Reveal;
|
|
10
11
|
};
|
|
11
12
|
export type ComboChartProps = ComponentProps<typeof EngineComposedChart> & {
|
|
12
13
|
animate?: boolean | ComboAnimation | undefined;
|
|
14
|
+
loading?: boolean | undefined;
|
|
15
|
+
loadingLabel?: string | undefined;
|
|
13
16
|
};
|
|
14
17
|
/** Native ComposedChart geometry with the maintained Line, Area and Bar series. */
|
|
15
|
-
export declare function ComboChart({ animate, children, ...props }: ComboChartProps): import("react").JSX.Element;
|
|
18
|
+
export declare function ComboChart({ animate, loading, loadingLabel, children, ...props }: ComboChartProps): import("react").JSX.Element;
|
|
16
19
|
export {};
|
package/dist/combo-chart.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { motion } from "motion/react";
|
|
4
3
|
import { useCallback, useId, useLayoutEffect, useRef, useState, useSyncExternalStore, } from "react";
|
|
5
4
|
import { ComposedChart as EngineComposedChart } from "recharts";
|
|
6
5
|
import { MotionContext } from "./animation.js";
|
|
7
6
|
import { BarLifecycle, BarMotion } from "./bar-chart.js";
|
|
8
7
|
import { LineChartFrame, useLineInteraction } from "./line-chart.js";
|
|
8
|
+
import { CartesianLoadingDesign } from "./loading-cartesian-designs.js";
|
|
9
|
+
import { RevealClip } from "./reveal-clip.js";
|
|
9
10
|
const query = "(prefers-reduced-motion: reduce)";
|
|
10
11
|
function subscribe(change) {
|
|
11
12
|
const media = window.matchMedia(query);
|
|
@@ -15,12 +16,6 @@ function subscribe(change) {
|
|
|
15
16
|
const snapshot = () => window.matchMedia(query).matches;
|
|
16
17
|
const serverSnapshot = () => true;
|
|
17
18
|
const defaultHover = { type: "spring", stiffness: 210, damping: 28, mass: 0.8 };
|
|
18
|
-
function Entrance({ id, family, options, finish, }) {
|
|
19
|
-
return (_jsx("defs", { children: _jsx("clipPath", { id: id, clipPathUnits: "userSpaceOnUse", children: _jsx(motion.rect, { "data-combo-reveal": family, x: 0, y: 0, height: "100%", initial: { width: "0%" }, animate: { width: "100%" }, onAnimationComplete: finish, transition: {
|
|
20
|
-
duration: Math.max(0, options.revealDurationMs ?? 1000) / 1000,
|
|
21
|
-
ease: options.revealEasing ?? [0.25, 0.1, 0.25, 1],
|
|
22
|
-
} }) }) }));
|
|
23
|
-
}
|
|
24
19
|
// A changed native child can change domains, axes, stacks or custom geometry.
|
|
25
20
|
// Conservatively end entrances rather than retain a clip in the old coordinate space.
|
|
26
21
|
function CompositionLifecycle({ children }) {
|
|
@@ -34,15 +29,22 @@ function CompositionLifecycle({ children }) {
|
|
|
34
29
|
return null;
|
|
35
30
|
}
|
|
36
31
|
/** Native ComposedChart geometry with the maintained Line, Area and Bar series. */
|
|
37
|
-
export function ComboChart({ animate = false, children, ...props }) {
|
|
32
|
+
export function ComboChart({ animate = false, loading, loadingLabel, children, ...props }) {
|
|
38
33
|
const id = useId();
|
|
39
34
|
const reduced = useSyncExternalStore(subscribe, snapshot, serverSnapshot);
|
|
40
35
|
const [finished, setFinished] = useState({ line: false, area: false, bar: false });
|
|
41
|
-
const interrupt = useCallback(() =>
|
|
36
|
+
const interrupt = useCallback(() => {
|
|
37
|
+
if (!loading)
|
|
38
|
+
setFinished({ line: true, area: true, bar: true });
|
|
39
|
+
}, [loading]);
|
|
40
|
+
useLayoutEffect(() => {
|
|
41
|
+
if (loading)
|
|
42
|
+
setFinished({ line: false, area: false, bar: false });
|
|
43
|
+
}, [loading]);
|
|
42
44
|
const finishLine = useCallback(() => setFinished((value) => ({ ...value, line: true })), []);
|
|
43
45
|
const finishArea = useCallback(() => setFinished((value) => ({ ...value, area: true })), []);
|
|
44
46
|
const finishBar = useCallback(() => setFinished((value) => ({ ...value, bar: true })), []);
|
|
45
|
-
const enabled = animate !== false && !reduced;
|
|
47
|
+
const enabled = animate !== false && !reduced && !loading;
|
|
46
48
|
const options = typeof animate === "object" ? animate : {};
|
|
47
49
|
const line = options.lineReveal === false ? false : { ...options, ...options.lineReveal };
|
|
48
50
|
const area = options.areaReveal === false ? false : { ...options, ...options.areaReveal };
|
|
@@ -53,12 +55,12 @@ export function ComboChart({ animate = false, children, ...props }) {
|
|
|
53
55
|
reveal: enabled && !finished.bar && bar !== false,
|
|
54
56
|
options: bar || {},
|
|
55
57
|
finish: finishBar,
|
|
56
|
-
}, children: _jsxs(LineChartFrame, { engine: EngineComposedChart, chartProps: {
|
|
58
|
+
}, children: _jsxs(LineChartFrame, { loading: loading, loadingLabel: loadingLabel, loadingSkeleton: "combo", loadingDesign: (seed) => _jsx(CartesianLoadingDesign, { family: "combo", seed: seed }), loadingAnimation: { ...options, ...(props.layout ? { layout: props.layout } : {}) }, engine: EngineComposedChart, chartProps: {
|
|
57
59
|
...props,
|
|
58
60
|
className: ["kind-ui-combo-chart", props.className].filter(Boolean).join(" "),
|
|
59
61
|
style: {
|
|
60
62
|
...props.style,
|
|
61
63
|
"--kind-ui-combo-area-clip": revealArea ? `url(#${id}-area)` : "none",
|
|
62
64
|
},
|
|
63
|
-
}, motionEnabled: enabled, interrupt: interrupt, clip: revealLine ? `url(#${id}-line)` : "none", children: [_jsx(BarLifecycle, { ...props }), _jsx(CompositionLifecycle, { children: children }), revealLine && (_jsx(
|
|
65
|
+
}, motionEnabled: enabled, interrupt: interrupt, clip: revealLine ? `url(#${id}-line)` : "none", children: [_jsx(BarLifecycle, { ...props }), _jsx(CompositionLifecycle, { children: children }), revealLine && (_jsx(RevealClip, { id: `${id}-line`, family: "line", combo: true, options: line || {}, finish: finishLine })), revealArea && (_jsx(RevealClip, { id: `${id}-area`, family: "area", combo: true, options: area || {}, finish: finishArea })), children] }) }) }));
|
|
64
66
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type CartesianGridProps, type DataKey, type XAxisProps, type YAxisProps } from "recharts";
|
|
3
3
|
import { type LineChartProps as ComposedLineChartProps, type LineSeriesProps, type TooltipProps } from "./animation.js";
|
|
4
|
+
import { type ChartBackgroundPatternProps } from "./chart-background-pattern.js";
|
|
4
5
|
import { type LegendProps } from "./legend.js";
|
|
5
6
|
import { type RootProps } from "./root.js";
|
|
6
7
|
import type { SeriesConfig } from "./types.js";
|
|
@@ -34,6 +35,7 @@ type GeneratedParts<DataPoint> = {
|
|
|
34
35
|
material?: LineSeriesProps["material"];
|
|
35
36
|
xAxis?: false | XAxisProps<DataPoint>;
|
|
36
37
|
yAxis?: false | YAxisProps<DataPoint>;
|
|
38
|
+
backgroundPattern?: ChartBackgroundPatternProps;
|
|
37
39
|
grid?: false | CartesianGridProps;
|
|
38
40
|
tooltip?: false | TooltipProps;
|
|
39
41
|
series?: readonly ConfiguredLineSeries<DataPoint>[];
|
|
@@ -46,6 +48,7 @@ type ExplicitParts = {
|
|
|
46
48
|
xDataKey?: never;
|
|
47
49
|
xAxis?: never;
|
|
48
50
|
yAxis?: never;
|
|
51
|
+
backgroundPattern?: never;
|
|
49
52
|
grid?: never;
|
|
50
53
|
tooltip?: never;
|
|
51
54
|
series?: never;
|
|
@@ -55,7 +58,7 @@ export type ConfiguredLineChartProps<DataPoint = DefaultDataPoint> = Omit<Compos
|
|
|
55
58
|
data: readonly DataPoint[];
|
|
56
59
|
"aria-describedby"?: string;
|
|
57
60
|
legend?: false | LegendProps;
|
|
58
|
-
rootProps?: Omit<RootProps, "config" | "children" | "visibleSeries" | "onVisibleSeriesChange">;
|
|
61
|
+
rootProps?: Omit<RootProps, "config" | "children" | "visibleSeries" | "defaultVisibleSeries" | "onVisibleSeriesChange">;
|
|
59
62
|
} & Name & Visibility & (GeneratedParts<DataPoint> | ExplicitParts);
|
|
60
63
|
export type LineChartProps = ComposedLineChartProps;
|
|
61
64
|
type CompositionLineChartProps = LineChartProps & {
|
|
@@ -63,6 +66,7 @@ type CompositionLineChartProps = LineChartProps & {
|
|
|
63
66
|
xDataKey?: never;
|
|
64
67
|
xAxis?: never;
|
|
65
68
|
yAxis?: never;
|
|
69
|
+
backgroundPattern?: never;
|
|
66
70
|
grid?: never;
|
|
67
71
|
tooltip?: never;
|
|
68
72
|
curve?: never;
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { useContext, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { CartesianGrid, XAxis, YAxis, } from "recharts";
|
|
5
5
|
import { LineChart as ComposedLineChart, LineSeries, Tooltip, } from "./animation.js";
|
|
6
|
+
import { ChartBackgroundPattern, } from "./chart-background-pattern.js";
|
|
6
7
|
import { ChartContext } from "./chart-context.js";
|
|
7
8
|
import { Legend } from "./legend.js";
|
|
8
9
|
import { Root } from "./root.js";
|
|
@@ -14,7 +15,7 @@ export function LineChart(props) {
|
|
|
14
15
|
}
|
|
15
16
|
function ConfiguredLineChart(props) {
|
|
16
17
|
const parent = useContext(ChartContext);
|
|
17
|
-
const { config, data, children, xDataKey, curve, material, xAxis, yAxis, grid, tooltip, series, legend, rootProps, visibleSeries, defaultVisibleSeries, onVisibleSeriesChange, style, className, width, height, responsive, accessibilityLayer = true, animate = true, ...chartProps } = props;
|
|
18
|
+
const { config, data, children, xDataKey, curve, material, xAxis, yAxis, grid, backgroundPattern, tooltip, series, legend, rootProps, visibleSeries, defaultVisibleSeries, onVisibleSeriesChange, style, className, width, height, responsive, accessibilityLayer = true, animate = true, loading, loadingLabel, ...chartProps } = props;
|
|
18
19
|
const controlled = visibleSeries !== undefined;
|
|
19
20
|
const initialMode = useRef(controlled);
|
|
20
21
|
// Undefined means all current configured keys, including keys added later.
|
|
@@ -32,7 +33,7 @@ function ConfiguredLineChart(props) {
|
|
|
32
33
|
throw new Error("Configured LineChart requires aria-label or aria-labelledby");
|
|
33
34
|
const generated = children === undefined;
|
|
34
35
|
if (!generated &&
|
|
35
|
-
[xDataKey, curve, material, xAxis, yAxis, grid, tooltip, series].some((part) => part !== undefined))
|
|
36
|
+
[xDataKey, curve, material, xAxis, yAxis, grid, tooltip, series, backgroundPattern].some((part) => part !== undefined))
|
|
36
37
|
throw new Error("Explicit LineChart children replace generated parts; remove xDataKey and generated-part options");
|
|
37
38
|
if (generated && xDataKey === undefined)
|
|
38
39
|
throw new Error("Configured LineChart requires xDataKey when children are omitted");
|
|
@@ -67,11 +68,13 @@ function ConfiguredLineChart(props) {
|
|
|
67
68
|
]
|
|
68
69
|
.filter(Boolean)
|
|
69
70
|
.join(" ");
|
|
70
|
-
return (_jsxs(Root, { ...rootProps, className: ["kind-ui-configured-line-root", rootProps?.className].filter(Boolean).join(" "), config: activeConfig, visibleSeries: visible, ...(change ? { onVisibleSeriesChange: change } : {}), children: [accessibilityLayer && (_jsx("p", { id: instructionId, "data-kind-ui": "chart-instructions", children: "Focus the chart and use the arrow keys to inspect values. Press Escape to dismiss the tooltip." })), _jsx(ComposedLineChart, { ...chartProps, data: data, accessibilityLayer: accessibilityLayer, animate: animate, ...(describedBy ? { "aria-describedby": describedBy } : {}), responsive: responsive ?? true, ...(width !== undefined ? { width } : {}), ...(height !== undefined ? { height } : {}), className: ["kind-ui-configured-line-chart", className].filter(Boolean).join(" "), style: {
|
|
71
|
+
return (_jsxs(Root, { ...rootProps, className: ["kind-ui-configured-line-root", rootProps?.className].filter(Boolean).join(" "), config: activeConfig, visibleSeries: visible, ...(change ? { onVisibleSeriesChange: change } : {}), children: [accessibilityLayer && (_jsx("p", { id: instructionId, "data-kind-ui": "chart-instructions", children: "Focus the chart and use the arrow keys to inspect values. Press Escape to dismiss the tooltip." })), _jsx(ComposedLineChart, { ...chartProps, data: data, accessibilityLayer: accessibilityLayer, animate: animate, loading: loading, loadingLabel: loadingLabel, ...(describedBy ? { "aria-describedby": describedBy } : {}), responsive: responsive ?? true, ...(width !== undefined ? { width } : {}), ...(height !== undefined ? { height } : {}), className: ["kind-ui-configured-line-chart", className].filter(Boolean).join(" "), style: {
|
|
71
72
|
...(width !== undefined ? { width } : {}),
|
|
72
73
|
...(height !== undefined ? { height } : {}),
|
|
73
74
|
...style,
|
|
74
|
-
}, children: generated ? (_jsxs(_Fragment, { children: [grid !== false && (_jsx(CartesianGrid, { vertical: false, stroke: "var(--kind-ui-chart-grid, #d1d5db)", strokeDasharray: "3 3", ...grid })), xAxis !== false && (_jsx(XAxis, { ...(xDataKey !== undefined ? { dataKey: xDataKey } : {}), axisLine: false, tickLine: false, tick: { fontSize: 12, fill: "var(--kind-ui-chart-muted-foreground, #6b7280)" }, ...xAxis })), yAxis !== false && (_jsx(YAxis, { axisLine: false, tickLine: false, tick: { fontSize: 12, fill: "var(--kind-ui-chart-muted-foreground, #6b7280)" }, ...yAxis })), series !== undefined
|
|
75
|
-
? series.map((item) => (_jsx(LineSeries, { type: curve ?? "monotone", material: material ?? "plain",
|
|
75
|
+
}, children: generated ? (_jsxs(_Fragment, { children: [backgroundPattern && _jsx(ChartBackgroundPattern, { ...backgroundPattern }), grid !== false && (_jsx(CartesianGrid, { vertical: false, stroke: "var(--kind-ui-chart-grid, #d1d5db)", strokeDasharray: "3 3", ...grid })), xAxis !== false && (_jsx(XAxis, { ...(xDataKey !== undefined ? { dataKey: xDataKey } : {}), axisLine: false, tickLine: false, tick: { fontSize: 12, fill: "var(--kind-ui-chart-muted-foreground, #6b7280)" }, ...xAxis })), yAxis !== false && (_jsx(YAxis, { axisLine: false, tickLine: false, tick: { fontSize: 12, fill: "var(--kind-ui-chart-muted-foreground, #6b7280)" }, ...yAxis })), series !== undefined
|
|
76
|
+
? series.map((item) => (_jsx(LineSeries, { type: curve ?? "monotone", material: material ?? "plain", ...(item.pointStyle === undefined || item.pointStyle === "default"
|
|
77
|
+
? { dot: { r: 2.5 } }
|
|
78
|
+
: {}), strokeWidth: 2, ...item }, item.seriesKey)))
|
|
76
79
|
: keys.map((key) => (_jsx(LineSeries, { dataKey: key, seriesKey: key, type: curve ?? "monotone", material: material ?? "plain", dot: { r: 2.5 }, strokeWidth: 2 }, key))), tooltip !== false && _jsx(Tooltip, { ...tooltip })] })) : (children) }), legend !== false && (generated || legend !== undefined) && _jsx(Legend, { ...legend })] }));
|
|
77
80
|
}
|
package/dist/emphasis.d.ts
CHANGED
|
@@ -24,9 +24,10 @@ export declare function EmphasisProvider({ enabled, children, }: {
|
|
|
24
24
|
enabled: boolean;
|
|
25
25
|
children: React.ReactNode;
|
|
26
26
|
}): import("react").JSX.Element;
|
|
27
|
+
export declare function useOptionalEmphasisActions(): Omit<EmphasisState, "active"> | null;
|
|
27
28
|
export declare function useEmphasisActions(): Omit<EmphasisState, "active">;
|
|
28
29
|
/** Explicit contract for custom and portaled marks; apply factor to an extra paint wrapper. */
|
|
29
|
-
export declare function useEmphasis(target: EmphasisTarget, enabled?: boolean): {
|
|
30
|
+
export declare function useEmphasis(target: EmphasisTarget, enabled?: boolean, persistent?: boolean): {
|
|
30
31
|
active: EmphasisTarget | null;
|
|
31
32
|
dimmed: boolean;
|
|
32
33
|
factor: number;
|
|
@@ -36,9 +37,11 @@ export declare function useEmphasis(target: EmphasisTarget, enabled?: boolean):
|
|
|
36
37
|
export type EmphasisMarkProps = Omit<ComponentPropsWithRef<"g">, "target"> & {
|
|
37
38
|
target: EmphasisTarget;
|
|
38
39
|
enabled?: boolean | undefined;
|
|
40
|
+
/** Explicitly bind persistent Root focus paint for custom marks. */
|
|
41
|
+
persistent?: boolean | undefined;
|
|
39
42
|
/** Adapter input from the engine, used only during native keyboard inspection. */
|
|
40
43
|
keyboardActive?: boolean | undefined;
|
|
41
44
|
};
|
|
42
45
|
/** Multiplicative paint layer; native geometry, consumer opacity and hit testing stay intact. */
|
|
43
|
-
export declare function EmphasisMark({ target, enabled, keyboardActive, children, ...props }: EmphasisMarkProps): import("react").JSX.Element;
|
|
46
|
+
export declare function EmphasisMark({ target, enabled, persistent, keyboardActive, children, ...props }: EmphasisMarkProps): import("react").JSX.Element;
|
|
44
47
|
export {};
|