@amcharts/amcharts5-mcp 1.0.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.
@@ -0,0 +1,667 @@
1
+ ---
2
+ name: amcharts5
3
+ description: >
4
+ Build any chart with the amCharts 5 JavaScript library — XY (line, area, bar,
5
+ column, candlestick, scatter), pie, donut, funnel, pyramid, geographic maps,
6
+ hierarchy (treemap, sunburst, force-directed), flow (Sankey, chord, arc), radar,
7
+ gauge, stock/financial, word cloud, Venn, Gantt, and timeline charts. Use this
8
+ skill whenever the user mentions amCharts, asks for amCharts 5 code, needs a
9
+ JavaScript chart built with amCharts, wants to create any data visualization
10
+ using the amCharts library, is migrating from amCharts v4 to v5, or needs help
11
+ with amCharts configuration, theming, exporting, tooltips, legends, or axis
12
+ setup. Also use when the user mentions chart types that amCharts supports, even
13
+ if they don't say "amCharts" explicitly, if amCharts is already present in the
14
+ project or was discussed in the conversation.
15
+ metadata:
16
+ author: amCharts
17
+ version: 1.0.0
18
+ category: code
19
+ tags: [charts, maps]
20
+ documentation: https://amcharts.com/docs/v5
21
+ support: contact@amcharts.com
22
+ ---
23
+
24
+ # amCharts 5
25
+
26
+ Build any chart with the amCharts 5 JavaScript charting library.
27
+
28
+ Docs: https://www.amcharts.com/docs/v5/
29
+
30
+ ## Critical rules — apply to ALL chart types
31
+
32
+ 1. **Check demos first (if you can browse the web)** — Before building a chart, search or browse https://www.amcharts.com/demos/ for a demo that matches the user's request. Demo source code is the most reliable starting point — adapt it rather than writing from scratch. Skip this step if you have no web access.
33
+ 2. **Read the docs (if you can browse the web)** — For unfamiliar features or configuration, check https://www.amcharts.com/docs/v5/ for guides and tutorials. The docs explain concepts, patterns, and options that the class reference alone does not. Skip if you have no web access.
34
+ 3. **Always use amCharts 5** — never v3 or v4. The APIs are completely different.
35
+ 4. **Use `.new()` factory** — never `new ClassName()`. Every object is created via `ClassName.new(root, { settings })`.
36
+ 5. **Root is always the first argument** to `.new()` (except Root itself, which takes a div ID).
37
+ 6. **Set data last** — once data is set, objects are created. Configuration applied after may not take effect.
38
+ 7. **Colors use `am5.color()`** — e.g. `am5.color(0xff0000)`, `am5.color("#ff0000")`, or `am5.color("rgb(255,0,0)")`. Never raw hex strings.
39
+ 8. **Percent values use `am5.percent()`** — e.g. `am5.percent(50)`, not `50` or `"50%"`.
40
+ 9. **Every axis needs a renderer** — `am5xy.AxisRendererX.new(root, {})` or `AxisRendererY`.
41
+ 10. **CategoryAxis must receive data** — call `xAxis.data.setAll(data)` in addition to series data. Forgetting this is the #1 bug.
42
+ 11. **DateAxis values must be timestamps** — use `new Date().getTime()`, not Date objects.
43
+ 12. **Disposal is mandatory in SPAs** — call `root.dispose()` on component unmount. Not `chart.dispose()`.
44
+ 13. **Canvas-rendered** — CSS cannot style chart internals. Use amCharts settings/templates instead.
45
+ 14. **Dark backgrounds require Dark theme** — If the user requests or the page clearly has a dark background, always add `am5themes_Dark.new(root)` to `root.setThemes()` alongside Animated. Without it, labels, grid, and tooltips will be invisible. If the background is not clearly dark, default to white/light and do NOT add the Dark theme unless asked.
46
+ 15. **Use default amCharts colors** — Do NOT invent custom color palettes unless the user explicitly asks for specific colors. amCharts assigns colors automatically from its built-in ColorSet. If you need a color programmatically, use `chart.get("colors").getIndex(index)` or `chart.get("colors").next()`. For pie/percent charts, use `series.get("colors")` instead.
47
+
48
+ ## Package / module map
49
+
50
+ | Chart family | ES module import | CDN script | Main classes |
51
+ |-------------|-----------------|-----------|-------------|
52
+ | Core | `@amcharts/amcharts5` | `index.js` | Root, Theme, Legend, Tooltip, Label, Container |
53
+ | XY charts | `@amcharts/amcharts5/xy` | `xy.js` | XYChart, axes, series |
54
+ | Pie / Sliced | `@amcharts/amcharts5/percent` | `percent.js` | PieChart, SlicedChart, PieSeries, FunnelSeries, PyramidSeries, PictorialStackedSeries |
55
+ | Map | `@amcharts/amcharts5/map` | `map.js` | MapChart, MapPolygonSeries, MapPointSeries, MapLineSeries |
56
+ | Hierarchy | `@amcharts/amcharts5/hierarchy` | `hierarchy.js` | Treemap, VoronoiTreemap, ForceDirected, Sunburst, Pack, Partition, Tree |
57
+ | Flow | `@amcharts/amcharts5/flow` | `flow.js` | Sankey, Chord, ChordDirected, ChordNonRibbon, ArcDiagram |
58
+ | Radar | `@amcharts/amcharts5/radar` | `radar.js` | RadarChart, AxisRendererCircular, AxisRendererRadial |
59
+ | Stock | `@amcharts/amcharts5/stock` | `stock.js` | StockChart, StockPanel, StockToolbar |
60
+ | Timeline | `@amcharts/amcharts5/timeline` | `timeline.js` | CurveChart, SerpentineChart, SpiralChart, CurveLineSeries, CurveColumnSeries |
61
+ | Word cloud | `@amcharts/amcharts5/wc` | `wc.js` | WordCloud |
62
+ | Venn | `@amcharts/amcharts5/venn` | `venn.js` | Venn |
63
+ | Gantt | `@amcharts/amcharts5/gantt` | `gantt.js` | Gantt (also needs xy) |
64
+ | Geodata | `@amcharts/amcharts5-geodata/*` | `geodata/*.js` | worldLow, usaLow, etc. |
65
+ | Themes | `@amcharts/amcharts5/themes/Animated` | `themes/Animated.js` | am5themes_Animated |
66
+ | Exporting | `@amcharts/amcharts5/plugins/exporting` | `plugins/exporting.js` | Exporting, ExportingMenu |
67
+
68
+ ## Which reference to read
69
+
70
+ Based on the chart type the user is building, read the relevant reference file for detailed API, patterns, and examples:
71
+
72
+ | User wants | Read |
73
+ |-----------|------|
74
+ | Line, area, bar, column, candlestick, OHLC, scatter, stacked charts | `references/xy.md` |
75
+ | Pie, donut, semi-circle, funnel, pyramid, pictorial stacked charts | `references/pie.md` |
76
+ | World map, country map, choropleth, bubble map, point map | `references/map.md` |
77
+ | Treemap, sunburst, force-directed, pack, partition, tree, org chart | `references/hierarchy.md` |
78
+ | Sankey, chord, arc diagram, alluvial, flow visualization | `references/flow.md` |
79
+ | Radar, spider, polar chart, gauge, speedometer, meter | `references/radar.md` |
80
+ | Financial stock chart, candlestick with indicators, trading chart | `references/stock.md` |
81
+ | Serpentine, spiral, curve chart, custom-shape timeline | `references/timeline.md` |
82
+ | Gantt chart, project timeline, task management chart | `references/gantt.md` |
83
+ | Word cloud, tag cloud, sentence cloud | `references/wordcloud.md` |
84
+ | Venn diagram, set overlap visualization | `references/venn.md` |
85
+ | Interactive controls: buttons, sliders, steppers, color pickers | `references/ui-elements.md` |
86
+
87
+ If the chart type is unclear, start with `references/xy.md` — XY charts are by far the most common.
88
+
89
+ If the user asks about core setup (theming, colors, exporting, legends, tooltips, disposal, responsive) without a specific chart type, the information below is sufficient — no reference file needed.
90
+
91
+ ## Root element setup
92
+
93
+ ```js
94
+ const root = am5.Root.new("chartdiv"); // div id or HTMLElement reference
95
+
96
+ // Apply theme(s)
97
+ root.setThemes([am5themes_Animated.new(root)]);
98
+
99
+ // Set locale (optional)
100
+ import am5locales_de_DE from "@amcharts/amcharts5/locales/de_DE";
101
+ root.locale = am5locales_de_DE;
102
+
103
+ // Set date/number formats (optional)
104
+ root.dateFormatter.setAll({ dateFormat: "yyyy-MM-dd" });
105
+ root.numberFormatter.setAll({ numberFormat: "#,###.##" });
106
+ ```
107
+
108
+ **Available themes:** `Animated`, `Dark`, `Frozen`, `Dataviz`, `Material`, `Moonrise`, `Spirited`, `Kelly`, `Micro`, `Responsive`.
109
+
110
+ ## Colors
111
+
112
+ ```js
113
+ // From hex integer or CSS string — only these forms are valid
114
+ am5.color(0xff0000)
115
+ am5.color("#ff0000")
116
+ am5.color("rgb(255, 0, 0)")
117
+
118
+ // WRONG — {r,g,b} objects are NOT accepted
119
+ // am5.color({ r: 255, g: 0, b: 0 }) // throws!
120
+
121
+ // Lighten / darken — STATIC methods on am5.Color (NOT instance methods)
122
+ am5.Color.lighten(am5.color(0xff0000), 0.3) // lighter
123
+ am5.Color.lighten(am5.color(0xff0000), -0.3) // darker (use negative value; there is NO .darken())
124
+ am5.Color.brighten(am5.color(0xff0000), 0.3) // brighter
125
+ // WRONG: am5.color(0xff0000).lighten(0.3) — this does NOT work, lighten is not an instance method
126
+
127
+ // Color sets (auto-cycle)
128
+ chart.get("colors").getIndex(0) // first color in palette
129
+ chart.get("colors").next() // next color
130
+
131
+ // Custom color set
132
+ chart.get("colors").set("colors", [
133
+ am5.color(0x095256),
134
+ am5.color(0x087f8c),
135
+ am5.color(0x5aaa95),
136
+ am5.color(0x86a873),
137
+ am5.color(0xbb9f06)
138
+ ]);
139
+ ```
140
+
141
+ ## Legend
142
+
143
+ ```js
144
+ const legend = chart.children.push(am5.Legend.new(root, {
145
+ centerX: am5.percent(50),
146
+ x: am5.percent(50),
147
+ layout: root.horizontalLayout // or verticalLayout, gridLayout
148
+ }));
149
+ // XY charts:
150
+ legend.data.setAll(chart.series.values);
151
+ // Pie/Percent charts:
152
+ legend.data.setAll(series.dataItems);
153
+ ```
154
+
155
+ ## Tooltip
156
+
157
+ ```js
158
+ series.set("tooltip", am5.Tooltip.new(root, {
159
+ labelText: "{name}: {valueY}" // data placeholders in {}
160
+ }));
161
+ ```
162
+
163
+ **Placeholders:** `{name}`, `{valueX}`, `{valueY}`, `{categoryX}`, `{categoryY}`, `{value}`, `{category}`, `{valuePercentTotal}`, `{sum}`.
164
+
165
+ **Inline formatting:** `"[bold]{name}[/]: [fontSize: 20px]{value}[/]"`
166
+
167
+ ## Chart title
168
+
169
+ Do NOT add titles as HTML elements — they are outside the canvas and won't appear in exports. Add an `am5.Label` to the container BEFORE the chart, and set `verticalLayout`:
170
+
171
+ ```js
172
+ // Option 1: directly on root.container
173
+ root.container.children.push(am5.Label.new(root, {
174
+ text: "Chart Title",
175
+ fontSize: "1.3em",
176
+ x: am5.p50,
177
+ centerX: am5.p50
178
+ }));
179
+ root.container.set("layout", root.verticalLayout);
180
+
181
+ var chart = root.container.children.push(am5xy.XYChart.new(root, { ... }));
182
+
183
+ // Option 2: with a wrapper container
184
+ var container = root.container.children.push(am5.Container.new(root, {
185
+ width: am5.p100,
186
+ height: am5.p100,
187
+ layout: root.verticalLayout
188
+ }));
189
+ container.children.push(am5.Label.new(root, {
190
+ text: "Chart Title",
191
+ fontSize: "1.3em",
192
+ x: am5.p50,
193
+ centerX: am5.p50
194
+ }));
195
+ var chart = container.children.push(am5xy.XYChart.new(root, { ... }));
196
+ ```
197
+
198
+ ## Exporting
199
+
200
+ ```js
201
+ import * as am5plugins_exporting from "@amcharts/amcharts5/plugins/exporting";
202
+
203
+ const exporting = am5plugins_exporting.Exporting.new(root, {
204
+ menu: am5plugins_exporting.ExportingMenu.new(root, {}),
205
+ filePrefix: "my-chart",
206
+ pngOptions: { quality: 0.8 },
207
+ pdfOptions: { addURL: true }
208
+ });
209
+ ```
210
+
211
+ ## Responsive rules
212
+
213
+ ```js
214
+ import am5themes_Responsive from "@amcharts/amcharts5/themes/Responsive";
215
+
216
+ const responsive = am5themes_Responsive.new(root);
217
+ responsive.addRule({
218
+ relevant: am5themes_Responsive.widthXS, // <= 200px
219
+ applying: function() {
220
+ legend.setAll({ visible: false });
221
+ },
222
+ removing: function() {
223
+ legend.setAll({ visible: true });
224
+ }
225
+ });
226
+ root.setThemes([am5themes_Animated.new(root), responsive]);
227
+ ```
228
+
229
+ ## Heat rules
230
+
231
+ Color or size elements by value. Requires `calculateAggregates: true` on the series (unless `minValue`/`maxValue` are set manually).
232
+
233
+ ```js
234
+ // Color columns by value
235
+ series.set("heatRules", [{
236
+ target: series.columns.template,
237
+ dataField: "valueY",
238
+ min: am5.color(0xe5dc36),
239
+ max: am5.color(0x5faa46),
240
+ key: "fill"
241
+ }]);
242
+
243
+ // Scale bullet radius by value
244
+ series.set("heatRules", [{
245
+ target: bulletTemplate, // am5.Template.new({})
246
+ dataField: "value",
247
+ min: 3,
248
+ max: 30,
249
+ key: "radius"
250
+ }]);
251
+ ```
252
+
253
+ **Heat rule settings:**
254
+
255
+ | Setting | Type | Description |
256
+ |---------|------|-------------|
257
+ | `target` | Template | Element template to apply heat to |
258
+ | `key` | string | Setting to modify: `"fill"`, `"radius"`, `"opacity"`, `"strokeWidth"`, `"fontSize"`, etc. |
259
+ | `dataField` | string | Data field for the value: `"valueY"`, `"value"`, `"valueX"`, etc. |
260
+ | `min` | color/number | Value applied at the lowest data value |
261
+ | `max` | color/number | Value applied at the highest data value |
262
+ | `minValue` | number | Override auto-calculated min (skips `calculateAggregates`) |
263
+ | `maxValue` | number | Override auto-calculated max (skips `calculateAggregates`) |
264
+ | `customFunction` | function | `(sprite, min, max, value)` — full control over the rule |
265
+
266
+ **Using heat rules on bullets** — bullets need an explicit `am5.Template`:
267
+
268
+ ```js
269
+ var circleTemplate = am5.Template.new({});
270
+
271
+ series.bullets.push(function() {
272
+ return am5.Bullet.new(root, {
273
+ sprite: am5.Circle.new(root, {
274
+ fill: series.get("fill"),
275
+ tooltipText: "{valueX}: {valueY}"
276
+ }, circleTemplate) // pass template as 3rd arg
277
+ });
278
+ });
279
+
280
+ series.set("heatRules", [{
281
+ target: circleTemplate,
282
+ dataField: "valueY",
283
+ min: 3,
284
+ max: 25,
285
+ key: "radius"
286
+ }]);
287
+ ```
288
+
289
+ **HeatLegend:**
290
+
291
+ ```js
292
+ var heatLegend = chart.children.push(am5.HeatLegend.new(root, {
293
+ orientation: "horizontal", // or "vertical"
294
+ startColor: am5.color(0xe5dc36),
295
+ endColor: am5.color(0x5faa46),
296
+ startText: "Low",
297
+ endText: "High",
298
+ stepCount: 5 // number of color stops
299
+ }));
300
+
301
+ // Sync legend range with series data
302
+ series.events.on("datavalidated", function() {
303
+ heatLegend.set("startValue", series.getPrivate("valueLow"));
304
+ heatLegend.set("endValue", series.getPrivate("valueHigh"));
305
+ });
306
+ ```
307
+
308
+ ## Animations
309
+
310
+ ```js
311
+ series.appear(1000); // duration in ms
312
+ chart.appear(1000, 100); // duration, delay
313
+ ```
314
+
315
+ ## Events
316
+
317
+ ```js
318
+ // Interaction events on elements
319
+ series.columns.template.events.on("click", (ev) => {
320
+ console.log("Clicked:", ev.target.dataItem.dataContext);
321
+ });
322
+
323
+ // Common events: click, pointerover, pointerout, pointerdown, globalpointermove
324
+
325
+ // Series/chart lifecycle events
326
+ series.events.on("datavalidated", () => {
327
+ // Fires after data is processed — safe to read dataItems
328
+ });
329
+
330
+ // Axis zoom/scroll — watch start/end settings, not events
331
+ xAxis.on("start", () => {
332
+ console.log("Zoomed/scrolled");
333
+ });
334
+ xAxis.on("end", () => {
335
+ console.log("Zoomed/scrolled");
336
+ });
337
+
338
+ // Setting change watch
339
+ sprite.on("width", (width) => {
340
+ console.log("Width changed to", width);
341
+ });
342
+
343
+ // One-time listener
344
+ series.events.once("datavalidated", () => { /* runs once */ });
345
+
346
+ // Remove listener
347
+ const disposer = sprite.events.on("click", handler);
348
+ disposer.dispose(); // removes the listener
349
+ ```
350
+
351
+ ## Settings API
352
+
353
+ ```js
354
+ // Set after creation
355
+ sprite.set("fill", am5.color(0xff0000));
356
+ sprite.setAll({ fill: am5.color(0xff0000), strokeWidth: 2 });
357
+
358
+ // Read current value
359
+ const fill = sprite.get("fill");
360
+ const width = sprite.getPrivate("width"); // read-only internal values
361
+ ```
362
+
363
+ ## Dynamic data
364
+
365
+ ```js
366
+ // Replace all data (full redraw, NO animation)
367
+ series.data.setAll(newData);
368
+
369
+ // Add items
370
+ series.data.push({ category: "New", value: 42 });
371
+
372
+ // Update item at index — this ANIMATES the change
373
+ series.data.setIndex(0, { category: "Updated", value: 99 });
374
+
375
+ // IMPORTANT: To update data WITH animation, use setIndex() per item.
376
+ // setAll() replaces everything at once — no transition animation.
377
+ // Loop through items for animated updates:
378
+ // newData.forEach(function(item, i) { series.data.setIndex(i, item); });
379
+
380
+ // Remove item at index
381
+ series.data.removeIndex(2);
382
+
383
+ // Insert at specific position
384
+ series.data.insertIndex(1, { category: "Inserted", value: 50 });
385
+
386
+ // Iterating dataItems — dataItems is a PLAIN ARRAY, not a List
387
+ // ❌ series.dataItems.each(fn) — will throw, .each() does not exist
388
+ // ✅ am5.array.each(series.dataItems, function(dataItem) {}) — amCharts array utility
389
+ // ✅ series.dataItems.forEach(function(dataItem) {}) — standard JS
390
+ ```
391
+
392
+ ## Adapters
393
+
394
+ ```js
395
+ // Dynamically modify a setting value before it's applied
396
+ series.columns.template.adapters.add("fill", (fill, target) => {
397
+ return target.dataItem.get("valueY") > 100
398
+ ? am5.color(0x00cc00)
399
+ : am5.color(0xcc0000);
400
+ });
401
+
402
+ // Adapter on axis labels
403
+ xAxis.get("renderer").labels.template.adapters.add("text", (text, target) => {
404
+ return text + "!";
405
+ });
406
+ ```
407
+
408
+ ## States
409
+
410
+ ```js
411
+ // Hover state — applied automatically on pointer over
412
+ series.columns.template.states.create("hover", {
413
+ fillOpacity: 0.8,
414
+ scale: 1.05
415
+ });
416
+
417
+ // Active state — toggled via click
418
+ series.columns.template.states.create("active", {
419
+ fill: am5.color(0xff0000)
420
+ });
421
+
422
+ // Built-in state names: "default", "hover", "active", "disabled", "hidden"
423
+ // State animation: stateAnimationDuration, stateAnimationEasing
424
+ ```
425
+
426
+ ## Custom themes
427
+
428
+ ```js
429
+ const myTheme = am5.Theme.new(root);
430
+ myTheme.rule("Label").setAll({ fontSize: 12, fill: am5.color(0x555555) });
431
+ myTheme.rule("Grid").setAll({ stroke: am5.color(0xe0e0e0) });
432
+ root.setThemes([am5themes_Animated.new(root), myTheme]);
433
+ // Theme order matters: later themes override earlier ones
434
+ ```
435
+
436
+ ## Dark theme
437
+
438
+ When the page has a dark background, add the Dark theme so labels, grid, and tooltips are readable:
439
+
440
+ ```js
441
+ root.setThemes([
442
+ am5themes_Animated.new(root),
443
+ am5themes_Dark.new(root) // must come after Animated
444
+ ]);
445
+ ```
446
+
447
+ Import: `import am5themes_Dark from "@amcharts/amcharts5/themes/Dark"` or CDN `themes/Dark.js`.
448
+
449
+ **Rule:** Only add Dark theme when the background is clearly dark. Default to white/light background with no Dark theme.
450
+
451
+ ## ColorSet — using default colors
452
+
453
+ amCharts assigns colors automatically via a built-in ColorSet. Do not invent custom palettes unless the user asks.
454
+
455
+ ```js
456
+ // Get the chart's default color set
457
+ var colors = chart.get("colors"); // XY, Radar, Percent charts only
458
+ var colors = series.get("colors"); // pie/percent charts use series-level colors
459
+
460
+ // MapChart has NO built-in ColorSet — create your own:
461
+ var colors = am5.ColorSet.new(root, {});
462
+
463
+ // Get a specific color by index (does not advance internal counter)
464
+ var color = colors.getIndex(0); // first default color
465
+ var color = colors.getIndex(3); // fourth default color
466
+
467
+ // Get next color in sequence (advances internal counter)
468
+ var color = colors.next();
469
+
470
+ // Reset counter back to start
471
+ colors.reset();
472
+
473
+ // Override the default palette (only if user requests specific colors)
474
+ colors.set("colors", [
475
+ am5.color(0x095256),
476
+ am5.color(0x087f8c),
477
+ am5.color(0x5aaa95)
478
+ ]);
479
+ ```
480
+
481
+ ## Data processor
482
+
483
+ ```js
484
+ // Auto-convert fields when loading external / API data
485
+ series.data.processor = am5.DataProcessor.new(root, {
486
+ dateFields: ["date"],
487
+ dateFormat: "yyyy-MM-dd",
488
+ numericFields: ["value", "count"],
489
+ colorFields: ["color"],
490
+ emptyAs: 0 // replace null/empty with 0
491
+ });
492
+ // Configure processor BEFORE setting data
493
+ ```
494
+
495
+ ## Accessibility
496
+
497
+ ```js
498
+ series.columns.template.setAll({
499
+ focusable: true,
500
+ ariaLabel: "{categoryX}: {valueY}",
501
+ role: "figure"
502
+ });
503
+ // Keyboard: TAB to navigate focusable elements, ENTER to click
504
+ // focusableGroup: "series1" — TAB to first, arrows within group
505
+ ```
506
+
507
+ ## Container & Layout
508
+
509
+ ```js
510
+ // Containers organize child elements
511
+ const container = root.container.children.push(am5.Container.new(root, {
512
+ width: am5.percent(100),
513
+ height: am5.percent(100),
514
+ layout: root.verticalLayout // also: horizontalLayout, gridLayout
515
+ }));
516
+
517
+ // Padding and margin
518
+ container.setAll({
519
+ paddingTop: 10,
520
+ paddingBottom: 10,
521
+ marginLeft: 20
522
+ });
523
+ ```
524
+
525
+ **Layout options:**
526
+
527
+ | Layout | Access | Behavior |
528
+ |--------|--------|----------|
529
+ | Vertical | `root.verticalLayout` | Children stacked top-to-bottom |
530
+ | Horizontal | `root.horizontalLayout` | Children in a row left-to-right |
531
+ | Grid | `root.gridLayout` | Multi-column grid |
532
+ | Custom grid | `am5.GridLayout.new(root, { maxColumns: 3 })` | Grid with custom column count |
533
+ | None | omit `layout` | Children placed at x/y coordinates |
534
+
535
+ Use layouts to arrange charts, legends, controls, and labels within containers.
536
+
537
+ ## UI Elements
538
+
539
+ amCharts 5 provides built-in interactive UI widgets. **Prefer these over HTML elements** when building controls, unless instructed otherwise. Read `references/ui-elements.md` for full API and examples.
540
+
541
+ | Element | Class | Description |
542
+ |---------|-------|-------------|
543
+ | Button | `am5.Button` | Clickable button with label, icon, background, hover/down/active states |
544
+ | Slider | `am5.Slider` | Single-value slider (0-1 range), fires `rangechanged` event |
545
+ | Scrollbar | `am5.Scrollbar` | Two-grip range selector, `orientation: "horizontal"\|"vertical"` |
546
+ | NumericStepper | `am5.NumericStepper` | Number input with up/down arrows |
547
+ | ProgressPie | `am5.ProgressPie` | Circular progress indicator with `value`, `radius`, `innerRadius` |
548
+ | SpriteResizer | `am5.SpriteResizer` | Drag-to-resize handles on any sprite |
549
+ | EditableLabel | `am5.EditableLabel` | Label that becomes editable text field on click |
550
+ | Modal | `am5.Modal` | HTML overlay dialog with `open()`/`close()` |
551
+ | ColorPicker | `am5plugins_colorPicker.ColorPicker` | Color picker (requires `plugins/colorPicker.js`) |
552
+
553
+ **Quick example — slider + button controlling a chart:**
554
+
555
+ ```js
556
+ // Slider to control a value
557
+ var slider = container.children.push(am5.Slider.new(root, {
558
+ orientation: "horizontal",
559
+ start: 0.5,
560
+ width: am5.percent(80),
561
+ centerX: am5.percent(50),
562
+ x: am5.percent(50)
563
+ }));
564
+ slider.events.on("rangechanged", function(ev) {
565
+ var value = ev.start; // 0-1 range
566
+ // update chart based on slider position
567
+ });
568
+
569
+ // Button
570
+ var button = container.children.push(am5.Button.new(root, {
571
+ label: am5.Label.new(root, { text: "Reset" }),
572
+ centerX: am5.percent(50),
573
+ x: am5.percent(50)
574
+ }));
575
+ button.events.on("click", function() {
576
+ slider.set("start", 0.5);
577
+ });
578
+ ```
579
+
580
+ ## Disposal (SPA frameworks)
581
+
582
+ ```js
583
+ // React
584
+ useLayoutEffect(() => {
585
+ const root = am5.Root.new("chartdiv");
586
+ // ... build chart
587
+ return () => { root.dispose(); };
588
+ }, []);
589
+
590
+ // Angular
591
+ ngOnDestroy() { this.root?.dispose(); }
592
+
593
+ // Vue
594
+ onUnmounted(() => { root.dispose(); });
595
+ ```
596
+
597
+ **Always call `root.dispose()`** — this cleans up all children, series, and event listeners.
598
+
599
+ ## v4 → v5 migration pitfalls
600
+
601
+ | v4 pattern (WRONG) | v5 equivalent (CORRECT) |
602
+ |-----------|--------------|
603
+ | `am4core.create("div", am4charts.XYChart)` | `am5.Root.new("div")` + `am5xy.XYChart.new(root, {})` |
604
+ | `new am4charts.LineSeries()` | `am5xy.LineSeries.new(root, {})` |
605
+ | `series.dataFields.valueY = "val"` | `valueYField: "val"` in `.new()` settings |
606
+ | `chart.data = [...]` | `series.data.setAll([...])` |
607
+ | `am4core.color("#f00")` | `am5.color(0xff0000)` |
608
+ | `am4core.percent(50)` | `am5.percent(50)` |
609
+ | `chart.dispose()` | `root.dispose()` |
610
+ | `chart.legend = new am4charts.Legend()` | `chart.children.push(am5.Legend.new(root, {}))` |
611
+
612
+ ## Common pitfalls
613
+
614
+ 1. **Using `new` keyword** — always use `.new()` factory.
615
+ 2. **Forgetting `CategoryAxis.data.setAll()`** — axis will be empty.
616
+ 3. **Passing Date objects to DateAxis** — must be timestamps (ms).
617
+ 4. **Missing axis renderer** — every axis needs `renderer: am5xy.AxisRendererX.new(root, {})`.
618
+ 5. **Setting data before configuration** — configure everything, then set data last.
619
+ 6. **Raw hex strings for colors** — use `am5.color()`.
620
+ 7. **Mixing v4 and v5 API** — they are completely incompatible.
621
+ 8. **Calling `chart.dispose()` instead of `root.dispose()`** — always dispose root.
622
+ 9. **Using CSS to style chart elements** — amCharts renders on Canvas, not DOM.
623
+ 10. **Wrong package import** — check the package map table above.
624
+ 11. **Calling `.each()` on `dataItems`** — `series.dataItems` is a plain array, not an amCharts `List`. Use `am5.array.each(series.dataItems, fn)` or standard `forEach`/`for` loops. Only `series.data` (the `ListData` object) has `.each()`.
625
+ 12. **CDN script load order** — `index.js` must load first, then `xy.js`, then any package that depends on it (`radar.js`, `timeline.js`, `gantt.js`). Wrong order causes runtime errors. Correct order: `index.js` → `xy.js` → `radar.js` / `timeline.js` / `gantt.js` → `themes/*.js`.
626
+ 13. **No `minorGrid` / `minorTicks` / `minorLabels` objects** — These do not exist on axes. Minor grid is enabled via boolean flags on the **renderer**: `minorGridEnabled: true` and optionally `minorLabelsEnabled: true`. Styling is done through theme rules targeting the `"minor"` tag, not through separate object properties.
627
+ 14. **Flow chart animated bullets go on `series.bullets`, NOT `series.links.template.bullets`** — To animate labels/circles flowing along Sankey or Chord links, use `series.bullets.push(function(...) { ... })`. Animate `bullet.locationX` (Sankey) or `bullet.locationY` (Chord) from 0→1 with `loops: Infinity`. Use an adapter on opacity for fade effect. See `references/flow.md` → "Animated bullets along links".
628
+ 15. **`MapPointSeries` needs `latitudeField`/`longitudeField` when using `data.setAll()`** — If point data has `latitude`/`longitude` fields, the series must declare them: `am5map.MapPointSeries.new(root, { latitudeField: "latitude", longitudeField: "longitude" })`. Without these, points silently won't appear. This is NOT needed when using `pushDataItem({ latitude: ..., longitude: ... })` which passes coordinates directly.
629
+ 16. **`data.setAll()` does NOT animate — use `data.setIndex()` for animated updates** — When the user asks to update/refresh data with animation, do NOT use `series.data.setAll(newData)` — it replaces everything instantly with no transition. Instead, update each item with `series.data.setIndex(i, newItem)` which triggers smooth value animation. For full replacement with animation, loop: `newData.forEach(function(item, i) { series.data.setIndex(i, item); })`.
630
+ 17. **`color.lighten()` / `color.darken()` are NOT instance methods** — `am5.color(0xff0000).lighten(0.3)` does NOT work. Use static methods: `am5.Color.lighten(color, 0.3)` to lighten, `am5.Color.lighten(color, -0.3)` to darken. There is NO `darken()` method — use negative lighten. Also available: `am5.Color.brighten()`, `am5.Color.saturate()`.
631
+ 18. **Venn diagram has no `VennDiagram` class** — `am5venn.Venn` is pushed directly into a `Container`, NOT into a chart's `series`. See `references/venn.md`.
632
+ 19. **Timeline `AxisRendererCurveX` requires `yRenderer`** — Always create the Y renderer first, then pass it: `am5timeline.AxisRendererCurveX.new(root, { yRenderer: yRenderer })`. Without this, crashes with `Cannot read properties of undefined (reading 'axis')`.
633
+ 20. **Gantt data uses TWO separate calls** — Do NOT use `chart.data.setAll()`. Set categories on `chart.yAxis.data.setAll([{id, name, parentId, color}])` and tasks on `chart.series.data.setAll([{id, start, duration, progress, linkTo}])`. Use flat `parentId` for hierarchy, NOT nested `children` arrays. CDN order: `index.js` → `xy.js` → `plugins/colorPicker.js` → `gantt.js` → `themes/Animated.js` (gantt.js webpack-depends on colorPicker chunk). See `references/gantt.md`.
634
+ 21. **No continent-level geodata at top-level CDN** — `geodata/europeLow.js` does NOT exist. Use `geodata/region/world/europeLow.js` (global: `am5geodata_region_world_europeLow`) or filter `worldLow` with `include: [...]`.
635
+ 22. **Do not add chart titles as HTML** — HTML titles are outside the canvas and won't appear in exports. Use `am5.Label` pushed into the container BEFORE the chart, with `verticalLayout` on the container. See "Chart title" section above.
636
+ 23. **`XYChartScrollbar` axes — never use `scrollbar.get("xAxis")`** — The axes passed to the scrollbar constructor are NOT stored as gettable settings. Create axes as separate variables, pass them to the scrollbar, and reuse those same variables for the scrollbar's inner series. `scrollbar.get("xAxis")` returns `undefined`.
637
+ 24. **`am5.color()` only accepts hex integers or CSS strings** — `am5.color(0xff0000)`, `am5.color("#ff0000")`, `am5.color("rgb(255,0,0)")` are valid. `am5.color({ r: 255, g: 0, b: 0 })` is NOT — it throws.
638
+ 25. **`MapChart` has NO `"colors"` setting** — `chart.get("colors")` returns `undefined` on `MapChart`. Only XY, Radar, and Percent charts auto-create a ColorSet. For maps, create your own: `am5.ColorSet.new(root, {})`.
639
+ 26. **`VoronoiTreemap` has NO `.rectangles` property** — Unlike `Treemap` (which has `series.rectangles.template`), `VoronoiTreemap` renders organic polygon cells. Style via `series.nodes.template` and its children, not `.rectangles`.
640
+ 27. **Labels with data placeholders need `populateText: true`** — When a Label uses data field placeholders like `text: "{name}"`, you MUST also set `populateText: true`. Without it, the placeholder is not resolved and the label appears blank. This applies everywhere Labels display dynamic data — bullet labels, map point labels, etc. Example: `am5.Label.new(root, { text: "{name}", populateText: true, ... })`.
641
+
642
+ ## Validate generated code (if you can execute commands)
643
+
644
+ If you have the ability to run shell commands, validate your generated chart code before delivering it to the user:
645
+
646
+ 1. Save the complete HTML+JS to a temp `.html` file
647
+ 2. Open it in a headless browser (Puppeteer, Playwright, or similar) and collect console errors for a few seconds
648
+ 3. If JavaScript errors are found, fix them and re-validate
649
+
650
+ Skip this step entirely if you cannot execute code (e.g., chat-only context with no tool access).
651
+
652
+ ## Verify unfamiliar API before using it
653
+
654
+ If you are unsure whether a method, property, or setting exists on an amCharts 5 class, **verify it before using it**. Check the class reference (class name in lowercase, e.g. `LineSeries` → `lineseries`):
655
+
656
+ 1. **Primary:** `https://www.amcharts.com/docs/v5/reference/{classname}/` — e.g. `https://www.amcharts.com/docs/v5/reference/lineseries/`
657
+ 2. **Fallback (if primary is unavailable):** Check the TypeScript source on GitHub — `https://raw.githubusercontent.com/amcharts/amcharts5/master/src/.internal/charts/` and navigate to the relevant file. Settings interfaces are named `I{ClassName}Settings`.
658
+
659
+ Common source file paths:
660
+ - XY series: `charts/xy/series/{ClassName}.ts`
661
+ - XY axes: `charts/xy/axes/{ClassName}.ts`
662
+ - Pie: `charts/percent/pie/{ClassName}.ts`
663
+ - Radar: `charts/radar/{ClassName}.ts`
664
+ - Map: `charts/map/{ClassName}.ts`
665
+ - Hierarchy: `charts/hierarchy/{ClassName}.ts`
666
+ - Flow: `charts/flow/{ClassName}.ts`
667
+ - Core sprites: `core/render/{ClassName}.ts`