UNPKG

apexcharts

Version:

A JavaScript Chart Library

1,313 lines (1,307 loc) 67 kB
// @ts-check /** * ApexCharts Options for setting the initial configuration of ApexCharts **/ import en from './../../locales/en.json' export default class Options { constructor() { this.yAxis = { show: true, showAlways: false, showForNullSeries: true, seriesName: undefined, opposite: false, reversed: false, logarithmic: false, logBase: 10, tickAmount: undefined, stepSize: undefined, forceNiceScale: false, alignZero: false, max: undefined, min: undefined, floating: false, decimalsInFloat: undefined, labels: { show: true, showDuplicates: false, minWidth: 0, maxWidth: 160, offsetX: 0, offsetY: 0, align: undefined, rotate: 0, padding: 20, style: { colors: [], fontSize: '11px', fontWeight: 400, fontFamily: undefined, cssClass: '', }, formatter: undefined, }, axisBorder: { show: false, color: '#e0e0e0', width: 1, offsetX: 0, offsetY: 0, }, axisTicks: { show: false, color: '#e0e0e0', width: 6, offsetX: 0, offsetY: 0, }, title: { text: undefined, rotate: -90, offsetY: 0, offsetX: 0, style: { color: undefined, fontSize: '11px', fontWeight: 900, fontFamily: undefined, cssClass: '', }, }, tooltip: { enabled: false, offsetX: 0, }, crosshairs: { show: true, position: 'front', stroke: { color: '#b6b6b6', width: 1, dashArray: 0, }, }, } this.pointAnnotation = { id: undefined, x: 0, y: null, yAxisIndex: 0, seriesIndex: undefined, mouseEnter: undefined, mouseLeave: undefined, click: undefined, marker: { size: 4, fillColor: '#fff', strokeWidth: 2, strokeColor: '#333', shape: 'circle', offsetX: 0, offsetY: 0, // radius: 2, // DEPRECATED cssClass: '', }, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'middle', offsetX: 0, offsetY: 0, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2, }, }, }, customSVG: { // this will be deprecated in the next major version as it is going to be replaced with a better alternative below (image) SVG: undefined, cssClass: undefined, offsetX: 0, offsetY: 0, }, image: { path: undefined, width: 20, height: 20, offsetX: 0, offsetY: 0, }, } this.yAxisAnnotation = { id: undefined, y: 0, y2: null, strokeDashArray: 1, fillColor: '#c2c2c2', borderColor: '#c2c2c2', borderWidth: 1, opacity: 0.3, offsetX: 0, offsetY: 0, width: '100%', yAxisIndex: 0, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'end', position: 'right', offsetX: 0, offsetY: -3, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2, }, }, }, } this.xAxisAnnotation = { id: undefined, x: 0, x2: null, strokeDashArray: 1, fillColor: '#c2c2c2', borderColor: '#c2c2c2', borderWidth: 1, opacity: 0.3, offsetX: 0, offsetY: 0, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'middle', orientation: 'vertical', position: 'top', offsetX: 0, offsetY: 0, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2, }, }, }, } this.text = { x: 0, y: 0, text: '', textAnchor: 'start', foreColor: undefined, fontSize: '13px', fontFamily: undefined, fontWeight: 400, appendTo: '.apexcharts-annotations', backgroundColor: 'transparent', borderColor: '#c2c2c2', borderRadius: 0, borderWidth: 0, paddingLeft: 4, paddingRight: 4, paddingTop: 2, paddingBottom: 2, } } init() { return { annotations: { yaxis: [this.yAxisAnnotation], xaxis: [this.xAxisAnnotation], points: [this.pointAnnotation], texts: [], images: [], shapes: [], }, // Weave (#1): public plugin platform. Per-chart activation list: // { name, options?, order? }. Requires the Weave host to be bundled // (`import 'apexcharts/features/weave'`, included in the full bundle) and // the plugin registered via ApexCharts.registerPlugin(). plugins: [], chart: { animations: { // Master switch — set false to render charts without any animation. // Each chart type gets a tailored initial-mount animation by default: // line/area/rangeArea/radar: pen-stroke draw + radial fill bloom // bar/stacked/range/funnel: grow from baseline (+ stagger) // scatter/bubble: scale-up pop with overshoot // heatmap: diagonal-wave cell reveal // treemap: largest-tile-first cascade // pie/donut/polar/gauge: arc sweep + needle settle // Speed is controlled by `speed`; per-element stagger by // `animateGradually.enabled` / `animateGradually.delay`. enabled: true, speed: 800, // Cadence (#6): easing for the generic tweens (data-update value // transitions, path morphs, marker animate). A registered name, a // cubic-bezier [x1,y1,x2,y2] array, or a function (t in [0,1]). // 'easeInOutSine' is the historical curve, so the default is // behavior-neutral. The tuned initial-draw pen/pop easings are fixed. easing: 'easeInOutSine', animateGradually: { // Drives per-element stagger across all chart types. When enabled, // bars/heatmap-cells/scatter-points/treemap-tiles reveal in // sequence; line/area markers fade in progressively along the // draw. `delay` is the requested step in ms (auto-capped per // chart so total stagger ≤ ~half the animation duration). delay: 150, enabled: true, }, dynamicAnimation: { // Data-change (updateSeries) animation. Independent from the // initial-mount animations above. enabled: true, speed: 350, // Easing for data-change morphs only (same accepted forms as // `animations.easing`). Unset -> inherit the chart-wide easing, // except detected streaming scrolls (rolling window / append // under xaxis.range) which default to 'linear' so the window // slides at constant velocity instead of pulsing each tick. easing: undefined, }, chartTypeMorph: { // Cross-type morph (updateOptions changing chart.type). Bridges // the destroy+recreate flicker by sampling source + target paths // into N evenly-spaced perimeter points and tweening point-by-point // with rotation-search alignment, so the transition is always smooth // and non-self-intersecting even between very different shapes (bar // rect ↔ pie wedge / radial arc). Supported pairs include bar ↔ // pie / donut / radialBar / polarArea / funnel / pyramid (plus the // trivial pie ↔ donut ↔ polarArea cases). Falls back to instant // snap when types or data shape are incompatible. enabled: true, speed: 600, }, // Honor the OS-level prefers-reduced-motion setting. When true (default) // and the user has the accessibility preference enabled, all initial-mount // animations are skipped and the chart renders instantly. respectReducedMotion: true, // Above this many data points, per-element morph + stagger (which // spins up one JS-driven animation timeline per path — three chained // tweens each in morphSVG) is replaced by a single GPU-composited // opacity fade of the whole series. Thousands of candlesticks/bars // otherwise jank the main thread on initial render and on every zoom. // The fade reuses the existing delayedElements reveal so the result // still animates in, just at O(1) cost instead of O(n). Set to 0 to // always animate per-element regardless of dataset size. largeDatasetThreshold: 1000, }, background: '', locales: [en], defaultLocale: 'en', // Perspectives (#10): serializable/shareable view state. Passive: // requires `import 'apexcharts/features/perspectives'`. serializeOptions // is the whitelist of function-free option paths stored in a token. perspectives: { serializeOptions: ['theme', 'xaxis', 'yaxis', 'title', 'subtitle'], }, // Rewind (#3): undo/redo history. Opt-in (bundle + behavior): requires // `import 'apexcharts/features/history'` AND chart.history.enabled. history: { enabled: false, maxDepth: 100, coalesceMs: 250, keyboard: true, }, // Strata (#2): hybrid SVG+canvas series renderer. 'svg' (default) | // 'canvas' | 'auto'. 'auto'/'canvas' need the canvas renderer feature // (`import 'apexcharts/features/renderer-canvas'`); without it, or with // a canvas-unsupported feature (pattern/image fill, color-matrix state // filters), selection falls back to 'svg'. Only the series layer is // canvas-capable in v1; chrome stays SVG. renderer: 'svg', rendererThreshold: 8000, layers: { series: 'auto', grid: 'svg', annotations: 'svg', dataLabels: 'svg', }, dropShadow: { enabled: false, enabledOnSeries: undefined, top: 2, left: 2, blur: 4, color: '#000', opacity: 0.7, }, events: { animationEnd: undefined, beforeMount: undefined, mounted: undefined, updated: undefined, click: undefined, mouseMove: undefined, mouseLeave: undefined, xAxisLabelClick: undefined, legendClick: undefined, markerClick: undefined, selection: undefined, dataPointSelection: undefined, dataPointMouseEnter: undefined, dataPointMouseLeave: undefined, beforeZoom: undefined, beforeResetZoom: undefined, zoomed: undefined, scrolled: undefined, brushScrolled: undefined, crossFilter: undefined, filterChange: undefined, annotationDragged: undefined, annotationEdited: undefined, annotationCreated: undefined, annotationStyled: undefined, annotationDeleted: undefined, measured: undefined, keyDown: undefined, keyUp: undefined, }, foreColor: '#373d3f', fontFamily: 'Helvetica, Arial, sans-serif', height: 'auto', parentHeightOffset: 15, redrawOnParentResize: true, redrawOnWindowResize: true, id: undefined, group: undefined, nonce: undefined, // Per-chart license key override for the gated premium features // (storyboard, link/crossfilter, ink, measure, contextMenu, // perspectives, history). Most specific wins: chart.license -> // ApexCharts.setLicense() -> window.Apex.license -> unlicensed (trial // watermark). Shared across the ApexCharts family. See setLicense(). license: undefined, offsetX: 0, offsetY: 0, injectStyleSheet: true, selection: { enabled: false, type: 'x', // selectedPoints: undefined, // default datapoints that should be selected automatically fill: { color: '#24292e', opacity: 0.1, }, stroke: { width: 1, color: '#24292e', opacity: 0.4, dashArray: 3, }, xaxis: { min: undefined, max: undefined, }, yaxis: { min: undefined, max: undefined, }, }, sparkline: { enabled: false, }, brush: { enabled: false, autoScaleYaxis: true, target: undefined, targets: undefined, }, // Linked Views (#4): crossfilter / linked highlighting. Requires the // `link` feature. Two modes: // HIGHLIGHT (P1): `enabled` with no `dimension`. Charts sharing a // `chart.group` form a set; brushing a range (needs // `chart.selection.enabled`) dims out-of-range marks in place. // FILTER (P2): set `dimension` (its presence selects this path). Each // chart declares a dimension + reduction over a shared record set // registered with ApexCharts.crossfilter({ id, records }); clicking a // bucket re-aggregates the other charts. See docs/spec. link: { enabled: false, mode: 'highlight', dimOpacity: 0.2, // FILTER-mode config (all optional except dimension): id: undefined, // crossfilter coordinator id (defaults to chart.group) dimension: undefined, // (row) => key; presence selects filter mode reduce: undefined, // 'count' | { sum|avg|min|max: field } | (rows)=>n type: undefined, // 'category' | 'range' (else inferred from bins) bins: undefined, // range dims: { width } | { count } | { thresholds } order: undefined, // category order: 'first-seen' | 'asc' | 'desc' | fn seriesName: undefined, // axis-chart series name (default 'Count') }, // Ink Layer (#7): direct-manipulation annotations. When enabled, every // point annotation is draggable (unless it sets draggable:false); or opt // in per annotation with annotations.points[].draggable. Clicking an // ink-managed annotation opens a floating editor card: rename inline, // recolor, toggle bold, step the font size, size/reshape the marker, or // delete the note. Axis-line annotations get separate Label and Line // color rows, so restyling the label chip never touches the stroke. // Requires the `ink` feature. Fires annotationDragged, // annotationEdited, annotationStyled and annotationDeleted. ink: { enabled: false, // Show a minimal "add note" tool palette; clicking it arms create // mode (the next plot click drops an editable, draggable annotation). palette: false, // Snap a dragged point / axis-line annotation to the nearest gridline // (numeric x + linear y). Undo/redo of ink edits is automatic when the // history (Rewind) feature is enabled. snap: false, // Accent swatches offered by the floating note editor; defaults to a // built-in 6-color palette when undefined. noteColors: undefined, }, // Measure ruler (#18): a measure/delta ruler. Requires the `measure` // feature. Hold `key` (default 'm') and drag A->B on the plot, or call // chart.startMeasure()/chart.stopMeasure() to arm it. The live ruler // reads dx, dy, %change and slope; on release it pins as a data-anchored // overlay that re-projects on zoom/resize. Fires `measured`. measure: { enabled: false, // 'span' (default): finance-style vertical band between two x-points // with a "change (%) + range" readout, endpoints snapped to the first // series. 'free': a diagonal ruler between two arbitrary points. mode: 'span', key: 'm', pinOnRelease: true, // Styling tokens. Every element also carries a stable CSS class // (apexcharts-measure-band / -vline / -line / -label-bg / -label, // group gets apexcharts-measure-up|down|flat). Colors are left // undefined so they resolve config -> `--apx-measure-*` CSS custom // property -> built-in default; set them here to force a color from JS. colors: { up: undefined, down: undefined, neutral: undefined, guide: undefined, }, band: true, // span mode: shaded band between the two x-positions guides: true, // span mode: vertical dashed reference lines markers: true, // endpoint dots on the series line // Content: value formatters and a full readout override. `label` // receives { from, to, dx, dy, percentChange, slope, mode } and // returns a string or string[] (lines). format: { x: undefined, y: undefined, percent: undefined }, label: undefined, }, // Radial Actions (#chrome): right-click / long-press context menu. // Requires the `contextMenu` feature. Each action receives the clicked // data coordinates, so verbs act at the point (not chart-wide like a // toolbar button). `items` is an ordered list of built-in ids // ('annotate' | 'xline' | 'yline' | 'measure') and/or custom // { id, label, icon, onClick(ctx, { x, y, seriesIndex, dataPointIndex, // clientX, clientY }) }. 'measure' is shown only when the measure tool // is enabled. `labels` overrides built-in text; `noteText` is the label // dropped by 'annotate'. contextMenu: { enabled: false, items: ['annotate', 'xline', 'yline', 'measure'], labels: { annotate: undefined, xline: undefined, yline: undefined, measure: undefined, }, noteText: 'Note', // 'xline' ("Annotate here") drops a dashed vertical LINE at the // clicked x; 'yline' ("Mark this level") a dashed horizontal line at // the clicked y. Lines only, never a range rectangle. Like the note, // a line is ink-managed when the ink feature is bundled: it opens // the floating editor (rename; separate Label and Line color rows, // so restyling the chip cannot blank the stroke; delete), drags // along its axis, and undoes via Rewind. `line` styles both items. line: { text: '', // label drawn on the line; empty for no label strokeDashArray: 4, color: undefined, // undefined keeps the annotation default color }, }, stacked: false, stackOnlyBar: true, // mixed chart with stacked bars and line series - incorrect line draw #907 stackType: 'normal', // Real-time streaming mode. When enabled, appendData() bounds memory // automatically: each series is trimmed to `maxPoints` (when set) or // to the visible `xaxis.range` window plus a two-point off-screen // runway (so exiting segments slide off the left edge instead of // popping). The scroll animation itself needs no opt-in; updates // that continue the previous window (appendData, or updateSeries with // a shifted fixed-length window) always translate at constant // velocity; see modules/animations/StreamScroll. streaming: { enabled: false, maxPoints: undefined, }, toolbar: { show: true, offsetX: 0, offsetY: 0, tools: { download: true, selection: true, zoom: true, zoomin: true, zoomout: true, pan: true, reset: true, // Shown only when the measure ruler is active (chart.measure.enabled // and the `measure` feature bundled). Toggles the measure tool; set // false to keep the ruler key-driven only. See chart.measure. measure: true, customIcons: [], }, export: { csv: { filename: undefined, columnDelimiter: ',', headerCategory: 'category', headerValue: 'value', categoryFormatter: undefined, valueFormatter: undefined, }, png: { filename: undefined, }, svg: { filename: undefined, }, scale: undefined, width: undefined, }, autoSelected: 'zoom', // accepts -> zoom, pan, selection, measure }, type: 'line', width: '100%', zoom: { enabled: true, type: 'x', autoScaleYaxis: false, allowMouseWheelZoom: true, // Momentum: two-finger pinch-zoom on touch devices. Zooms the x-axis // around the pinch centroid (matching the x-only wheel/toolbar zoom), // frame-by-frame rather than the 400ms wheel throttle. pinch: true, zoomedArea: { fill: { color: '#90CAF9', opacity: 0.4, }, stroke: { color: '#0D47A1', opacity: 0.4, width: 1, }, }, }, // Momentum: kinetic panning on touch. When a one-finger pan is released // with velocity, the chart keeps gliding and decelerates by `friction` // each frame, clamping (no elastic overshoot) at the data edges. pan: { inertia: true, friction: 0.92, }, accessibility: { enabled: true, description: undefined, announcements: { enabled: true, }, keyboard: { enabled: true, navigation: { enabled: true, wrapAround: false, }, }, }, dataReducer: { enabled: false, algorithm: 'lttb', targetPoints: 250, threshold: 500, }, }, parsing: { x: undefined, y: undefined, }, plotOptions: { line: { isSlopeChart: false, colors: { threshold: 0, colorAboveThreshold: undefined, colorBelowThreshold: undefined, }, }, area: { fillTo: 'origin', }, bar: { horizontal: false, columnWidth: '70%', // should be in percent 0 - 100 barHeight: '70%', // should be in percent 0 - 100 distributed: false, borderRadius: 0, borderRadiusApplication: 'around', // [around, end] borderRadiusWhenStacked: 'last', // [all, last] rangeBarOverlap: true, rangeBarGroupRows: false, hideZeroBarsWhenGrouped: false, isDumbbell: false, dumbbellColors: undefined, isFunnel: false, isFunnel3d: true, colors: { ranges: [], backgroundBarColors: [], backgroundBarOpacity: 1, backgroundBarRadius: 0, }, dataLabels: { position: 'top', // top, center, bottom maxItems: 100, hideOverflowingLabels: true, orientation: 'horizontal', total: { enabled: false, formatter: undefined, offsetX: 0, offsetY: 0, style: { color: '#373d3f', fontSize: '12px', fontFamily: undefined, fontWeight: 600, }, }, }, }, bubble: { zScaling: true, minBubbleRadius: undefined, maxBubbleRadius: undefined, }, scatter: { // Spread overlapping points apart ("jitter"). Two uses, one engine: // - Strip plot: supply data as { x: 'Category', y: [v1, v2, ...] }. // Each category becomes a band and the values are scattered // horizontally within it. Marker styling comes from the standard // `markers` / `colors` config. // - Overplotting: ordinary { x, y } points get a small random offset // so dense clusters fan out. The underlying data (and tooltip // values) stay exact — only the drawn position moves. // Offsets are in axis units (x: 1 = one category step) and are // deterministic (stable across re-renders, SSR-safe). jitter: { enabled: false, x: 0, // max ± horizontal offset, in x-axis units y: 0, // max ± vertical offset, in y-axis units distributed: false, // single series: colour each band differently maxPoints: 5000, // per band; excess values are stride-thinned }, }, candlestick: { colors: { upward: '#00B746', downward: '#EF403C', }, wick: { useFillColor: true, }, }, boxPlot: { colors: { upper: '#00E396', lower: '#008FFB', }, // Optional individual observations ("jitter") overlaid on each box. // Inert unless a data point supplies a `points: number[]` array; off // by default so existing boxPlot charts are unchanged. points: { show: false, shape: 'circle', // 'circle' | 'square' size: 2.5, // radius (px) jitter: 0.5, // 0..1 fraction of the box half-width to scatter within maxPoints: 3000, // cap per box; excess is stride-thinned opacity: 0.9, // 'series-dark' (default) → a darker shade of the series colour, // 'series' → the series colour, or any literal colour string. fillColor: 'series-dark', strokeColor: '#fff', strokeWidth: 1, // Optional `colorScale` (undeclared so a user object merges cleanly) // colours each dot by its value: { colors, min, max, steps } }, }, violin: { // Multiply the density-derived half-width. 1 = density's own maxWeight // maps to half the category slot. bandwidthScale: 1, // 'individual' → every violin uses the full slot width (scaled to its // own peak). 'group' → all violins share one scale (the densest in the // series), so widths stay proportional to density across categories. normalize: 'individual', // Individual observations ("jitter") overlaid on the violin shape. points: { show: true, shape: 'circle', // 'circle' | 'square' size: 2.5, // radius (px) jitter: 0.5, // 0..1 fraction of the half-width to scatter within constrainToViolin: true, // clamp jitter to the density width at each value maxPoints: 3000, // cap per violin; excess is stride-thinned opacity: 0.9, // Default: a darker shade of each violin's own colour, with a white // outline. fillColor accepts 'series-dark' (default), 'series' (the // violin's colour as-is), or any literal colour string. fillColor: 'series-dark', strokeColor: '#fff', strokeWidth: 1, // Optional `colorScale` (left undeclared so a user object merges // cleanly) colours each dot by its value along a ramp: // { colors: ['#0d0887', … '#f0f921'], min, max, steps } }, }, heatmap: { radius: 2, enableShades: true, shadeIntensity: 0.5, reverseNegativeShade: false, distributed: false, useFillColorAsStroke: false, colorScale: { inverse: false, ranges: [], min: undefined, max: undefined, // Replaces the default categorical legend with a continuous // gradient stripe + a hover indicator arrow. Honors // `chart.legend.position` (top / right / bottom / left). gradientLegend: { enabled: false, // Strip length along the legend's long axis. Accepts a number // (pixels) or a percentage string. For top/bottom placement the // percentage is resolved against the chart's SVG width; for // left/right placement, against the SVG height. width: '70%', height: '70%', thickness: 12, // Alignment of the strip within the legend area: // - top/bottom: 'start' = left, 'center', 'end' = right // - left/right: 'start' = top, 'center', 'end' = bottom align: 'center', // Number of gradient stops sampled from the shade function when // no explicit `ranges` are provided. stops: 16, // Show min/max labels at the ends of the strip. showLabels: true, // Show a value tooltip next to the arrow when hovering a cell. showHoverValue: true, labelStyle: { fontSize: '11px', fontFamily: undefined, colors: undefined, }, arrow: { size: 8, color: undefined, // falls back to chart.foreColor }, formatter: undefined, // (val) => string, for min/max + hover value }, }, }, funnel: { // 'rectangle' preserves the existing centered-rectangle funnel // geometry. 'trapezoid' produces continuous sloped sides between // consecutive stages (each stage's bottom width matches the next // stage's top width). shape: 'rectangle', // For shape: 'trapezoid' only — what to do with the last stage's // bottom edge: 'flat' (parallel sides) or 'taper' (taper to a point). lastShape: 'flat', }, treemap: { enableShades: true, shadeIntensity: 0.5, distributed: false, reverseNegativeShade: false, useFillColorAsStroke: false, borderRadius: 4, dataLabels: { format: 'scale', // scale | truncate }, colorScale: { inverse: false, ranges: [], min: undefined, max: undefined, }, seriesTitle: { show: true, offsetY: 1, offsetX: 1, borderColor: '#000', borderWidth: 1, borderRadius: 2, style: { background: 'rgba(0, 0, 0, 0.6)', color: '#fff', fontSize: '12px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 6, right: 6, top: 2, bottom: 2, }, }, }, }, unit: { // 'grouped' (each category is its own cluster, laid out in a row) | // 'packed' (one blob; categories coloured + sorted, minority centred) | // 'columns' (each category is a vertical bar built from stacked dots) | // 'grid' (one lattice of cells filled in category order - a waffle / // part-to-whole square "pie"; `chart.type:'waffle'` presets this). layout: 'grouped', // Update transition, controlling which previous dot each new dot // tweens from. 'group' (default): keyed per category, so dots stay in // their group and category-level enters/exits fade. 'flow': keyed by // global order, so the anonymous crowd migrates across a regroup (the // circles-to-bars effect). 'identity': keyed by each datum's id/name, // so a SPECIFIC unit migrates across any regroup/relayout keeping its // colour and size (needs the object form with unique ids/names). transition: 'group', // 'circle' | 'square' | 'image' (isotype pictogram). shape: 'circle', // Icon used when shape:'image'. Each unit renders this icon at the // given size. Set `tint:true` to recolour a monochrome icon to the // category colour (or a per-unit fillColor) so the pictogram matches // the legend; leave it off for multi-colour icons that should keep // their own colours. image: { src: undefined, width: 20, height: 20, tint: false, }, // dot radius in px, or 'auto' to size dots so the largest cluster // fits its allotted box. size: 'auto', // The 'columns' layout can size its dots independently of `size` // (which the circle layouts / storyboard beats often pin to a // constant so dots do not resize while migrating). 'inherit' uses // `size`; 'auto' sizes the dots to fill the plot height; a number // pins a columns-only size. Circle / square only (image icons keep // their intrinsic size). columns: { size: 'inherit', }, // The 'grid' (waffle) layout: one lattice of cells filled in category // order. `columns` = cells per row. `total` (optional) fixes the cell // budget - e.g. 100 for a percentage waffle - and largest-remainder // allocates the cells to categories; leave it undefined for one cell // per unit (respects unitValue / maxUnits). `fillFrom` picks the first // row: 'bottom' (default) or 'top'. // // `split:true` switches to SMALL MULTIPLES: one mini-waffle per // category, arranged in a near-square trellis (or `tileColumns` per // row). Each tile then has `total` cells (default 100) and fills a // fraction equal to the category's value over `max` (default = the // largest count, so the leader fills its tile; set `max:100` with // percentage data for true "of 100" tiles). The unfilled cells show as // a faint `trackColor` backdrop, and each tile gets its own label. grid: { columns: 10, total: undefined, fillFrom: 'bottom', // small-multiple (one waffle per category) mode + its knobs: split: false, // tiles per row; undefined = auto (near-square). tileColumns: undefined, // value -> filled-cell denominator; undefined = the largest count. max: undefined, // colour of the empty "track" cells; undefined = a neutral grey. trackColor: undefined, }, // The 'scatter' layout places each unit on real value axes (needs the // object-form data). Two modes via `y`: // - `y:'lanes'` (default): a BEESWARM. X is the per-unit value axis, // Y is a category lane. `spread:'swarm'` packs dots off the centre // line so equal values do not overlap; 'jitter' scatters randomly. // - `y:'value'`: a 2D value-value scatter. X = each datum's `x`, Y = // each datum's `y`, on two numeric axes; category = colour. // `sizeRange:[min,max]` turns dots into BUBBLES scaled (by area) from // each datum's `sizeField` (default 'z') - a bubble scatter / bubble // beeswarm. `tickAmount`/`xMin`/`xMax`/`xTitle`/`xFormatter` control the // X axis; the `y*` twins the Y axis (2D only); `laneLabelWidth` the // lane-label gutter (lanes mode); `gridlines` the grid. scatter: { y: 'lanes', spread: 'swarm', tickAmount: 5, xMin: undefined, xMax: undefined, xTitle: undefined, // (value) => string xFormatter: undefined, yTickAmount: 5, yMin: undefined, yMax: undefined, yTitle: undefined, // (value) => string yFormatter: undefined, // bubble sizing: datum key for the size value + [minR, maxR] in px. sizeField: 'z', sizeRange: undefined, laneLabelWidth: undefined, gridlines: true, }, // Opt-in bubble sizing: scale each dot's radius by its per-unit value // (needs the object-form data). Circle shape only; the lattice is // spaced for the largest bubble so dots never overlap. sizeByValue: { enabled: false, // radius (px) for the largest value, or 'auto' to fit the largest // bubble to the plot like uniform auto-sizing. maxRadius: 'auto', // radius (px) for the smallest value; defaults to ~35% of maxRadius. minRadius: undefined, // 'area' (bubble AREA proportional to value) | 'linear'. scale: 'area', }, // packing gap factor between spiral shells (1 = dots touch). spacing: 1.05, // corner radius for shape:'square'. borderRadius: 0, // 1 dot represents this many units of value (waffle scaling). unitValue: 1, // safety cap on total dots; counts scale down proportionally above it. maxUnits: 5000, // packed layout: order categories smallest-first so the minority // group nests in the centre of the blob. sortByGroup: true, clusterLabels: { show: true, // Label placement relative to the cluster/bar: 'top' (default) or // 'bottom'. A 'bottom' label is always straight; the curved arc // (below) rides the top crown only. position: 'top', curved: true, fontSize: '13px', fontFamily: undefined, fontWeight: 600, // defaults to the cluster's own colour when undefined. color: undefined, offsetY: 0, // (name, { seriesIndex, value, percent, w }) => string formatter: undefined, }, tooltip: { // Per-unit tooltip body. Each dot carries its category (seriesIndex) // and its index within that category (dataPointIndex), so the // formatter can look up per-unit data and return a string/HTML. // ({ seriesName, seriesIndex, dataPointIndex, count, unitValue, // color, w }) => string // Default: "#<dataPointIndex+1> of <count>". formatter: undefined, }, }, radialBar: { inverseOrder: false, startAngle: 0, endAngle: 360, offsetX: 0, offsetY: 0, // Gauge sub-shape. 'arc' (default) renders the existing filled // value-arc gauge; 'needle' replaces the value-arc with a rotating // pointer/needle. Bands and ticks are independent and work for both // shapes. shape: 'arc', // Value-to-angle mapping. Defaults to the existing 0..100 range // used by radialBar. Override for gauges that need a custom domain // (e.g. min: 0, max: 240 for a speedometer). min: 0, max: 100, // Threshold bands rendered as colored arc segments along the gauge // arc (e.g. [{from:0,to:30,color:'#FF4560'}, ...]). Bands draw // behind the value-arc and tick marks. Set to [] (default) to // disable. bands: [], bandsStyle: { // % of arc radius. Slightly less than the value-arc stroke so // the value-arc reads on top by default. strokeWidth: '40%', // px gap between consecutive bands. gap: 0, // Hide the track when bands cover the full range; the bands // themselves act as the visual backdrop. hideTrackWhenPresent: true, }, // Tick marks rendered along (outside) the gauge arc. ticks: { show: false, major: { count: 11, length: 10, width: 2, color: '#666', // 'inside' draws ticks from `radius - length` to `radius`; // 'outside' draws from `radius` to `radius + length`. placement: 'outside', }, minor: { count: 4, // minor ticks BETWEEN each pair of major ticks length: 5, width: 1, color: '#999', placement: 'outside', }, labels: { show: false, offset: 6, fontSize: '11px', fontFamily: undefined, fontWeight: 400, color: '#666', /** @param {number} v */ formatter(v) { return String(v) }, }, }, // Needle/dial configuration. Only applies when `shape: 'needle'`. needle: { color: '#333', // Needle length as a % of the gauge radius (string like '85%') // or as an absolute px number. length: '85%', // px width of the needle line at the base. baseWidth: 4, // px width of the needle tip (tapered if smaller than baseWidth). tipWidth: 1, // px offset from the geometric arc center on Y. Positive values // push the needle base down (toward the chord midpoint of a // ∩-shape gauge); negative pushes up. The needle rotates around // this shifted point. offsetY: 0, // When true, also render the filled value-arc alongside the // needle. Default false preserves the previous needle-only // behavior. Useful for gauges that want a progress ring plus a // pointer indicator. showValueArc: false, animation: { enabled: true, duration: 800, easing: 'ease-out', }, }, hollow: { margin: 5, size: '50%', background: 'transparent', image: undefined, imageWidth: 150, imageHeight: 150, imageOffsetX: 0, imageOffsetY: 0, imageClipped: true, position: 'front', // Optional stroke around the hollow ring. Combined with // `strokeDasharray` this produces a dashed indicator circle // around the value text — useful for gauge designs where the // value sits inside its own boundary. stroke: undefined, strokeWidth: 1, strokeDasharray: undefined, dropShadow: { enabled: false, top: 0, left: 0, blur: 3, color: '#000', opacity: 0.5, }, }, track: { show: true, startAngle: undefined, endAngle: undefined, background: '#f2f2f2', strokeWidth: '97%', opacity: 1, margin: 5, // margin is in pixels dropShadow: { enabled: false, top: 0, left: 0, blur: 3, color: '#000', opacity: 0.5, }, }, dataLabels: { show: true, name: { show: true, fontSize: '16px', fontFamily: undefined, fontWeight: 600, color: undefined, offsetY: 0, /** * @param {any} val */ formatter(val) { return val }, }, value: { show: true, fontSize: '14px', fontFamily: undefined, fontWeight: 400, color: undefined, offsetY: 16, /** * @param {any} val */ formatter(val) { return val + '%' }, }, total: { show: false, label: 'Total', fontSize: '16px', fontWeight: 600, fontFamily: undefined, color: undefined, /** * @param {import('../../types/internal').ChartStateW} w */ formatter(w) { return ( /** * @param {number} a * @param {number} b */ w.globals.seriesTotals.reduce((a, b) => a + b, 0) / w.seriesData.series.length + '%' ) }, }, }, barLabels: { enabled: false, offsetX: 0, offsetY: 0, useSeriesColors: true, fontFamily: undefined, fontWeight: 600, fontSize: '16px', /** * @param {any} val */ formatter(val) { return val }, onClick: undefined, }, }, pie: { customScale: 1, offsetX: 0, offsetY: 0, startAngle: 0, endAngle: 360, expandOnClick: true, dataLabels: { // These are the percentage values which are displayed on slice offset: 0, // offset by which labels will move outside minAngleToShowLabel: 10, // External (outer) labels: render the category/series name outside // the slice, joined to it by a leader (connector) line, so users // don't have to map legend colors back to slices. The percentage // keeps rendering inside the slice (governed by dataLabels.enabled). // Pie + donut only; ignored for polarArea (radial length already // encodes the value there). external: { show: false, // master switch for the external (outer) labels offsetX: 0, offsetY: 0, fontSize: undefined, // falls back to dataLabels.style.fontSize fontFamily: undefined, // falls back to dataLabels.style.fontFamily fontWeight: undefined, // falls back to dataLabels.style.fontWeight color: undefined, // defaults to chart.foreColor (readable text) /** * Return a string (single line) or an array of strings (stacked * lines, e.g. [name, percent + '%']). * @param {string} name * @param {{ seriesIndex: number, percent: number, value: number, w: any }} opts * @returns {string | string[]} */ formatter: undefined, connector: { show: true, width: 1, color: undefined, // defaults to the slice color length: 16, // horizontal run after the radial elbow (px) gap: 6, // radial gap from slice edge to the elbow point (px) }, }, }, donut: { size: '65%', background: 'transparent', labels: { // These are the inner labels appearing inside donut show: false, name: { show: true, fontSize: '16px', fontFamily: undefined, fontWeight: 600,