@moderneinc/react-charts 1.5.2-next.f2fa0c → 1.5.2-next.f8b5a8
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/dist/components/campaign-timeline/campaign-timeline.component.d.ts +3 -0
- package/dist/components/campaign-timeline/campaign-timeline.constants.d.ts +13 -0
- package/dist/components/campaign-timeline/campaign-timeline.types.d.ts +156 -0
- package/dist/components/campaign-timeline/components/axis-band.component.d.ts +11 -0
- package/dist/components/campaign-timeline/components/burndown-band.component.d.ts +18 -0
- package/dist/components/campaign-timeline/components/event-lane-band.component.d.ts +16 -0
- package/dist/components/campaign-timeline/components/playhead.component.d.ts +14 -0
- package/dist/components/campaign-timeline/hooks/use-campaign-timeline.hook.d.ts +30 -0
- package/dist/components/campaign-timeline/utils/burndown-paths.d.ts +29 -0
- package/dist/components/campaign-timeline/utils/layout-event-flags.d.ts +43 -0
- package/dist/components/campaign-timeline/utils/measure-text.d.ts +9 -0
- package/dist/components/campaign-timeline/utils/pack-event-rows.d.ts +21 -0
- package/dist/components/morph-chart/hooks/use-morph-chart.hook.d.ts +3 -1
- package/dist/components/morph-chart/morph-chart.types.d.ts +3 -0
- package/dist/components/morph-chart/utils/parliament-renderer.d.ts +2 -0
- package/dist/components/parliament-chart/hooks/use-parliament-chart.hook.d.ts +3 -1
- package/dist/components/parliament-chart/parliament-chart.constants.d.ts +14 -5
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6998 -6131
- package/dist/theme/readable-color.d.ts +9 -0
- package/dist/utils/is-development.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared between the hook that MEASURES and the components that RENDER -
|
|
3
|
+
* duplicating any of these lets collision detection drift from the painted text.
|
|
4
|
+
*/
|
|
5
|
+
/** Used where the parent reports no width (SSR, jsdom, collapsed container). */
|
|
6
|
+
export declare const FALLBACK_WIDTH = 900;
|
|
7
|
+
/** Spacing so the plot and the grip's rounded end don't sit flush to the edge. */
|
|
8
|
+
export declare const RIGHT_INSET = 10;
|
|
9
|
+
export declare const TICK_SPACING = 90;
|
|
10
|
+
/** How close, in pixels, the playhead must be to an event to snap to it. */
|
|
11
|
+
export declare const SNAP_RADIUS = 8;
|
|
12
|
+
export declare const TICK_FONT_SIZE = 10.5;
|
|
13
|
+
export declare const MIN_LABEL_GAP = 12;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three bands on one shared x-axis - burn-down, axis, row-packed events -
|
|
3
|
+
* scrubbed by a single playhead. Event names are the caller's vocabulary.
|
|
4
|
+
*/
|
|
5
|
+
/** A discrete run/action on the event track. */
|
|
6
|
+
export type CampaignEvent = {
|
|
7
|
+
/** Stable identity, used for packing, selection, and React keys. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Caller-supplied display name. Arbitrary - drives the flag's label. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Start of the event (ms since epoch). Positions the flag's pole. */
|
|
12
|
+
start: number;
|
|
13
|
+
/**
|
|
14
|
+
* NOTE: never drawn. Flags anchor at `start` and are sized to their label;
|
|
15
|
+
* `end` only widens the domain, adds a snap target, and marks "still
|
|
16
|
+
* running" when absent. `null` is accepted so JSON passes through unstripped.
|
|
17
|
+
*/
|
|
18
|
+
end?: number | null;
|
|
19
|
+
/**
|
|
20
|
+
* Contrast-corrected against the surface, so one palette works in both
|
|
21
|
+
* themes. Burn-down series colors are not - they carry no text.
|
|
22
|
+
*/
|
|
23
|
+
color?: string;
|
|
24
|
+
/** Passed straight through to `onEventClick`. The component never reads it. */
|
|
25
|
+
meta?: Record<string, unknown>;
|
|
26
|
+
};
|
|
27
|
+
/** One stacked band beneath the burn-down line. */
|
|
28
|
+
export type BurndownSeries = {
|
|
29
|
+
/** Key into each point's `values` map. */
|
|
30
|
+
key: string;
|
|
31
|
+
/** Human-readable name for this band. The component never reads it - it is
|
|
32
|
+
* kept alongside the data so callers building their own legend don't need a
|
|
33
|
+
* parallel key-to-label map. */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Fill color for this band. Drawn as a low-opacity area. */
|
|
36
|
+
color: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A sampled check point: per-series counts still in flight. The burn-down line
|
|
40
|
+
* is the SUM of these, so bands always cap exactly at the line.
|
|
41
|
+
*/
|
|
42
|
+
export type BurndownPoint = {
|
|
43
|
+
timestamp: number;
|
|
44
|
+
values: Record<string, number>;
|
|
45
|
+
};
|
|
46
|
+
export type BurndownConfig = {
|
|
47
|
+
/** The fixed population the campaign started with - the dashed ceiling. */
|
|
48
|
+
total: number;
|
|
49
|
+
/** Stacked bottom-up in array order. */
|
|
50
|
+
series: BurndownSeries[];
|
|
51
|
+
/**
|
|
52
|
+
* Sorted defensively. The line steps rather than interpolating: a gap
|
|
53
|
+
* between samples means "no data", not "a smooth decline".
|
|
54
|
+
*/
|
|
55
|
+
points: BurndownPoint[];
|
|
56
|
+
};
|
|
57
|
+
/** Emitted when the playhead moves. */
|
|
58
|
+
export type PlayheadChangeReason = 'drag' | 'keyboard' | 'click';
|
|
59
|
+
/** Resolved palette handed to every band, so all three draw from one source. */
|
|
60
|
+
export type CampaignTimelineColors = {
|
|
61
|
+
surface: string;
|
|
62
|
+
/**
|
|
63
|
+
* WARNING: the MUI palette value, not the painted `surface`. Overriding
|
|
64
|
+
* `--rc-campaign-surface` to another lightness invalidates contrast math.
|
|
65
|
+
*/
|
|
66
|
+
surfaceValue: string;
|
|
67
|
+
isDark: boolean;
|
|
68
|
+
track: string;
|
|
69
|
+
border: string;
|
|
70
|
+
grid: string;
|
|
71
|
+
muted: string;
|
|
72
|
+
text: string;
|
|
73
|
+
accent: string;
|
|
74
|
+
accentContrast: string;
|
|
75
|
+
};
|
|
76
|
+
/** A tick position plus whether it earned a label. */
|
|
77
|
+
export type PlacedTick = {
|
|
78
|
+
timestamp: number;
|
|
79
|
+
x: number;
|
|
80
|
+
label: string;
|
|
81
|
+
/**
|
|
82
|
+
* False on edge overflow, collision, or repetition; the tick still renders as
|
|
83
|
+
* a minor mark. Axis and gridlines both read this so they cannot disagree.
|
|
84
|
+
*/
|
|
85
|
+
showLabel: boolean;
|
|
86
|
+
};
|
|
87
|
+
export type CampaignTimelineProps = {
|
|
88
|
+
/** Events to lay out on the packed track. Order is irrelevant. */
|
|
89
|
+
events: CampaignEvent[];
|
|
90
|
+
/** Burn-down series and check points. */
|
|
91
|
+
burndown: BurndownConfig;
|
|
92
|
+
/** Controlled playhead position (ms since epoch). */
|
|
93
|
+
time?: number;
|
|
94
|
+
/** Initial playhead position when uncontrolled. Defaults to the domain end. */
|
|
95
|
+
defaultTime?: number;
|
|
96
|
+
/** Called as the playhead moves. */
|
|
97
|
+
onTimeChange?: (time: number, reason: PlayheadChangeReason) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Snap the playhead to nearby event starts/ends on click and drag.
|
|
100
|
+
* Arrow-key stepping always moves event-to-event regardless of this flag.
|
|
101
|
+
* @default true
|
|
102
|
+
*/
|
|
103
|
+
snapToEvents?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* How far data is known - typically the last status refresh. The line stops
|
|
106
|
+
* here and the rest is hatched: unrefreshed, not empty. Defaults to no hatch.
|
|
107
|
+
*/
|
|
108
|
+
now?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Extends the x-domain to at least this time, so the chart can show
|
|
111
|
+
* wall-clock time past the last refresh. Never shrinks the domain: a value
|
|
112
|
+
* earlier than the last data point has no effect.
|
|
113
|
+
*/
|
|
114
|
+
horizonEnd?: number;
|
|
115
|
+
/** Ids of events drawn in the selected state. */
|
|
116
|
+
selectedEventIds?: string[];
|
|
117
|
+
/** Called when an event flag is clicked. */
|
|
118
|
+
onEventClick?: (event: CampaignEvent) => void;
|
|
119
|
+
/** Called when an event flag is hovered (null on leave). */
|
|
120
|
+
onEventHover?: (event: CampaignEvent | null) => void;
|
|
121
|
+
/**
|
|
122
|
+
* Width in pixels. Omit to fill the parent element and track it on resize.
|
|
123
|
+
* Falls back to 900 where the parent reports no width (SSR, jsdom, or a
|
|
124
|
+
* collapsed container).
|
|
125
|
+
*/
|
|
126
|
+
width?: number;
|
|
127
|
+
/** Height of the burn-down band. @default 132 */
|
|
128
|
+
burndownHeight?: number;
|
|
129
|
+
/** Height of the shared axis strip. @default 26 */
|
|
130
|
+
axisHeight?: number;
|
|
131
|
+
/** Height of each packed event row. @default 26 */
|
|
132
|
+
laneHeight?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Formats axis tick labels. The default picks ONE resolution for the whole
|
|
135
|
+
* axis from the tick spacing d3 chose: day-and-coarser renders "Aug 4",
|
|
136
|
+
* anything finer adds a time.
|
|
137
|
+
*/
|
|
138
|
+
formatDate?: (timestamp: number) => string;
|
|
139
|
+
/** Formats the playhead grip label. */
|
|
140
|
+
formatPlayheadLabel?: (timestamp: number) => string;
|
|
141
|
+
/** Formats the `total` and `remaining` annotations. */
|
|
142
|
+
formatValue?: (value: number) => string;
|
|
143
|
+
/** Label beside the dashed total line. @default 'total' */
|
|
144
|
+
totalLabel?: string;
|
|
145
|
+
/** Label on the callout tracking the line's end. @default 'in flight' */
|
|
146
|
+
remainingLabel?: string;
|
|
147
|
+
/** Suffix on flags whose event has no end. @default 'running' */
|
|
148
|
+
runningLabel?: string;
|
|
149
|
+
/** Text shown inside the hatched region. Hidden when the region is too
|
|
150
|
+
* narrow to hold it. */
|
|
151
|
+
hatchLabel?: string;
|
|
152
|
+
/** Fallback flag color. Defaults to the theme's primary color. */
|
|
153
|
+
defaultEventColor?: string;
|
|
154
|
+
/** Accessible name for the playhead slider. @default 'Timeline position' */
|
|
155
|
+
playheadAriaLabel?: string;
|
|
156
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CampaignTimelineColors, PlacedTick } from '../campaign-timeline.types';
|
|
2
|
+
type AxisBandProps = {
|
|
3
|
+
ticks: PlacedTick[];
|
|
4
|
+
plotWidth: number;
|
|
5
|
+
height: number;
|
|
6
|
+
colors: CampaignTimelineColors;
|
|
7
|
+
fontFamily: string;
|
|
8
|
+
};
|
|
9
|
+
/** Memoized: ticks are stable while the playhead moves. */
|
|
10
|
+
export declare const AxisBand: import('react').MemoExoticComponent<({ ticks, plotWidth, height, colors, fontFamily }: AxisBandProps) => import("react").JSX.Element>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BurndownPoint, BurndownSeries, CampaignTimelineColors } from '../campaign-timeline.types';
|
|
2
|
+
type BurndownBandProps = {
|
|
3
|
+
points: BurndownPoint[];
|
|
4
|
+
series: BurndownSeries[];
|
|
5
|
+
total: number;
|
|
6
|
+
height: number;
|
|
7
|
+
plotWidth: number;
|
|
8
|
+
scaleX: (timestamp: number) => number;
|
|
9
|
+
/** Data is only known up to here; the line stops rather than guessing. */
|
|
10
|
+
now: number;
|
|
11
|
+
colors: CampaignTimelineColors;
|
|
12
|
+
formatValue: (value: number) => string;
|
|
13
|
+
totalLabel: string;
|
|
14
|
+
remainingLabel: string;
|
|
15
|
+
fontFamily: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const BurndownBand: import('react').MemoExoticComponent<({ points, series, total, height, plotWidth, scaleX, now, colors, formatValue, totalLabel, remainingLabel, fontFamily }: BurndownBandProps) => import("react").JSX.Element>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CampaignEvent, CampaignTimelineColors } from '../campaign-timeline.types';
|
|
2
|
+
import { FlagLayout } from '../utils/layout-event-flags';
|
|
3
|
+
type EventLaneBandProps = {
|
|
4
|
+
flags: FlagLayout[];
|
|
5
|
+
rowCount: number;
|
|
6
|
+
laneHeight: number;
|
|
7
|
+
plotWidth: number;
|
|
8
|
+
defaultColor: string;
|
|
9
|
+
selectedIds: Set<string>;
|
|
10
|
+
colors: CampaignTimelineColors;
|
|
11
|
+
fontFamily: string;
|
|
12
|
+
onEventClick?: (event: CampaignEvent) => void;
|
|
13
|
+
onEventHover?: (event: CampaignEvent | null) => void;
|
|
14
|
+
};
|
|
15
|
+
export declare const EventLaneBand: import('react').MemoExoticComponent<({ flags, rowCount, laneHeight, plotWidth, defaultColor, selectedIds, colors, fontFamily, onEventClick, onEventHover }: EventLaneBandProps) => import("react").JSX.Element>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
type PlayheadProps = {
|
|
3
|
+
x: number;
|
|
4
|
+
totalHeight: number;
|
|
5
|
+
/** Vertical center of the axis strip, where the grip sits. */
|
|
6
|
+
gripCenterY: number;
|
|
7
|
+
label: string;
|
|
8
|
+
color: string;
|
|
9
|
+
contrastColor: string;
|
|
10
|
+
fontFamily: string;
|
|
11
|
+
plotWidth: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const Playhead: FunctionComponent<PlayheadProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';
|
|
2
|
+
import { BurndownConfig, CampaignEvent, PlacedTick, PlayheadChangeReason } from '../campaign-timeline.types';
|
|
3
|
+
type UseCampaignTimelineProps = {
|
|
4
|
+
events: CampaignEvent[];
|
|
5
|
+
burndown: BurndownConfig;
|
|
6
|
+
time?: number;
|
|
7
|
+
defaultTime?: number;
|
|
8
|
+
onTimeChange?: (time: number, reason: PlayheadChangeReason) => void;
|
|
9
|
+
snapToEvents: boolean;
|
|
10
|
+
now?: number;
|
|
11
|
+
horizonEnd?: number;
|
|
12
|
+
width?: number;
|
|
13
|
+
fontFamily: string;
|
|
14
|
+
formatDate?: (timestamp: number) => string;
|
|
15
|
+
};
|
|
16
|
+
export declare const useCampaignTimeline: ({ events, burndown, time, defaultTime, onTimeChange, snapToEvents, now, horizonEnd, width: widthProp, fontFamily, formatDate }: UseCampaignTimelineProps) => {
|
|
17
|
+
containerRef: import('react').RefObject<HTMLDivElement>;
|
|
18
|
+
width: number;
|
|
19
|
+
plotWidth: number;
|
|
20
|
+
domain: [number, number];
|
|
21
|
+
placedTicks: PlacedTick[];
|
|
22
|
+
scaleX: (timestamp: number) => number;
|
|
23
|
+
currentTime: number;
|
|
24
|
+
isScrubbing: boolean;
|
|
25
|
+
handlePointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;
|
|
26
|
+
handlePointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void;
|
|
27
|
+
handlePointerUp: (event: ReactPointerEvent<HTMLDivElement>) => void;
|
|
28
|
+
handleKeyDown: (event: ReactKeyboardEvent<HTMLDivElement>) => void;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BurndownPoint, BurndownSeries } from '../campaign-timeline.types';
|
|
2
|
+
type Scale = (value: number) => number;
|
|
3
|
+
/** Sum of every series at a point - the count still in flight. */
|
|
4
|
+
export declare const sumSeries: (point: BurndownPoint, series: BurndownSeries[]) => number;
|
|
5
|
+
export declare const remainingByPoint: (points: BurndownPoint[], series: BurndownSeries[]) => number[];
|
|
6
|
+
/**
|
|
7
|
+
* Points at or before `now`, ascending, with anything non-finite dropped.
|
|
8
|
+
*
|
|
9
|
+
* WARNING: filtering has to happen HERE rather than only in
|
|
10
|
+
* `buildBurndownGeometry`, because the caller derives the y-domain from these
|
|
11
|
+
* points - a single NaN value would make `scaleLinear` return NaN for every
|
|
12
|
+
* input and blank the entire band.
|
|
13
|
+
*/
|
|
14
|
+
export declare const knownPoints: (points: BurndownPoint[], now: number, series: BurndownSeries[]) => BurndownPoint[];
|
|
15
|
+
type BurndownBandPath = {
|
|
16
|
+
key: string;
|
|
17
|
+
color: string;
|
|
18
|
+
d: string;
|
|
19
|
+
};
|
|
20
|
+
type BurndownGeometry = {
|
|
21
|
+
linePath: string;
|
|
22
|
+
bands: BurndownBandPath[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Bands come from the stack; the line is those values re-summed. They coincide
|
|
26
|
+
* only because the default stack offset puts the top of the stack at the sum.
|
|
27
|
+
*/
|
|
28
|
+
export declare const buildBurndownGeometry: (points: BurndownPoint[], series: BurndownSeries[], xScale: Scale, yScale: Scale) => BurndownGeometry;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CampaignEvent } from '../campaign-timeline.types';
|
|
2
|
+
export declare const POLE_WIDTH = 2.5;
|
|
3
|
+
export declare const BANNER_HEIGHT = 20;
|
|
4
|
+
export declare const FLAG_FONT_SIZE = 11;
|
|
5
|
+
export declare const FLAG_FONT_WEIGHT = 600;
|
|
6
|
+
export type FlagLayout = {
|
|
7
|
+
event: CampaignEvent;
|
|
8
|
+
/** Pixel x of the event's start - where the pole sits. */
|
|
9
|
+
poleX: number;
|
|
10
|
+
width: number;
|
|
11
|
+
row: number;
|
|
12
|
+
label: string;
|
|
13
|
+
/** True when the label was moved left of the pole to stay on canvas. */
|
|
14
|
+
labelOutside: boolean;
|
|
15
|
+
labelX: number;
|
|
16
|
+
/** Chip behind an outside label. Zero width when the label is inline. */
|
|
17
|
+
chipX: number;
|
|
18
|
+
chipWidth: number;
|
|
19
|
+
/** The flag's full rendered extent - its packing footprint. */
|
|
20
|
+
x0: number;
|
|
21
|
+
x1: number;
|
|
22
|
+
};
|
|
23
|
+
type LayoutEventFlagsOptions = {
|
|
24
|
+
events: CampaignEvent[];
|
|
25
|
+
xScale: (timestamp: number) => number;
|
|
26
|
+
plotWidth: number;
|
|
27
|
+
fontFamily: string;
|
|
28
|
+
runningLabel: string;
|
|
29
|
+
gap?: number;
|
|
30
|
+
};
|
|
31
|
+
/** An event with no end is still running - it has no known conclusion. */
|
|
32
|
+
export declare const isRunning: (event: CampaignEvent) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* A flag whose label was pushed outside contributes that label to its
|
|
35
|
+
* footprint, or a neighbour would pack into space the label already occupies.
|
|
36
|
+
*/
|
|
37
|
+
export declare const layoutEventFlags: ({ events, xScale, plotWidth, fontFamily, runningLabel, gap }: LayoutEventFlagsOptions) => {
|
|
38
|
+
flags: FlagLayout[];
|
|
39
|
+
rowCount: number;
|
|
40
|
+
};
|
|
41
|
+
/** Rectangle whose left edge tapers to a point, so the eye lands on the start. */
|
|
42
|
+
export declare const buildFlagBannerPath: (x: number, y: number, width: number, height: number) => string;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text measurement for row packing: flags are packed by rendered extent, so the
|
|
3
|
+
* packer needs label widths before anything reaches the DOM.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Falls back to a character-count estimate where canvas metrics are
|
|
7
|
+
* unavailable (SSR, jsdom without `canvas`), so flags still measure differently.
|
|
8
|
+
*/
|
|
9
|
+
export declare const measureText: (text: string, fontSize: number, fontFamily: string, fontWeight?: number | string) => number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greedy first-fit row packing, in PIXEL space rather than time space: two
|
|
3
|
+
* events minutes apart can still have labels that overlap on screen.
|
|
4
|
+
*/
|
|
5
|
+
/** A flag's horizontal footprint, in pixels. */
|
|
6
|
+
type PackableItem = {
|
|
7
|
+
/** Its pole, or its label chip when the label was pushed outside. */
|
|
8
|
+
x0: number;
|
|
9
|
+
x1: number;
|
|
10
|
+
};
|
|
11
|
+
type PackedRows = {
|
|
12
|
+
/** Row index per input position, 0 = topmost. */
|
|
13
|
+
rows: number[];
|
|
14
|
+
rowCount: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Rows come back indexed by input POSITION, not keyed by event id, so duplicate
|
|
18
|
+
* ids in caller data cannot collapse two flags onto one row.
|
|
19
|
+
*/
|
|
20
|
+
export declare const packEventRows: (items: PackableItem[], gap?: number) => PackedRows;
|
|
21
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaletteMode } from '@mui/material/styles';
|
|
1
2
|
import { RefObject } from 'react';
|
|
2
3
|
import { HoveredData, MorphChartCategory, MorphChartDataPoint, MorphMode } from '../morph-chart.types';
|
|
3
4
|
type UseMorphChartProps = {
|
|
@@ -5,6 +6,7 @@ type UseMorphChartProps = {
|
|
|
5
6
|
data: MorphChartDataPoint[];
|
|
6
7
|
categories: MorphChartCategory[];
|
|
7
8
|
mode: 'parliament' | 'stacked-area';
|
|
9
|
+
paletteMode?: PaletteMode;
|
|
8
10
|
width: number;
|
|
9
11
|
height: number;
|
|
10
12
|
margin: {
|
|
@@ -58,7 +60,7 @@ type UseMorphChartProps = {
|
|
|
58
60
|
y: number;
|
|
59
61
|
} | null) => void;
|
|
60
62
|
};
|
|
61
|
-
export declare const useMorphChart: ({ containerRef, data, categories, mode, width, height, margin, timeRange, showGrid, showAxes, axisLabelColor, axisLabelSize, formatDate, formatValue, markers, arcAngle, parliamentRadius, seatSize, animationDuration, onMorphComplete, onAnimationStateChange, onTimelineReady, onAnimationProgress, onHoveredDataChange, hoveredCategory: externalHoveredCategory, maxSeats, parliamentTimestamp, enableBrush, onTimeRangeChange, minAllowedTime: minAllowedTimeConstraint, maxAllowedTime: maxAllowedTimeConstraint, showScaleIndicator, reposPerSeat, timelineEvents, showTimeline, timelineHeight, timelineOffset, brushColor, showCrosshair, onCrosshairMove }: UseMorphChartProps) => {
|
|
63
|
+
export declare const useMorphChart: ({ containerRef, data, categories, mode, paletteMode, width, height, margin, timeRange, showGrid, showAxes, axisLabelColor, axisLabelSize, formatDate, formatValue, markers, arcAngle, parliamentRadius, seatSize, animationDuration, onMorphComplete, onAnimationStateChange, onTimelineReady, onAnimationProgress, onHoveredDataChange, hoveredCategory: externalHoveredCategory, maxSeats, parliamentTimestamp, enableBrush, onTimeRangeChange, minAllowedTime: minAllowedTimeConstraint, maxAllowedTime: maxAllowedTimeConstraint, showScaleIndicator, reposPerSeat, timelineEvents, showTimeline, timelineHeight, timelineOffset, brushColor, showCrosshair, onCrosshairMove }: UseMorphChartProps) => {
|
|
62
64
|
isMorphing: boolean;
|
|
63
65
|
currentMode: MorphMode;
|
|
64
66
|
hoveredCategory: string | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaletteMode } from '@mui/material/styles';
|
|
1
2
|
import { D3StackedAreaCategory } from '../d3-stacked-area-chart/d3-stacked-area-chart.types';
|
|
2
3
|
export type MorphMode = 'area' | 'parliament' | 'morphing';
|
|
3
4
|
export type MorphChartDataPoint = {
|
|
@@ -25,6 +26,8 @@ export type MorphChartProps = {
|
|
|
25
26
|
categories: MorphChartCategory[];
|
|
26
27
|
/** Current visualization mode */
|
|
27
28
|
mode: 'parliament' | 'stacked-area';
|
|
29
|
+
/** Light/dark palette mode, affects seat border styling */
|
|
30
|
+
paletteMode?: PaletteMode;
|
|
28
31
|
/** Morph progress: 0 = fully area, 1 = fully parliament */
|
|
29
32
|
morphProgress?: number;
|
|
30
33
|
/** Chart dimensions */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaletteMode } from '@mui/material/styles';
|
|
1
2
|
import { Selection } from 'd3-selection';
|
|
2
3
|
import { MorphChartCategory, ParliamentLayout } from '../morph-chart.types';
|
|
3
4
|
/**
|
|
@@ -11,6 +12,7 @@ interface ParliamentRenderOptions {
|
|
|
11
12
|
addClasses?: boolean;
|
|
12
13
|
instanceId?: string;
|
|
13
14
|
parliamentRadius?: number;
|
|
15
|
+
paletteMode?: PaletteMode;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Render parliament seats into an SVG container
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaletteMode } from '@mui/material/styles';
|
|
1
2
|
import { RefObject } from 'react';
|
|
2
3
|
import { ChartConfig, HoveredData, ProcessedDataItem } from '../parliament-chart.types';
|
|
3
4
|
import { ArcSweepDirection } from '../utils/parliament-animation';
|
|
@@ -13,6 +14,7 @@ type UseParliamentChartProps = {
|
|
|
13
14
|
setActivePartyName: (name: string | null) => void;
|
|
14
15
|
chartConfig: ChartConfig;
|
|
15
16
|
seatSize: number;
|
|
17
|
+
paletteMode: PaletteMode;
|
|
16
18
|
shouldAnimate?: boolean;
|
|
17
19
|
animationDirection?: ArcSweepDirection;
|
|
18
20
|
onAnimationComplete?: () => void;
|
|
@@ -22,5 +24,5 @@ type UseParliamentChartProps = {
|
|
|
22
24
|
* Generates SVG visualization with seat circles and handles hover states
|
|
23
25
|
* for displaying repository statistics.
|
|
24
26
|
*/
|
|
25
|
-
export declare const useParliamentChart: ({ containerRef, processedData, totalRepositories, arcAngle, useEnhanced, maxSeats, setHoveredData, activePartyName, setActivePartyName, chartConfig, seatSize, shouldAnimate, animationDirection, onAnimationComplete }: UseParliamentChartProps) => void;
|
|
27
|
+
export declare const useParliamentChart: ({ containerRef, processedData, totalRepositories, arcAngle, useEnhanced, maxSeats, setHoveredData, activePartyName, setActivePartyName, chartConfig, seatSize, paletteMode, shouldAnimate, animationDirection, onAnimationComplete }: UseParliamentChartProps) => void;
|
|
26
28
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaletteMode } from '@mui/material/styles';
|
|
1
2
|
export declare const DEFAULT_CHART_CONFIG: {
|
|
2
3
|
readonly arcAngle: 180;
|
|
3
4
|
readonly maxSeats: 200;
|
|
@@ -37,14 +38,22 @@ export declare const MODERNE_VULNERABILITY_COLORS: {
|
|
|
37
38
|
DATA_MISSING: string;
|
|
38
39
|
};
|
|
39
40
|
/**
|
|
40
|
-
* Resolve a seat's fill + border from its category color.
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Resolve a seat's fill + border from its category color and label.
|
|
42
|
+
* Light mode: every category, including No LST, gets the classic two-tone
|
|
43
|
+
* dot (fill + darker border). Dark mode: regular categories get a border
|
|
44
|
+
* matching their fill (no visible ring); No LST gets a faint ghost fill and
|
|
45
|
+
* a dashed ghost border instead.
|
|
46
|
+
*
|
|
47
|
+
* `label` identifies No LST by name rather than by color — consumers theme
|
|
48
|
+
* No LST's color per palette mode, so it won't reliably match
|
|
49
|
+
* `HOLLOW_CATEGORY_COLORS` by hex.
|
|
44
50
|
*
|
|
45
51
|
* Pass `radius` to also get the proportional `strokeWidth` / `dashArray`.
|
|
46
52
|
*/
|
|
47
|
-
export declare function resolveSeatStyle(color: string, radius?: number
|
|
53
|
+
export declare function resolveSeatStyle(color: string, radius?: number, options?: {
|
|
54
|
+
paletteMode?: PaletteMode;
|
|
55
|
+
label?: string;
|
|
56
|
+
}): {
|
|
48
57
|
fill: string;
|
|
49
58
|
stroke: string;
|
|
50
59
|
dashed: boolean;
|