@moderneinc/react-charts 1.1.0 → 1.2.0-next.2f2ee2
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/chrono-chart/chrono-chart.component.d.ts +3 -0
- package/dist/components/chrono-chart/chrono-chart.types.d.ts +58 -0
- package/dist/components/chrono-chart/components/category-table.component.d.ts +3 -0
- package/dist/components/chrono-chart/components/category-table.types.d.ts +17 -0
- package/dist/components/chrono-chart/utils/data-transformer.d.ts +9 -0
- package/dist/components/d3-stacked-area-chart/d3-stacked-area-chart.component.d.ts +7 -0
- package/dist/components/d3-stacked-area-chart/d3-stacked-area-chart.types.d.ts +89 -0
- package/dist/components/d3-stacked-area-chart/hooks/use-d3-stacked-area.hook.d.ts +34 -0
- package/dist/components/morph-chart/hooks/shared/computations.d.ts +27 -0
- package/dist/components/morph-chart/hooks/shared/types.d.ts +22 -0
- package/dist/components/morph-chart/hooks/use-morph-chart.hook.d.ts +85 -0
- package/dist/components/morph-chart/index.d.ts +2 -0
- package/dist/components/morph-chart/morph-chart.component.d.ts +14 -0
- package/dist/components/morph-chart/morph-chart.types.d.ts +154 -0
- package/dist/components/morph-chart/utils/animation-constants.d.ts +23 -0
- package/dist/components/morph-chart/utils/animation-utils.d.ts +44 -0
- package/dist/components/morph-chart/utils/arc-path-calculator.d.ts +53 -0
- package/dist/components/morph-chart/utils/area-renderer.d.ts +24 -0
- package/dist/components/morph-chart/utils/bar-renderer.d.ts +19 -0
- package/dist/components/morph-chart/utils/gsap-orchestrator.d.ts +252 -0
- package/dist/components/morph-chart/utils/morph-interpolator.d.ts +96 -0
- package/dist/components/morph-chart/utils/parliament-renderer.d.ts +23 -0
- package/dist/components/morph-chart/utils/parliament-seat-extractor.d.ts +33 -0
- package/dist/components/morph-chart/utils/position-mapper.d.ts +48 -0
- package/dist/components/morph-chart/utils/segment-transformer.d.ts +70 -0
- package/dist/components/morph-chart/utils/svg-patterns.d.ts +19 -0
- package/dist/components/parliament-chart/hooks/{useParliamentChart.d.ts → use-parliament-chart.hook.d.ts} +6 -2
- package/dist/components/parliament-chart/{ParliamentChart.d.ts → parliament-chart.component.d.ts} +1 -1
- package/dist/components/parliament-chart/{ParliamentChart.types.d.ts → parliament-chart.types.d.ts} +6 -1
- package/dist/components/parliament-chart/utils/parliament-animation.d.ts +13 -0
- package/dist/components/stacked-area-chart/hooks/use-stacked-area-chart.hook.d.ts +6 -0
- package/dist/components/stacked-area-chart/stacked-area-chart.component.d.ts +10 -0
- package/dist/components/stacked-area-chart/stacked-area-chart.constants.d.ts +115 -0
- package/dist/components/stacked-area-chart/stacked-area-chart.types.d.ts +186 -0
- package/dist/components/stacked-area-chart/utils/color.utils.d.ts +4 -0
- package/dist/components/timeline-chart/hooks/use-timeline-chart.hook.d.ts +2 -0
- package/dist/components/timeline-chart/timeline-chart.component.d.ts +9 -0
- package/dist/components/timeline-chart/timeline-chart.types.d.ts +133 -0
- package/dist/components/timeline-chart/timeline-selected-events.component.d.ts +9 -0
- package/dist/index.cjs +144 -11
- package/dist/index.d.ts +21 -8
- package/dist/index.js +30451 -4879
- package/dist/theme/{defaultColors.d.ts → default-colors.d.ts} +8 -4
- package/dist/theme/timeline-defaults.d.ts +50 -0
- package/package.json +32 -13
- /package/dist/components/parliament-chart/{ParliamentChart.constants.d.ts → parliament-chart.constants.d.ts} +0 -0
- /package/dist/components/parliament-chart/utils/{parliamentArcCalculator.d.ts → parliament-arc-calculator.d.ts} +0 -0
- /package/dist/components/parliament-chart/utils/{parliamentChartData.utils.d.ts → parliament-chart-data.utils.d.ts} +0 -0
- /package/dist/components/parliament-chart/utils/{parliamentSvgEnhanced.d.ts → parliament-svg-enhanced.d.ts} +0 -0
- /package/dist/components/parliament-chart/utils/{parliamentSvgPatterns.d.ts → parliament-svg-patterns.d.ts} +0 -0
- /package/dist/components/parliament-chart/utils/{parliamentSvg.d.ts → parliament-svg.d.ts} +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Selection } from 'd3-selection';
|
|
2
|
+
import { MorphChartCategory } from '../morph-chart.types';
|
|
3
|
+
interface AreaRenderOptions {
|
|
4
|
+
xScale: (value: Date) => number;
|
|
5
|
+
yScale: (value: number) => number;
|
|
6
|
+
addClasses?: boolean;
|
|
7
|
+
instanceId?: string;
|
|
8
|
+
}
|
|
9
|
+
interface StackedDataPoint {
|
|
10
|
+
data: {
|
|
11
|
+
timestamp: number;
|
|
12
|
+
};
|
|
13
|
+
0: number;
|
|
14
|
+
1: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Render stacked areas into an SVG container
|
|
18
|
+
* @param container - D3 selection of the container (typically a <g> element)
|
|
19
|
+
* @param stackedData - D3 stacked data (output of d3.stack())
|
|
20
|
+
* @param categories - Category definitions with colors and opacity
|
|
21
|
+
* @param options - Rendering options (scales, styling)
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderStackedAreas(container: Selection<SVGGElement, unknown, null, undefined>, stackedData: StackedDataPoint[][], categories: MorphChartCategory[], options: AreaRenderOptions): void;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MorphChartCategory } from '../morph-chart.types';
|
|
2
|
+
export type StackedBarSegment = {
|
|
3
|
+
timestamp: number;
|
|
4
|
+
category: string;
|
|
5
|
+
dataKey: string;
|
|
6
|
+
y0: number;
|
|
7
|
+
y1: number;
|
|
8
|
+
value: number;
|
|
9
|
+
color: string;
|
|
10
|
+
isSpecialCategory: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Generate stacked bar data from time series
|
|
14
|
+
* Converts raw data into stacked segments for bar rendering
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateStackedBarData(data: Array<{
|
|
17
|
+
timestamp: number;
|
|
18
|
+
[key: string]: number;
|
|
19
|
+
}>, categories: MorphChartCategory[]): StackedBarSegment[];
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { Selection } from 'd3-selection';
|
|
2
|
+
import { MorphChartCategory } from '../morph-chart.types';
|
|
3
|
+
interface AnimationDurations {
|
|
4
|
+
seatsToBar: number;
|
|
5
|
+
axesReveal: number;
|
|
6
|
+
barSlide: number;
|
|
7
|
+
barsGrow: number;
|
|
8
|
+
barsToArea: number;
|
|
9
|
+
}
|
|
10
|
+
interface AnimationCallbacks {
|
|
11
|
+
onStageComplete?: (stage: string) => void;
|
|
12
|
+
onProgress?: (progress: number) => void;
|
|
13
|
+
onComplete?: () => void;
|
|
14
|
+
}
|
|
15
|
+
interface AnimationControls {
|
|
16
|
+
play: () => void;
|
|
17
|
+
pause: () => void;
|
|
18
|
+
reverse: () => void;
|
|
19
|
+
restart: () => void;
|
|
20
|
+
seek: (progress: number) => void;
|
|
21
|
+
seekToStage: (stageName: string) => void;
|
|
22
|
+
kill: () => void;
|
|
23
|
+
getProgress: () => number;
|
|
24
|
+
getCurrentStage: () => string;
|
|
25
|
+
getTimeline: () => gsap.core.Timeline;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* GSAP Orchestrator class that manages the entire animation sequence
|
|
29
|
+
*/
|
|
30
|
+
export declare class GSAPOrchestrator {
|
|
31
|
+
private timeline;
|
|
32
|
+
private currentStage;
|
|
33
|
+
private callbacks;
|
|
34
|
+
private durations;
|
|
35
|
+
constructor(durations: AnimationDurations, callbacks?: AnimationCallbacks);
|
|
36
|
+
/**
|
|
37
|
+
* Stage 1: Animate parliament seats collapsing into bar segments
|
|
38
|
+
*
|
|
39
|
+
* Transforms the circular parliament layout into a stacked vertical bar.
|
|
40
|
+
* Each seat morphs from its position in the parliament arc into a rectangular
|
|
41
|
+
* segment of a bar, maintaining visual continuity through smooth transitions.
|
|
42
|
+
*
|
|
43
|
+
* @param seats - D3 selection of parliament seat rectangles to animate
|
|
44
|
+
* @param targetPositions - Array of target positions for each seat, where each position defines the final rectangle geometry (x, y, width, height)
|
|
45
|
+
* @returns this - Returns the orchestrator instance for method chaining
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* **Visual transformation:**
|
|
49
|
+
* - Parliament seats (circular arc) → Vertical bar segments (stacked rectangles)
|
|
50
|
+
* - All seats animate simultaneously (no stagger)
|
|
51
|
+
* - Uses power2.inOut easing for smooth acceleration/deceleration
|
|
52
|
+
*
|
|
53
|
+
* **Data preservation:**
|
|
54
|
+
* - Original seat positions stored in data-orig-* attributes for potential reversal
|
|
55
|
+
* - Target positions must match seat count (indexed by array position)
|
|
56
|
+
*
|
|
57
|
+
* **Timeline integration:**
|
|
58
|
+
* - Added at 'seatsToBar' label
|
|
59
|
+
* - Duration: 30% of total animation (STAGE_DURATION_RATIOS.SEATS_TO_BAR)
|
|
60
|
+
* - Triggers onStageComplete callback when starting
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const seats = svg.selectAll('.parliament-seat');
|
|
65
|
+
* const targets = calculateBarPositions(seats);
|
|
66
|
+
* orchestrator.animateSeatsToBar(seats, targets);
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
animateSeatsToBar(seats: Selection<SVGRectElement, unknown, null, undefined>, targetPositions: Array<{
|
|
70
|
+
x: number;
|
|
71
|
+
y: number;
|
|
72
|
+
width: number;
|
|
73
|
+
height: number;
|
|
74
|
+
}>): GSAPOrchestrator;
|
|
75
|
+
/**
|
|
76
|
+
* Stage 2a: Reveal X and Y axes to establish timeline context
|
|
77
|
+
*
|
|
78
|
+
* Fades in the chart axes (x-axis with dates, y-axis with values) to provide
|
|
79
|
+
* spatial context before the bar slides to its position. This stage establishes
|
|
80
|
+
* the timeline framework that gives meaning to the bar's position.
|
|
81
|
+
*
|
|
82
|
+
* @param xAxisGroup - D3 selection of the x-axis group element (must have opacity: 0)
|
|
83
|
+
* @param yAxisGroup - D3 selection of the y-axis group element (must have opacity: 0)
|
|
84
|
+
* @returns this - Returns the orchestrator instance for method chaining
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* **Visual transformation:**
|
|
88
|
+
* - Axes fade in from opacity 0 → 1
|
|
89
|
+
* - Uses full stage duration for smooth, gradual reveal
|
|
90
|
+
* - Both axes animate simultaneously
|
|
91
|
+
* - Uses power2.inOut easing for professional motion
|
|
92
|
+
*
|
|
93
|
+
* **Data requirements:**
|
|
94
|
+
* - Axes must already exist in the DOM with opacity: 0
|
|
95
|
+
* - xAxisGroup should contain tick marks and labels for dates
|
|
96
|
+
* - yAxisGroup should contain tick marks and labels for values
|
|
97
|
+
*
|
|
98
|
+
* **Timeline integration:**
|
|
99
|
+
* - Added at 'axesReveal' label (after seats→bar transformation)
|
|
100
|
+
* - Duration: 12.5% of total animation (STAGE_DURATION_RATIOS.AXES_REVEAL)
|
|
101
|
+
* - Happens **before** bar slide to establish context first
|
|
102
|
+
* - Triggers onStageComplete callback when starting
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* const xAxis = svg.select('.x-axis').style('opacity', 0);
|
|
107
|
+
* const yAxis = svg.select('.y-axis').style('opacity', 0);
|
|
108
|
+
* orchestrator.animateAxesReveal(xAxis, yAxis);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
animateAxesReveal(xAxisGroup: Selection<SVGGElement, unknown, null, undefined>, yAxisGroup: Selection<SVGGElement, unknown, null, undefined>): GSAPOrchestrator;
|
|
112
|
+
/**
|
|
113
|
+
* Stage 2b: Slide the collapsed bar horizontally to its timeline position
|
|
114
|
+
*
|
|
115
|
+
* Moves the vertical bar created in Stage 1 to its correct x-position on the timeline.
|
|
116
|
+
* This stage establishes spatial context by positioning the bar relative to the time axis.
|
|
117
|
+
*
|
|
118
|
+
* @param barSegments - D3 selection of bar segment rectangles to slide
|
|
119
|
+
* @param targetX - Final x-coordinate where the bar should be positioned on the timeline
|
|
120
|
+
* @returns this - Returns the orchestrator instance for method chaining
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* **Visual transformation:**
|
|
124
|
+
* - Horizontal slide only (y-position and height remain constant)
|
|
125
|
+
* - All bar segments move together as a unified column
|
|
126
|
+
* - Uses power2.out easing for smooth deceleration (settling into place)
|
|
127
|
+
*
|
|
128
|
+
* **Timeline integration:**
|
|
129
|
+
* - Added at 'barSlide' label (after seats→bar transformation)
|
|
130
|
+
* - Duration: 25% of total animation (STAGE_DURATION_RATIOS.BAR_SLIDE)
|
|
131
|
+
* - Triggers onStageComplete callback when starting
|
|
132
|
+
*
|
|
133
|
+
* **Positioning:**
|
|
134
|
+
* - targetX typically corresponds to a specific timestamp on the x-axis
|
|
135
|
+
* - For "rightmost edge" positioning: targetX = width - margin.right
|
|
136
|
+
* - For "middle date" positioning: targetX = xScale(middleTimestamp)
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* const barSegments = svg.selectAll('.bar-segment');
|
|
141
|
+
* const rightEdgeX = width - margin.right;
|
|
142
|
+
* orchestrator.animateBarSlide(barSegments, rightEdgeX);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
animateBarSlide(barSegments: Selection<SVGRectElement, unknown, null, undefined>, targetX: number): GSAPOrchestrator;
|
|
146
|
+
/**
|
|
147
|
+
* Stage 3: Grow other bars with ripple effect from parliament position
|
|
148
|
+
*
|
|
149
|
+
* Animates the historical bars growing from the baseline, creating a wave-like
|
|
150
|
+
* ripple effect radiating outward from the parliament bar's position. Bars closer
|
|
151
|
+
* to the parliament position appear first, with increasing delay for distant bars.
|
|
152
|
+
*
|
|
153
|
+
* @param otherBars - D3 selection of bars at other timestamps (excluding parliament bar)
|
|
154
|
+
* @param parliamentIndex - Timeline index of the parliament bar (center of ripple)
|
|
155
|
+
* @param staggerDelay - Delay multiplier per distance unit (default: TIMING.RIPPLE_STAGGER_DELAY = 0.05)
|
|
156
|
+
* @returns this - Returns the orchestrator instance for method chaining
|
|
157
|
+
*
|
|
158
|
+
* @remarks
|
|
159
|
+
* **Visual transformation:**
|
|
160
|
+
* - Bars grow vertically from height=0 (baseline) to final stacked height
|
|
161
|
+
* - Ripple effect: delay = |barIndex - parliamentIndex| × staggerDelay
|
|
162
|
+
* - Bars furthest from parliament bar appear last (e.g., delay of 0.50s for 10 bars away)
|
|
163
|
+
* - Uses power2.out easing for smooth upward growth
|
|
164
|
+
*
|
|
165
|
+
* **Data requirements:**
|
|
166
|
+
* Each bar element must have these data attributes:
|
|
167
|
+
* - `data-final-y`: Target y-coordinate (top of bar)
|
|
168
|
+
* - `data-final-height`: Target height
|
|
169
|
+
* - `data-timestamp-index`: Position in timeline array
|
|
170
|
+
* - `data-baseline-y`: Y-coordinate of chart baseline (for fromTo animation)
|
|
171
|
+
*
|
|
172
|
+
* **Timeline integration:**
|
|
173
|
+
* - Added at 'barsGrow' label (after bar slide)
|
|
174
|
+
* - Duration: 25% of total animation (STAGE_DURATION_RATIOS.BARS_GROW)
|
|
175
|
+
* - Individual bars have additional stagger delays
|
|
176
|
+
* - Triggers onStageComplete callback when starting
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const otherBars = svg.selectAll('.bar:not(.parliament-bar)');
|
|
181
|
+
* const parliamentIndex = 15; // Parliament bar is at index 15
|
|
182
|
+
* orchestrator.animateBarsGrow(otherBars, parliamentIndex, 0.05);
|
|
183
|
+
* // Bars will appear with 50ms delay per timeline distance
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
animateBarsGrow(otherBars: Selection<SVGRectElement, unknown, null, undefined>, parliamentIndex: number, staggerDelay?: number): GSAPOrchestrator;
|
|
187
|
+
/**
|
|
188
|
+
* Stage 4: Morph bars into curved areas using path interpolation
|
|
189
|
+
*
|
|
190
|
+
* Transforms rectangular stacked bars into smooth, curved area paths. This is
|
|
191
|
+
* the final stage that creates the traditional stacked area chart appearance.
|
|
192
|
+
* Uses GSAP's path morphing to interpolate from bar rectangles to bezier curves.
|
|
193
|
+
*
|
|
194
|
+
* @param allBars - D3 selection of all bar rectangles (will be hidden during morph)
|
|
195
|
+
* @param morphPaths - D3 selection of SVG paths used for morphing (one per category)
|
|
196
|
+
* @param targetAreaPaths - Map of category IDs to target SVG path strings (curved areas)
|
|
197
|
+
* @param categories - Array of category definitions (used for grouping)
|
|
198
|
+
* @returns this - Returns the orchestrator instance for method chaining
|
|
199
|
+
*
|
|
200
|
+
* @remarks
|
|
201
|
+
* **Visual transformation:**
|
|
202
|
+
* - Rectangular bars (straight edges) → Curved area paths (smooth curves)
|
|
203
|
+
* - Bars fade out (opacity: 0), morphing paths fade in (opacity: 1)
|
|
204
|
+
* - GSAP interpolates path data attribute from bar shape to curve shape
|
|
205
|
+
* - Uses power2.inOut easing for smooth shape morphing
|
|
206
|
+
*
|
|
207
|
+
* **Path morphing technique:**
|
|
208
|
+
* 1. Each category has a morphPath element that starts as combined bar outline
|
|
209
|
+
* 2. morphPath's `d` attribute animates from bar path → area path
|
|
210
|
+
* 3. GSAP handles point interpolation automatically
|
|
211
|
+
* 4. Original bars hidden to avoid visual duplication
|
|
212
|
+
*
|
|
213
|
+
* **Data requirements:**
|
|
214
|
+
* - morphPaths must have `data-category` attribute matching category ID
|
|
215
|
+
* - allBars must have CSS class `category-{categoryKey}` for grouping
|
|
216
|
+
* - targetAreaPaths keys must match category IDs
|
|
217
|
+
*
|
|
218
|
+
* **Timeline integration:**
|
|
219
|
+
* - Added at 'barsToArea' label (after bars grow)
|
|
220
|
+
* - Duration: 20% of total animation (STAGE_DURATION_RATIOS.BARS_TO_AREA)
|
|
221
|
+
* - Triggers onStageComplete callback when starting
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```ts
|
|
225
|
+
* const allBars = svg.selectAll('.stacked-bar rect');
|
|
226
|
+
* const morphPaths = svg.selectAll('.morph-path');
|
|
227
|
+
* const targetPaths = new Map([
|
|
228
|
+
* ['java', 'M 100 300 C 150 280, 200 270, 250 260 L 250 300 Z'],
|
|
229
|
+
* ['python', 'M 100 260 C 150 240, 200 230, 250 220 L 250 260 Z']
|
|
230
|
+
* ]);
|
|
231
|
+
* orchestrator.animateBarsToArea(allBars, morphPaths, targetPaths, categories);
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
animateBarsToArea(allBars: Selection<SVGRectElement, unknown, null, undefined>, morphPaths: Selection<SVGPathElement, unknown, null, undefined>, targetAreaPaths: Map<string, string>, _categories: MorphChartCategory[]): GSAPOrchestrator;
|
|
235
|
+
/**
|
|
236
|
+
* Handle timeline progress updates
|
|
237
|
+
*/
|
|
238
|
+
private handleProgress;
|
|
239
|
+
/**
|
|
240
|
+
* Get animation control interface
|
|
241
|
+
*/
|
|
242
|
+
getControls(): AnimationControls;
|
|
243
|
+
/**
|
|
244
|
+
* Start the animation
|
|
245
|
+
*/
|
|
246
|
+
play(): void;
|
|
247
|
+
/**
|
|
248
|
+
* Clean up and destroy the timeline
|
|
249
|
+
*/
|
|
250
|
+
destroy(): void;
|
|
251
|
+
}
|
|
252
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { AreaPoint, SeatPosition } from '../morph-chart.types';
|
|
2
|
+
/**
|
|
3
|
+
* Interpolate between two numbers
|
|
4
|
+
*/
|
|
5
|
+
export declare function lerp(start: number, end: number, progress: number): number;
|
|
6
|
+
/**
|
|
7
|
+
* Easing function for smooth morphing (ease-in-out cubic)
|
|
8
|
+
*/
|
|
9
|
+
export declare function easeInOutCubic(t: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Easing function for elastic effect (optional, for more dramatic animation)
|
|
12
|
+
*/
|
|
13
|
+
export declare function easeOutElastic(t: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Map parliament seats to their corresponding positions at the rightmost edge of the area chart
|
|
16
|
+
* Seats should map to the vertical position in the stacked area based on their category
|
|
17
|
+
*
|
|
18
|
+
* @param seats - Parliament seat positions
|
|
19
|
+
* @param areaSlice - Area chart data points at the rightmost time slice
|
|
20
|
+
* @param chartWidth - Width of the area chart
|
|
21
|
+
* @param chartHeight - Height of the area chart
|
|
22
|
+
* @param margin - Chart margins
|
|
23
|
+
*/
|
|
24
|
+
export declare function mapSeatsToRightEdge(seats: SeatPosition[], areaSlice: AreaPoint[], chartWidth: number, chartHeight: number): Map<SeatPosition, {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Calculate interpolated seat position during parliament → area morphing
|
|
30
|
+
*
|
|
31
|
+
* Phase 1 (0.0 - 0.5): Seats move from parliament positions to right edge of area chart
|
|
32
|
+
* Phase 2 (0.5 - 1.0): Seats stay at right edge while areas expand
|
|
33
|
+
*
|
|
34
|
+
* @param seat - Original parliament seat position
|
|
35
|
+
* @param targetPosition - Target position at right edge
|
|
36
|
+
* @param progress - Overall morph progress (0 = parliament, 1 = area)
|
|
37
|
+
*/
|
|
38
|
+
export declare function interpolateSeatToEdge(seat: SeatPosition, targetPosition: {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
}, progress: number): {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
opacity: number;
|
|
45
|
+
radius: number;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Calculate interpolated area expansion during parliament → area morphing
|
|
49
|
+
*
|
|
50
|
+
* Phase 1 (0.0 - 0.5): Areas are compressed to right edge (not visible)
|
|
51
|
+
* Phase 2 (0.5 - 1.0): Areas expand leftward from right edge
|
|
52
|
+
*
|
|
53
|
+
* @param progress - Overall morph progress (0 = parliament, 1 = area)
|
|
54
|
+
* @param chartWidth - Full width of area chart
|
|
55
|
+
*/
|
|
56
|
+
export declare function interpolateAreaExpansion(progress: number, chartWidth: number): {
|
|
57
|
+
visibleWidth: number;
|
|
58
|
+
opacity: number;
|
|
59
|
+
clipX: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Calculate interpolated positions for area → parliament morphing (reverse)
|
|
63
|
+
*
|
|
64
|
+
* Phase 1 (0.0 - 0.5): Areas compress to right edge
|
|
65
|
+
* Phase 2 (0.5 - 1.0): Seats expand from right edge to parliament layout
|
|
66
|
+
*/
|
|
67
|
+
export declare function interpolateAreaToParliament(progress: number, chartWidth: number, seat: SeatPosition, edgePosition: {
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
}): {
|
|
71
|
+
areaClipX: number;
|
|
72
|
+
areaOpacity: number;
|
|
73
|
+
seatX: number;
|
|
74
|
+
seatY: number;
|
|
75
|
+
seatOpacity: number;
|
|
76
|
+
seatRadius: number;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Calculate the vertical stacking position for area points
|
|
80
|
+
* Used to determine where seats should map to at the right edge
|
|
81
|
+
*/
|
|
82
|
+
export declare function calculateStackedPosition(value: number, previousSum: number, maxValue: number, chartHeight: number): {
|
|
83
|
+
y0: number;
|
|
84
|
+
y1: number;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Extract the rightmost time slice from area chart data
|
|
88
|
+
* This represents the same point-in-time as the parliament chart
|
|
89
|
+
*/
|
|
90
|
+
export declare function extractRightmostSlice(data: Array<{
|
|
91
|
+
timestamp: number;
|
|
92
|
+
[key: string]: number;
|
|
93
|
+
}>, categories: Array<{
|
|
94
|
+
dataKey: string;
|
|
95
|
+
label: string;
|
|
96
|
+
}>, chartHeight: number): AreaPoint[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Selection } from 'd3-selection';
|
|
2
|
+
import { MorphChartCategory, ParliamentLayout } from '../morph-chart.types';
|
|
3
|
+
/**
|
|
4
|
+
* Sanitize category name for use in CSS class names
|
|
5
|
+
* Replaces spaces, slashes, and other special characters with hyphens
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeCategoryForClass(category: string): string;
|
|
8
|
+
interface ParliamentRenderOptions {
|
|
9
|
+
centerX: number;
|
|
10
|
+
centerY: number;
|
|
11
|
+
addClasses?: boolean;
|
|
12
|
+
instanceId?: string;
|
|
13
|
+
parliamentRadius?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render parliament seats into an SVG container
|
|
17
|
+
* @param container - D3 selection of the container (typically a <g> element)
|
|
18
|
+
* @param layout - Parliament layout with seat positions
|
|
19
|
+
* @param categories - Category definitions with colors
|
|
20
|
+
* @param options - Rendering options (positioning, styling)
|
|
21
|
+
*/
|
|
22
|
+
export declare function renderParliamentSeats(container: Selection<SVGGElement, unknown, null, undefined>, layout: ParliamentLayout, categories: MorphChartCategory[], options: ParliamentRenderOptions): void;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ParliamentLayout } from '../morph-chart.types';
|
|
2
|
+
type Party = {
|
|
3
|
+
id: string | number;
|
|
4
|
+
name: string;
|
|
5
|
+
seats: number;
|
|
6
|
+
colour: string;
|
|
7
|
+
};
|
|
8
|
+
type ParliamentOptions = {
|
|
9
|
+
arcAngle: number;
|
|
10
|
+
arcAngleFlexibility?: number;
|
|
11
|
+
radius: number;
|
|
12
|
+
seatSize: number;
|
|
13
|
+
minSeatSize: number;
|
|
14
|
+
maxSeatSize: number;
|
|
15
|
+
spacing: number;
|
|
16
|
+
innerRadiusRatio: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Generate parliament layout with seat positions
|
|
20
|
+
* Based on the logic from parliament-svg-enhanced.ts but returns position data
|
|
21
|
+
* instead of SVG elements
|
|
22
|
+
*/
|
|
23
|
+
export declare function generateParliamentLayout(parties: Party[], options: ParliamentOptions): ParliamentLayout;
|
|
24
|
+
/**
|
|
25
|
+
* Convert category data to parliament party format
|
|
26
|
+
*/
|
|
27
|
+
export declare function categoriesToParties(categories: Array<{
|
|
28
|
+
dataKey: string;
|
|
29
|
+
label: string;
|
|
30
|
+
color: string;
|
|
31
|
+
value: number;
|
|
32
|
+
}>, totalRepositories: number, maxSeats: number): Party[];
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ScaleLinear, ScaleTime } from 'd3-scale';
|
|
2
|
+
import { ParliamentLayout, SeatPosition } from '../morph-chart.types';
|
|
3
|
+
/**
|
|
4
|
+
* Map parliament seats to their target positions at the right edge of the stacked area chart
|
|
5
|
+
* Seats can be positioned at the top (y1) or distributed vertically within their category's segment
|
|
6
|
+
*
|
|
7
|
+
* NOTE: stackData uses dataKey, but parliamentLayout.seats use category labels.
|
|
8
|
+
* We need to match by label, so stackData must contain label information.
|
|
9
|
+
*
|
|
10
|
+
* @param distributeVertically - If true, seats are spread between y0 and y1; if false, all seats at y1
|
|
11
|
+
*/
|
|
12
|
+
export declare function mapSeatsToStackEdge(parliamentLayout: ParliamentLayout, stackData: Array<{
|
|
13
|
+
dataKey: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
y0: number;
|
|
16
|
+
y1: number;
|
|
17
|
+
timestamp?: number;
|
|
18
|
+
isSpecialCategory?: boolean;
|
|
19
|
+
}>, xScale: ScaleTime<number, number>, yScale: ScaleLinear<number, number>, chartWidth: number, chartHeight: number, distributeVertically?: boolean): Map<SeatPosition, {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Extract the rightmost slice of stacked area data
|
|
25
|
+
* This represents the same point-in-time as the parliament chart
|
|
26
|
+
*
|
|
27
|
+
* IMPORTANT: The stack is generated using original category order.
|
|
28
|
+
* We build the slice in original order to match the stack generation.
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractRightmostStackSlice(data: Array<{
|
|
31
|
+
timestamp: number;
|
|
32
|
+
[key: string]: number;
|
|
33
|
+
}>, categories: Array<{
|
|
34
|
+
dataKey: string;
|
|
35
|
+
label: string;
|
|
36
|
+
color: string;
|
|
37
|
+
parliamentMapping?: {
|
|
38
|
+
isSpecialCategory?: boolean;
|
|
39
|
+
};
|
|
40
|
+
}>, _yScale: ScaleLinear<number, number>): Array<{
|
|
41
|
+
dataKey: string;
|
|
42
|
+
label: string;
|
|
43
|
+
y0: number;
|
|
44
|
+
y1: number;
|
|
45
|
+
value: number;
|
|
46
|
+
timestamp: number;
|
|
47
|
+
isSpecialCategory?: boolean;
|
|
48
|
+
}>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ScaleLinear, ScaleTime } from 'd3-scale';
|
|
2
|
+
import { MorphChartCategory } from '../morph-chart.types';
|
|
3
|
+
interface StackedSeriesDataPoint {
|
|
4
|
+
data: {
|
|
5
|
+
timestamp: number;
|
|
6
|
+
};
|
|
7
|
+
0: number;
|
|
8
|
+
1: number;
|
|
9
|
+
}
|
|
10
|
+
export type SegmentTransform = {
|
|
11
|
+
segmentId: string;
|
|
12
|
+
dataKey: string;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
rotation: number;
|
|
17
|
+
length: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Calculate curve data for stacked area chart
|
|
21
|
+
* Generates the curved path data that segments will transform into
|
|
22
|
+
*
|
|
23
|
+
* @param stackedData - D3 stacked data
|
|
24
|
+
* @param categories - Category definitions
|
|
25
|
+
* @param xScale - X scale (time)
|
|
26
|
+
* @param yScale - Y scale (values)
|
|
27
|
+
* @returns Array of curve data for each category
|
|
28
|
+
*/
|
|
29
|
+
export declare function calculateStackedCurveData(stackedData: StackedSeriesDataPoint[][], categories: MorphChartCategory[], xScale: ScaleTime<number, number>, yScale: ScaleLinear<number, number>): Array<{
|
|
30
|
+
dataKey: string;
|
|
31
|
+
category: string;
|
|
32
|
+
points: Array<{
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
timestamp: number;
|
|
36
|
+
}>;
|
|
37
|
+
pathData: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Calculate transformations for horizontal bar top segments to align with curves
|
|
41
|
+
* Each segment gets position, rotation, and length data
|
|
42
|
+
*
|
|
43
|
+
* @param barSegments - Array of bar segments with their positions
|
|
44
|
+
* @param curveData - Calculated curve data for all categories
|
|
45
|
+
* @param segmentLength - Desired length of each segment
|
|
46
|
+
* @returns Array of transformation data for each segment
|
|
47
|
+
*/
|
|
48
|
+
export declare function calculateSegmentTransforms(barSegments: Array<{
|
|
49
|
+
dataKey: string;
|
|
50
|
+
timestamp: number;
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
width: number;
|
|
54
|
+
}>, curveData: ReturnType<typeof calculateStackedCurveData>, segmentLength: number): SegmentTransform[];
|
|
55
|
+
/**
|
|
56
|
+
* Extract bar top segment positions from rendered bars
|
|
57
|
+
* Identifies the top edge of each bar segment for transformation
|
|
58
|
+
*
|
|
59
|
+
* @param svg - SVG container with bar elements
|
|
60
|
+
* @returns Array of segment position data
|
|
61
|
+
*/
|
|
62
|
+
export declare function extractBarTopPositions(svg: SVGSVGElement): Array<{
|
|
63
|
+
dataKey: string;
|
|
64
|
+
timestamp: number;
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
element: SVGElement;
|
|
69
|
+
}>;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Selection } from 'd3-selection';
|
|
2
|
+
/**
|
|
3
|
+
* Add all hatch pattern definitions to an SVG's <defs> element
|
|
4
|
+
* Call this once when setting up the SVG
|
|
5
|
+
* @param svg - The SVG selection to add patterns to
|
|
6
|
+
* @param instancePrefix - Unique prefix for this instance to avoid ID conflicts
|
|
7
|
+
*/
|
|
8
|
+
export declare function addHatchPatternDefs(svg: Selection<SVGSVGElement, unknown, null, undefined>, instancePrefix: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Transform a color to use instance-specific pattern IDs
|
|
11
|
+
* Converts 'url(#patternName)' to 'url(#prefix-patternName)'
|
|
12
|
+
*/
|
|
13
|
+
export declare function transformColorForInstance(color: string, instancePrefix: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get the display color for a category, handling pattern URLs
|
|
16
|
+
* Returns the line color for patterns (better visibility in hover states)
|
|
17
|
+
* Works with both instance-specific and generic pattern URLs
|
|
18
|
+
*/
|
|
19
|
+
export declare function getDisplayColor(color: string): string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
|
-
import { ChartConfig, HoveredData, ProcessedDataItem } from '../
|
|
2
|
+
import { ChartConfig, HoveredData, ProcessedDataItem } from '../parliament-chart.types';
|
|
3
|
+
import { ArcSweepDirection } from '../utils/parliament-animation';
|
|
3
4
|
type UseParliamentChartProps = {
|
|
4
5
|
containerRef: RefObject<HTMLDivElement>;
|
|
5
6
|
processedData: ProcessedDataItem[];
|
|
@@ -12,11 +13,14 @@ type UseParliamentChartProps = {
|
|
|
12
13
|
setActivePartyName: (name: string | null) => void;
|
|
13
14
|
chartConfig: ChartConfig;
|
|
14
15
|
seatSize: number;
|
|
16
|
+
shouldAnimate?: boolean;
|
|
17
|
+
animationDirection?: ArcSweepDirection;
|
|
18
|
+
onAnimationComplete?: () => void;
|
|
15
19
|
};
|
|
16
20
|
/**
|
|
17
21
|
* Hook that manages parliament chart rendering and interactivity.
|
|
18
22
|
* Generates SVG visualization with seat circles and handles hover states
|
|
19
23
|
* for displaying repository statistics.
|
|
20
24
|
*/
|
|
21
|
-
export declare const useParliamentChart: ({ containerRef, processedData, totalRepositories, arcAngle, useEnhanced, maxSeats, setHoveredData, activePartyName, setActivePartyName, chartConfig, seatSize }: UseParliamentChartProps) => void;
|
|
25
|
+
export declare const useParliamentChart: ({ containerRef, processedData, totalRepositories, arcAngle, useEnhanced, maxSeats, setHoveredData, activePartyName, setActivePartyName, chartConfig, seatSize, shouldAnimate, animationDirection, onAnimationComplete }: UseParliamentChartProps) => void;
|
|
22
26
|
export {};
|
package/dist/components/parliament-chart/{ParliamentChart.d.ts → parliament-chart.component.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FunctionComponent } from 'react';
|
|
2
|
-
import { ParliamentChartProps } from './
|
|
2
|
+
import { ParliamentChartProps } from './parliament-chart.types';
|
|
3
3
|
/**
|
|
4
4
|
* Renders an interactive parliament-style chart visualization for repository statistics.
|
|
5
5
|
* Displays repository counts as seats in a semi-circular or arc layout, with scaling
|
package/dist/components/parliament-chart/{ParliamentChart.types.d.ts → parliament-chart.types.d.ts}
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ParliamentChartTheme } from '../../theme/
|
|
1
|
+
import { ParliamentChartTheme } from '../../theme/default-colors';
|
|
2
|
+
import { ArcSweepDirection } from './utils/parliament-animation';
|
|
2
3
|
type ParliamentDataSeries = {
|
|
3
4
|
value: number;
|
|
4
5
|
label: string;
|
|
@@ -12,6 +13,10 @@ export type ParliamentChartProps = {
|
|
|
12
13
|
arcAngle?: number;
|
|
13
14
|
useEnhanced?: boolean;
|
|
14
15
|
theme?: ParliamentChartTheme;
|
|
16
|
+
showTable?: boolean;
|
|
17
|
+
shouldAnimate?: boolean;
|
|
18
|
+
animationDirection?: ArcSweepDirection;
|
|
19
|
+
onAnimationComplete?: () => void;
|
|
15
20
|
};
|
|
16
21
|
export type ProcessedDataItem = {
|
|
17
22
|
id: string | number;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ArcSweepDirection = 'left-to-right' | 'right-to-left';
|
|
2
|
+
/**
|
|
3
|
+
* Animates the parliament chart with an arc sweep reveal effect.
|
|
4
|
+
* Creates a clipPath that progressively reveals or collapses seats.
|
|
5
|
+
*
|
|
6
|
+
* @param svgElement - The SVG element containing the parliament chart
|
|
7
|
+
* @param arcAngle - The arc angle in degrees (e.g., 200)
|
|
8
|
+
* @param radius - The radius of the parliament arc
|
|
9
|
+
* @param direction - Direction of the sweep: 'left-to-right' (expand) or 'right-to-left' (collapse)
|
|
10
|
+
* @param duration - Animation duration in milliseconds (default: 900ms)
|
|
11
|
+
* @param onComplete - Optional callback fired when animation completes
|
|
12
|
+
*/
|
|
13
|
+
export declare function animateArcSweep(svgElement: SVGSVGElement, arcAngle: number, radius: number, direction?: ArcSweepDirection, duration?: number, onComplete?: () => void): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UseStackedAreaChartProps, UseStackedAreaChartReturn } from '../stacked-area-chart.types';
|
|
2
|
+
/**
|
|
3
|
+
* Manages stacked area chart data validation, processing, and formatting.
|
|
4
|
+
* Handles category validation, timestamp ranges, and max value computation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useStackedAreaChart(props: UseStackedAreaChartProps): UseStackedAreaChartReturn;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
import { StackedAreaChartProps } from './stacked-area-chart.types';
|
|
3
|
+
/**
|
|
4
|
+
* Displays time-series data as a stacked area chart with responsive sizing,
|
|
5
|
+
* customizable colors, interactive tooltips, and smooth animations.
|
|
6
|
+
*
|
|
7
|
+
* Designed for ParliamentChart transitions - data structure supports point-in-time
|
|
8
|
+
* views enabling animated morphing between visualizations.
|
|
9
|
+
*/
|
|
10
|
+
export declare const StackedAreaChart: FunctionComponent<StackedAreaChartProps>;
|