apexcharts 8.3.0 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/apexcharts.common.js +2 -2
- package/dist/apexcharts.core.js +20039 -19931
- package/dist/apexcharts.core.min.js +2 -2
- package/dist/apexcharts.css +3 -8
- package/dist/apexcharts.esm.js +950 -574
- package/dist/apexcharts.full.js +23401 -22504
- package/dist/apexcharts.full.min.js +2 -2
- package/dist/apexcharts.js +21723 -21287
- package/dist/apexcharts.min.js +2 -2
- package/dist/apexcharts.ssr.common.js +2 -2
- package/dist/apexcharts.ssr.esm.js +21758 -21242
- package/dist/area.common.js +2 -2
- package/dist/area.esm.js +118 -65
- package/dist/bar.common.js +2 -2
- package/dist/bar.esm.js +404 -218
- package/dist/bar.js +2 -2
- package/dist/boxPlot.common.js +2 -2
- package/dist/boxPlot.esm.js +379 -205
- package/dist/bubble.common.js +2 -2
- package/dist/bubble.esm.js +118 -65
- package/dist/candlestick.common.js +2 -2
- package/dist/candlestick.esm.js +379 -205
- package/dist/candlestick.js +2 -2
- package/dist/column.common.js +2 -2
- package/dist/column.esm.js +404 -218
- package/dist/core.common.js +2 -2
- package/dist/core.esm.js +20034 -19926
- package/dist/donut.common.js +2 -2
- package/dist/donut.esm.js +106 -11
- package/dist/dumbbell.common.js +2 -2
- package/dist/dumbbell.esm.js +404 -218
- package/dist/features/all.common.js +2 -2
- package/dist/features/all.esm.js +282 -184
- package/dist/features/annotations.common.js +2 -2
- package/dist/features/annotations.esm.js +65 -48
- package/dist/features/annotations.js +2 -2
- package/dist/features/context-menu.common.js +1 -1
- package/dist/features/context-menu.esm.js +1 -1
- package/dist/features/context-menu.js +1 -1
- package/dist/features/drilldown.common.js +2 -2
- package/dist/features/drilldown.esm.js +137 -124
- package/dist/features/drilldown.js +2 -2
- package/dist/features/dumbbell.common.js +1 -1
- package/dist/features/dumbbell.esm.js +1 -1
- package/dist/features/dumbbell.js +1 -1
- package/dist/features/exports.common.js +2 -2
- package/dist/features/exports.esm.js +31 -15
- package/dist/features/exports.js +2 -2
- package/dist/features/facet.common.js +1 -1
- package/dist/features/facet.esm.js +1 -1
- package/dist/features/facet.js +1 -1
- package/dist/features/highlight-filter.common.js +2 -2
- package/dist/features/highlight-filter.esm.js +206 -119
- package/dist/features/highlight-filter.js +2 -2
- package/dist/features/history.common.js +1 -1
- package/dist/features/history.esm.js +1 -1
- package/dist/features/history.js +1 -1
- package/dist/features/ink.common.js +1 -1
- package/dist/features/ink.esm.js +1 -1
- package/dist/features/ink.js +1 -1
- package/dist/features/keyboard.common.js +1 -1
- package/dist/features/keyboard.esm.js +1 -1
- package/dist/features/keyboard.js +1 -1
- package/dist/features/legend.common.js +2 -2
- package/dist/features/legend.esm.js +52 -28
- package/dist/features/legend.js +2 -2
- package/dist/features/link.common.js +1 -1
- package/dist/features/link.esm.js +1 -1
- package/dist/features/link.js +1 -1
- package/dist/features/marks.common.js +1 -1
- package/dist/features/marks.esm.js +1 -1
- package/dist/features/marks.js +1 -1
- package/dist/features/measure.common.js +1 -1
- package/dist/features/measure.esm.js +1 -1
- package/dist/features/measure.js +1 -1
- package/dist/features/morph.common.js +2 -2
- package/dist/features/morph.esm.js +27 -14
- package/dist/features/morph.js +2 -2
- package/dist/features/perspectives.common.js +2 -2
- package/dist/features/perspectives.esm.js +4 -1
- package/dist/features/perspectives.js +2 -2
- package/dist/features/raincloud.common.js +2 -2
- package/dist/features/raincloud.esm.js +26 -27
- package/dist/features/raincloud.js +2 -2
- package/dist/features/renderer-canvas.common.js +2 -2
- package/dist/features/renderer-canvas.esm.js +35 -21
- package/dist/features/renderer-canvas.js +2 -2
- package/dist/features/stats.common.js +2 -2
- package/dist/features/stats.esm.js +52 -59
- package/dist/features/stats.js +2 -2
- package/dist/features/storyboard.common.js +2 -2
- package/dist/features/storyboard.esm.js +4 -1
- package/dist/features/storyboard.js +2 -2
- package/dist/features/streamgraph.common.js +2 -2
- package/dist/features/streamgraph.esm.js +160 -55
- package/dist/features/streamgraph.js +2 -2
- package/dist/features/toolbar.common.js +2 -2
- package/dist/features/toolbar.esm.js +78 -28
- package/dist/features/toolbar.js +2 -2
- package/dist/features/trellis.common.js +2 -2
- package/dist/features/trellis.esm.js +876 -543
- package/dist/features/trellis.js +2 -2
- package/dist/features/waterfall.common.js +2 -2
- package/dist/features/waterfall.esm.js +14 -25
- package/dist/features/waterfall.js +2 -2
- package/dist/features/weave.common.js +2 -2
- package/dist/features/weave.esm.js +13 -12
- package/dist/features/weave.js +2 -2
- package/dist/full.common.js +2 -2
- package/dist/full.esm.js +1893 -1342
- package/dist/heatmap.common.js +2 -2
- package/dist/heatmap.esm.js +38 -54
- package/dist/heatmap.js +2 -2
- package/dist/histogram.common.js +2 -2
- package/dist/histogram.esm.js +455 -276
- package/dist/icicle.common.js +2 -2
- package/dist/icicle.esm.js +156 -91
- package/dist/icicle.js +2 -2
- package/dist/line.common.js +2 -2
- package/dist/line.esm.js +118 -65
- package/dist/line.js +2 -2
- package/dist/pictograms.common.js +2 -2
- package/dist/pictograms.esm.js +2 -2
- package/dist/pictograms.js +2 -2
- package/dist/pie.common.js +2 -2
- package/dist/pie.esm.js +106 -11
- package/dist/pie.js +2 -2
- package/dist/polarArea.common.js +2 -2
- package/dist/polarArea.esm.js +106 -11
- package/dist/radar.common.js +2 -2
- package/dist/radar.esm.js +23 -9
- package/dist/radar.js +2 -2
- package/dist/radialBar.common.js +2 -2
- package/dist/radialBar.esm.js +108 -14
- package/dist/radialBar.js +2 -2
- package/dist/raincloud.common.js +2 -2
- package/dist/raincloud.esm.js +39 -31
- package/dist/rangeArea.common.js +2 -2
- package/dist/rangeArea.esm.js +118 -65
- package/dist/rangeBar.common.js +2 -2
- package/dist/rangeBar.esm.js +404 -218
- package/dist/scatter.common.js +2 -2
- package/dist/scatter.esm.js +118 -65
- package/dist/streamgraph.common.js +2 -2
- package/dist/streamgraph.esm.js +276 -118
- package/dist/sunburst.common.js +2 -2
- package/dist/sunburst.esm.js +333 -116
- package/dist/sunburst.js +2 -2
- package/dist/treemap.common.js +2 -2
- package/dist/treemap.esm.js +155 -124
- package/dist/treemap.js +2 -2
- package/dist/unit-shapes.common.js +2 -2
- package/dist/unit-shapes.esm.js +2 -2
- package/dist/unit-shapes.js +2 -2
- package/dist/unit.common.js +2 -2
- package/dist/unit.esm.js +29 -27
- package/dist/unit.js +2 -2
- package/dist/violin.common.js +2 -2
- package/dist/violin.esm.js +14 -5
- package/dist/violin.js +2 -2
- package/dist/waterfall.common.js +2 -2
- package/dist/waterfall.esm.js +417 -242
- package/package.json +1 -1
- package/src/apexcharts.js +37 -60
- package/src/assets/apexcharts.css +3 -8
- package/src/charts/Bar.js +30 -12
- package/src/charts/BarStacked.js +10 -4
- package/src/charts/BoxCandleStick.js +8 -2
- package/src/charts/Icicle.js +60 -76
- package/src/charts/Line.js +58 -22
- package/src/charts/Pie.js +136 -14
- package/src/charts/Radar.js +6 -9
- package/src/charts/Radial.js +2 -6
- package/src/charts/RangeBar.js +13 -13
- package/src/charts/Scatter.js +5 -7
- package/src/charts/Sunburst.js +157 -135
- package/src/charts/Treemap.js +100 -56
- package/src/charts/common/Breadcrumb.js +37 -16
- package/src/charts/common/PreviousPaths.js +45 -0
- package/src/charts/common/Stats.js +30 -23
- package/src/charts/common/bar/DataLabels.js +85 -77
- package/src/charts/common/bar/Helpers.js +144 -56
- package/src/charts/common/line/Helpers.js +8 -11
- package/src/charts/common/partition/NodeTooltip.js +62 -22
- package/src/charts/common/partition/Partition.js +64 -19
- package/src/charts/common/partition/Tint.js +6 -3
- package/src/charts/common/partition/Transitions.js +108 -0
- package/src/charts/common/treemap/ColorScale.js +30 -14
- package/src/charts/common/treemap/Helpers.js +47 -68
- package/src/charts/common/treemap/Nested.js +2 -3
- package/src/features/raincloud.js +16 -10
- package/src/features/stats.js +67 -62
- package/src/modules/Animations.js +102 -95
- package/src/modules/AxisMapping.js +47 -12
- package/src/modules/Base.js +12 -14
- package/src/modules/CoreUtils.js +26 -46
- package/src/modules/Data.js +82 -55
- package/src/modules/DataLabels.js +14 -13
- package/src/modules/Exports.js +44 -19
- package/src/modules/Fill.js +17 -8
- package/src/modules/Filters.js +50 -50
- package/src/modules/Graphics.js +65 -84
- package/src/modules/Markers.js +57 -58
- package/src/modules/MorphPieces.js +16 -10
- package/src/modules/MorphTypeChange.js +21 -9
- package/src/modules/Range.js +32 -55
- package/src/modules/RendererController.js +4 -4
- package/src/modules/Responsive.js +5 -1
- package/src/modules/Scales.js +24 -15
- package/src/modules/Series.js +85 -73
- package/src/modules/Toolbar.js +3 -2
- package/src/modules/UnitLayoutRegistry.js +8 -5
- package/src/modules/UnitMarkRegistry.js +7 -10
- package/src/modules/ZoomPanSelection.js +4 -0
- package/src/modules/animations/AxisTransition.js +11 -4
- package/src/modules/animations/DataLabelTransition.js +30 -15
- package/src/modules/animations/Easing.js +2 -1
- package/src/modules/animations/LayoutTransition.js +43 -32
- package/src/modules/animations/LengthTransition.js +176 -84
- package/src/modules/annotations/Helpers.js +68 -52
- package/src/modules/axes/AxesUtils.js +14 -12
- package/src/modules/axes/Grid.js +21 -7
- package/src/modules/axes/XAxis.js +4 -4
- package/src/modules/axes/YAxis.js +12 -13
- package/src/modules/dimensions/Dimensions.js +9 -3
- package/src/modules/dimensions/Grid.js +2 -2
- package/src/modules/dimensions/XAxis.js +2 -5
- package/src/modules/drilldown/Breadcrumb.js +11 -53
- package/src/modules/drilldown/Drilldown.js +151 -95
- package/src/modules/helpers/InitCtxVariables.js +2 -1
- package/src/modules/helpers/UpdateHelpers.js +165 -15
- package/src/modules/helpers/XKey.js +56 -0
- package/src/modules/highlightFilter/HighlightFilter.js +98 -49
- package/src/modules/highlightFilter/PiePart.js +6 -3
- package/src/modules/highlightFilter/RadialPart.js +41 -7
- package/src/modules/highlightFilter/TreemapPart.js +71 -44
- package/src/modules/highlightFilter/util.js +23 -7
- package/src/modules/legend/Helpers.js +6 -1
- package/src/modules/legend/Legend.js +39 -13
- package/src/modules/license/LicenseEnforcer.js +5 -0
- package/src/modules/settings/Defaults.js +62 -106
- package/src/modules/settings/Globals.js +5 -0
- package/src/modules/settings/Options.js +0 -7
- package/src/modules/settings/TypeAliases.js +33 -16
- package/src/modules/streamgraph/StreamData.js +81 -35
- package/src/modules/streamgraph/StreamLabels.js +44 -17
- package/src/modules/tooltip/Labels.js +80 -80
- package/src/modules/tooltip/Marker.js +25 -21
- package/src/modules/tooltip/Position.js +88 -51
- package/src/modules/tooltip/Tooltip.js +229 -253
- package/src/modules/tooltip/Utils.js +64 -131
- package/src/modules/tooltip/constants.js +5 -5
- package/src/modules/trellis/Trellis.js +402 -248
- package/src/modules/trellis/TrellisChrome.js +110 -44
- package/src/modules/trellis/TrellisExports.js +48 -13
- package/src/modules/trellis/TrellisFrames.js +11 -15
- package/src/modules/trellis/TrellisScales.js +201 -115
- package/src/modules/trellis/TrellisSplit.js +72 -36
- package/src/modules/trellis/TrellisSync.js +41 -13
- package/src/modules/trellis/TrellisTooltip.js +101 -78
- package/src/modules/trellis/pivotRows.js +20 -6
- package/src/modules/waterfall/WaterfallData.js +14 -30
- package/src/modules/weave/WeaveHost.js +18 -12
- package/src/pictograms/registry.js +2 -1
- package/src/renderers/Renderer.js +41 -37
- package/src/renderers/canvas/CanvasCompositor.js +4 -1
- package/src/renderers/canvas/CanvasGraphics.js +56 -24
- package/src/ssr/RenderShim.js +129 -20
- package/src/svg/SVGContainer.js +3 -2
- package/src/svg/SVGFilter.js +26 -17
- package/src/types/internal.d.ts +8 -6
- package/src/unit-shapes/registry.js +3 -1
- package/src/utils/DateTime.js +5 -20
- package/src/utils/Utils.js +0 -14
- package/src/utils/nameAsHtml.js +16 -0
- package/types/apexcharts.d.ts +72 -13
package/src/features/stats.js
CHANGED
|
@@ -45,6 +45,7 @@ import { collapsedIndices, stashSeries } from '../modules/helpers/RawStash'
|
|
|
45
45
|
import {
|
|
46
46
|
binCounts,
|
|
47
47
|
computeBinning,
|
|
48
|
+
deriveStat,
|
|
48
49
|
derivedStats,
|
|
49
50
|
fiveNumberSummary,
|
|
50
51
|
isDerived,
|
|
@@ -204,45 +205,19 @@ function histogramTransform(ser, w) {
|
|
|
204
205
|
* @returns {any[]}
|
|
205
206
|
*/
|
|
206
207
|
function boxPlotTransform(ser, w) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const data = s.data.map((/** @type {any} */ d, /** @type {number} */ j) => {
|
|
221
|
-
// An existing summary wins: this is the documented input shape. Unless we
|
|
222
|
-
// are the ones who derived it, in which case the options that shaped it
|
|
223
|
-
// may have changed.
|
|
224
|
-
const key = i + ':' + j
|
|
225
|
-
if (
|
|
226
|
-
Array.isArray(d?.y) &&
|
|
227
|
-
d.y.length === 5 &&
|
|
228
|
-
!isDerived(derived, key, d.y)
|
|
229
|
-
) {
|
|
230
|
-
return d
|
|
231
|
-
}
|
|
232
|
-
const values = observationsOf(d, false)
|
|
233
|
-
if (!values) return d
|
|
234
|
-
const summary = fiveNumberSummary(values, { whiskers })
|
|
235
|
-
if (!summary) return d
|
|
236
|
-
touched = true
|
|
237
|
-
byPoint[j] = values
|
|
238
|
-
derived.set(key, summary.summary)
|
|
239
|
-
return { ...d, y: summary.summary, points: values }
|
|
240
|
-
})
|
|
241
|
-
if (touched) observed[i] = byPoint
|
|
242
|
-
return touched ? { ...s, data } : s
|
|
243
|
-
})
|
|
244
|
-
recordObservations(w, observed, ser.length)
|
|
245
|
-
return out
|
|
208
|
+
return sampleTransform(
|
|
209
|
+
ser,
|
|
210
|
+
w,
|
|
211
|
+
'boxPlot',
|
|
212
|
+
{ whiskers: w.config.plotOptions?.boxPlot?.whiskers || 'minmax' },
|
|
213
|
+
fiveNumberSummary,
|
|
214
|
+
(/** @type {any} */ d) => Array.isArray(d?.y) && d.y.length === 5 && d.y,
|
|
215
|
+
(/** @type {any} */ d, /** @type {any} */ est, /** @type {number[]} */ values) => ({
|
|
216
|
+
...d,
|
|
217
|
+
y: est.summary,
|
|
218
|
+
points: values,
|
|
219
|
+
}),
|
|
220
|
+
)
|
|
246
221
|
}
|
|
247
222
|
|
|
248
223
|
/**
|
|
@@ -261,43 +236,73 @@ function boxPlotTransform(ser, w) {
|
|
|
261
236
|
* @returns {any[]}
|
|
262
237
|
*/
|
|
263
238
|
function violinTransform(ser, w) {
|
|
264
|
-
if (!Array.isArray(ser)) return ser
|
|
265
239
|
const kde = w.config.plotOptions?.violin?.kde || {}
|
|
266
|
-
|
|
240
|
+
return sampleTransform(
|
|
241
|
+
ser,
|
|
242
|
+
w,
|
|
243
|
+
'violin',
|
|
244
|
+
{ bandwidth: kde.bandwidth, resolution: kde.resolution },
|
|
245
|
+
kernelDensity,
|
|
246
|
+
(/** @type {any} */ d) =>
|
|
247
|
+
Array.isArray(d?.y?.density) && d.y.density.length && d.y.density,
|
|
248
|
+
(/** @type {any} */ d, /** @type {any} */ est, /** @type {number[]} */ values) => ({
|
|
249
|
+
...d,
|
|
250
|
+
// Keep the rest of an object `y`: a summary given with the points still
|
|
251
|
+
// draws the box lane.
|
|
252
|
+
y: {
|
|
253
|
+
...(d.y && typeof d.y === 'object' && !Array.isArray(d.y) ? d.y : {}),
|
|
254
|
+
density: est.density,
|
|
255
|
+
points: values,
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The shared walk of the boxPlot and violin transforms: every datum of every
|
|
263
|
+
* series of `type` that carries a sample and no statistic of its own (or the
|
|
264
|
+
* one this transform wrote last pass) gets `fn(sample, opts)`, written by
|
|
265
|
+
* `write`.
|
|
266
|
+
*
|
|
267
|
+
* A combo's other series are not samples: a violin series carries its jitter
|
|
268
|
+
* in `points` too, and a boxPlot's or a rangeArea's `y` is a flat number
|
|
269
|
+
* array, which a violin would estimate into a density.
|
|
270
|
+
*
|
|
271
|
+
* @param {any[]} ser
|
|
272
|
+
* @param {any} w
|
|
273
|
+
* @param {string} type
|
|
274
|
+
* @param {any} opts
|
|
275
|
+
* @param {(values: number[], opts: any) => any} fn
|
|
276
|
+
* @param {(d: any) => any} statOf - the datum's own statistic, or falsy
|
|
277
|
+
* @param {(d: any, est: any, values: number[]) => any} write
|
|
278
|
+
* @returns {any[]}
|
|
279
|
+
*/
|
|
280
|
+
function sampleTransform(ser, w, type, opts, fn, statOf, write) {
|
|
281
|
+
if (!Array.isArray(ser)) return ser
|
|
282
|
+
const derived = derivedStats(w, type)
|
|
267
283
|
/** @type {Array<Array<number[] | null>>} */
|
|
268
284
|
const observed = []
|
|
269
285
|
|
|
270
286
|
const out = ser.map((/** @type {any} */ s, /** @type {number} */ i) => {
|
|
271
|
-
|
|
272
|
-
// `y` is a flat number array too, and was estimated into a density.
|
|
273
|
-
if (!Array.isArray(s?.data) || (s.type && s.type !== 'violin')) return s
|
|
287
|
+
if (!Array.isArray(s?.data) || (s.type && s.type !== type)) return s
|
|
274
288
|
let touched = false
|
|
275
289
|
/** @type {Array<number[] | null>} */
|
|
276
290
|
const byPoint = new Array(s.data.length).fill(null)
|
|
277
291
|
const data = s.data.map((/** @type {any} */ d, /** @type {number} */ j) => {
|
|
292
|
+
// An existing statistic wins: this is the documented input shape. Unless
|
|
293
|
+
// we are the ones who derived it, in which case the options that shaped
|
|
294
|
+
// it may have changed.
|
|
278
295
|
const key = i + ':' + j
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
) {
|
|
284
|
-
return d
|
|
285
|
-
}
|
|
286
|
-
const values = observationsOf(d, true)
|
|
296
|
+
const stat = statOf(d)
|
|
297
|
+
if (stat && !isDerived(derived, key, stat)) return d
|
|
298
|
+
// Only a density-based type reads a flat number `y` as the sample.
|
|
299
|
+
const values = observationsOf(d, type === 'violin')
|
|
287
300
|
if (!values) return d
|
|
288
|
-
const est =
|
|
289
|
-
bandwidth: kde.bandwidth,
|
|
290
|
-
resolution: kde.resolution,
|
|
291
|
-
})
|
|
301
|
+
const est = deriveStat(derived, key, values, opts, fn)
|
|
292
302
|
if (!est) return d
|
|
293
303
|
touched = true
|
|
294
304
|
byPoint[j] = values
|
|
295
|
-
|
|
296
|
-
// draws the box lane.
|
|
297
|
-
const rest =
|
|
298
|
-
d.y && typeof d.y === 'object' && !Array.isArray(d.y) ? d.y : {}
|
|
299
|
-
derived.set(key, est.density)
|
|
300
|
-
return { ...d, y: { ...rest, density: est.density, points: values } }
|
|
305
|
+
return write(d, est, values)
|
|
301
306
|
})
|
|
302
307
|
if (touched) observed[i] = byPoint
|
|
303
308
|
return touched ? { ...s, data } : s
|
|
@@ -30,6 +30,57 @@ function easeOutBack(t) {
|
|
|
30
30
|
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Each chart's mount frame loop: the steppers below (sweep, pop, draw) used
|
|
35
|
+
* to poll one requestAnimationFrame chain per element, so a line with 2,000
|
|
36
|
+
* markers and labels ran 4,000 callbacks a frame. They queue jobs here and
|
|
37
|
+
* share ONE rAF per chart per frame, which stops when the queue drains or
|
|
38
|
+
* the chart is destroyed. A job returns true to run again next frame, or a
|
|
39
|
+
* function: its writes, run once every job has done its reads. A job queued
|
|
40
|
+
* during a frame first runs on the next, as its own rAF did.
|
|
41
|
+
* State per chart: `q` the next frame's jobs, `n` the pops in flight.
|
|
42
|
+
* @type {WeakMap<object, any>}
|
|
43
|
+
*/
|
|
44
|
+
const loops = new WeakMap()
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {import('../types/internal').ChartStateW} w
|
|
48
|
+
* @param {(now: number) => any} job
|
|
49
|
+
* @returns {any} the chart's loop state
|
|
50
|
+
*/
|
|
51
|
+
function onFrame(w, job) {
|
|
52
|
+
let s = loops.get(w)
|
|
53
|
+
if (!s) loops.set(w, (s = { n: 0, q: [] }))
|
|
54
|
+
// The first job queued for a frame requests it.
|
|
55
|
+
if (s.q.push(job) < 2) {
|
|
56
|
+
BrowserAPIs.requestAnimationFrame((now) => {
|
|
57
|
+
const jobs = s.q
|
|
58
|
+
s.q = []
|
|
59
|
+
// for...of also visits the writes appended mid-loop, after every read.
|
|
60
|
+
for (const j of jobs) {
|
|
61
|
+
// A destroyed chart drops its queue and its pop count, checked per
|
|
62
|
+
// job: an animationEnd handler a job reaches may destroy it.
|
|
63
|
+
if (w.globals.isDestroyed) {
|
|
64
|
+
s.n = 0
|
|
65
|
+
break
|
|
66
|
+
}
|
|
67
|
+
// A throw (a user handler) loses only its own job, as when each
|
|
68
|
+
// element had its own rAF, and is reported once the frame is done.
|
|
69
|
+
try {
|
|
70
|
+
const r = j(now)
|
|
71
|
+
if (r === true) onFrame(w, j)
|
|
72
|
+
else if (r) jobs.push(r)
|
|
73
|
+
} catch (e) {
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
throw e
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
return s
|
|
82
|
+
}
|
|
83
|
+
|
|
33
84
|
/**
|
|
34
85
|
* Cached reduced-motion query — `matchMedia` evaluation is cheap but the
|
|
35
86
|
* MediaQueryList instance is reused if a chart re-renders.
|
|
@@ -116,29 +167,20 @@ export function applyProgressiveReveal(el, x, w) {
|
|
|
116
167
|
const easedT = 1 - Math.cbrt(1 - xRatio)
|
|
117
168
|
const revealDelay = easedT * drawSpeed
|
|
118
169
|
|
|
119
|
-
const
|
|
120
|
-
const style = node.style
|
|
170
|
+
const style = el.node.style
|
|
121
171
|
style.opacity = '0'
|
|
122
172
|
|
|
123
|
-
// Anchor on the first
|
|
124
|
-
// as its t=0
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// would override the element's SVG `opacity` attribute (e.g. an
|
|
135
|
-
// x-axis range annotation rect with `opacity: 0.4`).
|
|
136
|
-
style.opacity = ''
|
|
137
|
-
} else {
|
|
138
|
-
BrowserAPIs.requestAnimationFrame(tick)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
BrowserAPIs.requestAnimationFrame(tick)
|
|
173
|
+
// Anchor on the first frame after render, the same frame `animateDraw` uses
|
|
174
|
+
// as its t=0, so reveal and draw share an origin; snap on frame boundaries.
|
|
175
|
+
let startAnchor = -1
|
|
176
|
+
onFrame(w, (/** @type {number} */ now) => {
|
|
177
|
+
if (startAnchor < 0) startAnchor = now
|
|
178
|
+
if (now - startAnchor < revealDelay) return true
|
|
179
|
+
// Clear the inline opacity rather than forcing '1': an inline style
|
|
180
|
+
// would override the element's SVG `opacity` attribute (e.g. an
|
|
181
|
+
// x-axis range annotation rect with `opacity: 0.4`).
|
|
182
|
+
style.opacity = ''
|
|
183
|
+
})
|
|
142
184
|
return true
|
|
143
185
|
}
|
|
144
186
|
|
|
@@ -301,30 +343,25 @@ export default class Animations {
|
|
|
301
343
|
style.transform = 'scale(0)'
|
|
302
344
|
style.opacity = '0'
|
|
303
345
|
|
|
346
|
+
// Pops land in stagger order, so the animation is over when the LAST one
|
|
347
|
+
// lands: completion waits for the chart's pop count to drain. A destroyed
|
|
348
|
+
// chart's loop stops before it, so animationEnd never fires on a
|
|
349
|
+
// torn-down chart (react-apexcharts#602).
|
|
304
350
|
const startAt = performance.now() + delay
|
|
305
|
-
/** @
|
|
306
|
-
const step = (now) => {
|
|
307
|
-
// Chart may have been destroyed before this frame ran (React StrictMode
|
|
308
|
-
// mount/unmount, route change). Bail without rescheduling and without
|
|
309
|
-
// onComplete, which would fire animationEnd on a torn-down chart. Mirrors
|
|
310
|
-
// the guard in animateDraw (see react-apexcharts#602).
|
|
311
|
-
if (w.globals.isDestroyed) return
|
|
351
|
+
const s = onFrame(w, (/** @type {number} */ now) => {
|
|
312
352
|
const t = Math.max(0, Math.min(1, (now - startAt) / speed))
|
|
313
353
|
style.transform = `scale(${easeOutBack(t)})`
|
|
314
354
|
// Fade in over the first half so the back-out overshoot is visible
|
|
315
355
|
// (rather than blasted in at full opacity from frame 1).
|
|
316
356
|
style.opacity = String(Math.min(1, t * 2))
|
|
317
|
-
if (t < 1)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
BrowserAPIs.requestAnimationFrame(step)
|
|
357
|
+
if (t < 1) return true
|
|
358
|
+
style.transform = ''
|
|
359
|
+
style.transformOrigin = ''
|
|
360
|
+
style.transformBox = ''
|
|
361
|
+
style.opacity = ''
|
|
362
|
+
if (!--s.n && onComplete) onComplete()
|
|
363
|
+
})
|
|
364
|
+
s.n++
|
|
328
365
|
}
|
|
329
366
|
|
|
330
367
|
/*
|
|
@@ -423,9 +460,8 @@ export default class Animations {
|
|
|
423
460
|
|
|
424
461
|
if (!w.globals.bulkRevealScheduled) {
|
|
425
462
|
w.globals.bulkRevealScheduled = true
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (w.globals.isDestroyed) return
|
|
463
|
+
// the frame loop skips it on a chart destroyed before it ran
|
|
464
|
+
onFrame(w, () => {
|
|
429
465
|
w.globals.bulkRevealScheduled = false
|
|
430
466
|
const faded = w.globals.fadeRevealEls
|
|
431
467
|
w.globals.fadeRevealEls = []
|
|
@@ -566,9 +602,7 @@ export default class Animations {
|
|
|
566
602
|
node.setAttribute('mask', `url(#${maskId})`)
|
|
567
603
|
|
|
568
604
|
const startAt = performance.now() + (delay || 0)
|
|
569
|
-
/** @
|
|
570
|
-
const step = (now) => {
|
|
571
|
-
if (w.globals.isDestroyed) return
|
|
605
|
+
onFrame(w, (/** @type {number} */ now) => {
|
|
572
606
|
const t = Math.max(0, Math.min(1, (now - startAt) / speed))
|
|
573
607
|
const eased = easeOutCubic(t)
|
|
574
608
|
if (isRadial) {
|
|
@@ -576,15 +610,11 @@ export default class Animations {
|
|
|
576
610
|
} else {
|
|
577
611
|
revealEl.setAttribute('width', String(eased * targetWidth))
|
|
578
612
|
}
|
|
579
|
-
if (t < 1)
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
finalize()
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
BrowserAPIs.requestAnimationFrame(step)
|
|
613
|
+
if (t < 1) return true
|
|
614
|
+
node.removeAttribute('mask')
|
|
615
|
+
if (mask.parentNode) mask.parentNode.removeChild(mask)
|
|
616
|
+
finalize()
|
|
617
|
+
})
|
|
588
618
|
}
|
|
589
619
|
|
|
590
620
|
// Stroke draw via stroke-dashoffset (only safe when no custom dash pattern exists).
|
|
@@ -594,58 +624,35 @@ export default class Animations {
|
|
|
594
624
|
node.setAttribute('stroke-dashoffset', String(len))
|
|
595
625
|
|
|
596
626
|
const startAt = performance.now() + (delay || 0)
|
|
597
|
-
/** @
|
|
598
|
-
const step = (now) => {
|
|
599
|
-
if (w.globals.isDestroyed) return
|
|
627
|
+
onFrame(w, (/** @type {number} */ now) => {
|
|
600
628
|
const t = Math.max(0, Math.min(1, (now - startAt) / speed))
|
|
601
629
|
node.setAttribute('stroke-dashoffset', String(len * (1 - easeOutCubic(t))))
|
|
602
|
-
if (t < 1)
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
finalize()
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
BrowserAPIs.requestAnimationFrame(step)
|
|
630
|
+
if (t < 1) return true
|
|
631
|
+
node.removeAttribute('stroke-dasharray')
|
|
632
|
+
node.removeAttribute('stroke-dashoffset')
|
|
633
|
+
finalize()
|
|
634
|
+
})
|
|
611
635
|
}
|
|
612
636
|
|
|
613
637
|
// Defer one frame: callers (e.g. Line.js for forecast paths) set stroke-dasharray
|
|
614
|
-
// *after* renderPaths returns, so a sync check would miss it.
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if (isFill) {
|
|
623
|
-
runMaskReveal()
|
|
624
|
-
return
|
|
625
|
-
}
|
|
626
|
-
|
|
638
|
+
// *after* renderPaths returns, so a sync check would miss it. The job only
|
|
639
|
+
// reads (dash, length) and hands back its writes, which the loop runs
|
|
640
|
+
// after every path's reads, so N series cost one style and layout flush,
|
|
641
|
+
// not N. The loop skips it on a destroyed chart, whose DOM is gone
|
|
642
|
+
// (react-apexcharts#602).
|
|
643
|
+
onFrame(w, () => {
|
|
644
|
+
// A stroke with a custom dash pattern keeps it and reveals via the mask
|
|
645
|
+
// instead of fighting dashoffset.
|
|
627
646
|
const existingDash = node.getAttribute('stroke-dasharray')
|
|
628
|
-
|
|
629
|
-
!!existingDash && existingDash !== '0' && existingDash !== ''
|
|
630
|
-
if (hasCustomDash) {
|
|
631
|
-
// Preserve dash pattern; reveal via mask instead of fighting dashoffset.
|
|
632
|
-
runMaskReveal()
|
|
633
|
-
return
|
|
634
|
-
}
|
|
647
|
+
if (isFill || (existingDash && existingDash !== '0')) return runMaskReveal
|
|
635
648
|
|
|
636
649
|
let len = 0
|
|
637
650
|
try {
|
|
638
|
-
|
|
639
|
-
len = node.getTotalLength()
|
|
640
|
-
}
|
|
651
|
+
len = node.getTotalLength()
|
|
641
652
|
} catch (_) {
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
if (!len) {
|
|
645
|
-
finalize()
|
|
646
|
-
return
|
|
653
|
+
// no geometry to measure: nothing to draw
|
|
647
654
|
}
|
|
648
|
-
runStrokeDraw(len)
|
|
655
|
+
return len ? () => runStrokeDraw(len) : finalize
|
|
649
656
|
})
|
|
650
657
|
}
|
|
651
658
|
|
|
@@ -65,21 +65,56 @@ export default class AxisMapping {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
68
|
+
* The plot area on screen, in client px: its corner is where the plot's
|
|
69
|
+
* group is translated to (translateX, translateY into the svg), and it is
|
|
70
|
+
* gridWidth by gridHeight. The one screen-to-plot measurement: the tooltip,
|
|
71
|
+
* zoom, selection and every other pointer reader map through it, so x and y
|
|
72
|
+
* cannot disagree under CSS zoom.
|
|
73
|
+
*
|
|
74
|
+
* Never the `.apexcharts-grid` group's box: a group measures to the union
|
|
75
|
+
* of what it happens to draw (fact 2 above). The plot's outline starts a
|
|
76
|
+
* pixel down (`Grid.drawGridArea`), so unless gridlines or row bands reach
|
|
77
|
+
* the top edge the box starts a pixel below the plot, and on a numeric-x bar
|
|
78
|
+
* chart the horizontal gridlines run `barPadForNumericAxis` out past both
|
|
79
|
+
* sides.
|
|
80
|
+
*
|
|
81
|
+
* `zoom` is the CSS zoom of any container the chart sits in (screen px per
|
|
82
|
+
* plot px): the measured svg width over `svgWidth`, the unscaled width it
|
|
83
|
+
* was drawn at. A distance measured on screen from this corner is divided
|
|
84
|
+
* by it to land in plot px, the space the series are laid out and painted in.
|
|
85
|
+
* With nothing mounted to measure, screen px are taken as svg px.
|
|
86
|
+
*
|
|
87
|
+
* @param {import('../types/internal').ChartStateW} w
|
|
88
|
+
* @returns {{ left: number, top: number, width: number, height: number, zoom: number }}
|
|
89
|
+
*/
|
|
90
|
+
static plotRect(w) {
|
|
91
|
+
const svg =
|
|
92
|
+
w.dom.Paper?.node || w.dom.baseEl?.querySelector('.apexcharts-svg')
|
|
93
|
+
const box = (svg || w.dom.elWrap)?.getBoundingClientRect() || {
|
|
94
|
+
left: 0,
|
|
95
|
+
top: 0,
|
|
96
|
+
width: 0,
|
|
97
|
+
}
|
|
98
|
+
const zoom =
|
|
99
|
+
(svg && w.globals.svgWidth ? box.width / w.globals.svgWidth : 1) || 1
|
|
100
|
+
return {
|
|
101
|
+
left: box.left + w.layout.translateX * zoom,
|
|
102
|
+
top: box.top + w.layout.translateY * zoom,
|
|
103
|
+
width: w.layout.gridWidth * zoom,
|
|
104
|
+
height: w.layout.gridHeight * zoom,
|
|
105
|
+
zoom,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Client (screen) x -> pixels from the plot origin of {@link plotRect}.
|
|
111
|
+
* Pass the rect when the caller has already measured it.
|
|
73
112
|
* @param {import('../types/internal').ChartStateW} w
|
|
74
113
|
* @param {number} screenX
|
|
114
|
+
* @param {{ left: number, zoom: number }} [plot]
|
|
75
115
|
* @returns {number}
|
|
76
116
|
*/
|
|
77
|
-
static screenXToPlotPx(w, screenX) {
|
|
78
|
-
|
|
79
|
-
const svg = baseEl && baseEl.querySelector('.apexcharts-svg')
|
|
80
|
-
if (!svg) return screenX - w.layout.translateX
|
|
81
|
-
const svgRect = svg.getBoundingClientRect()
|
|
82
|
-
const zoom = w.globals.svgWidth ? svgRect.width / w.globals.svgWidth : 1
|
|
83
|
-
return (screenX - svgRect.left) / (zoom || 1) - w.layout.translateX
|
|
117
|
+
static screenXToPlotPx(w, screenX, plot = AxisMapping.plotRect(w)) {
|
|
118
|
+
return (screenX - plot.left) / plot.zoom
|
|
84
119
|
}
|
|
85
120
|
}
|
package/src/modules/Base.js
CHANGED
|
@@ -133,23 +133,21 @@ export default class Base {
|
|
|
133
133
|
// Cleared at the top of every parse, filled by features/stats, read by
|
|
134
134
|
// Weave's api.data. null on every chart that has no such transform.
|
|
135
135
|
seriesObservations: null,
|
|
136
|
-
// Waterfall accumulation
|
|
136
|
+
// Waterfall accumulation, written by the waterfall series transform
|
|
137
137
|
// (features/waterfall) each parse; empty for every other chart type.
|
|
138
|
-
// values[i][j]
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
138
|
+
// values[i][j] = the bar's signed height (end - start), which is
|
|
139
|
+
// the delta for a step bar and the sum for a
|
|
140
|
+
// subtotal / total bar. This is what a label and a
|
|
141
|
+
// tooltip show, in place of the "start - end" a
|
|
142
|
+
// range bar would otherwise read out. Empty for a
|
|
143
|
+
// combo series of another type.
|
|
144
|
+
// geometry[i][j] = the px box the bar was actually drawn in, recorded
|
|
145
|
+
// by RangeBar. The connectors are drawn from these
|
|
146
|
+
// boxes alone (the level is the box's far edge).
|
|
147
|
+
// Present (as []) only on a waterfall, which is what
|
|
148
|
+
// tells RangeBar to record at all.
|
|
149
149
|
waterfallData: {
|
|
150
150
|
values: [],
|
|
151
|
-
cumulative: [],
|
|
152
|
-
kinds: [],
|
|
153
151
|
geometry: null,
|
|
154
152
|
},
|
|
155
153
|
// Dumbbell endpoints, written by the dumbbell series transform
|
package/src/modules/CoreUtils.js
CHANGED
|
@@ -91,29 +91,21 @@ class CoreUtils {
|
|
|
91
91
|
return total
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
// get total of the all values inside all series
|
|
95
94
|
/**
|
|
96
|
-
*
|
|
95
|
+
* The total of one series; 0 for an index that names no series.
|
|
96
|
+
* @param {number} index
|
|
97
97
|
*/
|
|
98
|
-
getSeriesTotalByIndex(index
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
0,
|
|
104
|
-
)
|
|
105
|
-
} else {
|
|
106
|
-
const seriesAtIndex = this.w.seriesData.series[index]
|
|
107
|
-
if (!Array.isArray(seriesAtIndex)) {
|
|
108
|
-
// pie/donut/polarArea/radialBar called per-index from legend loop
|
|
109
|
-
return seriesAtIndex ?? 0
|
|
110
|
-
}
|
|
111
|
-
// axis charts - supporting multiple series
|
|
112
|
-
return seriesAtIndex.reduce(
|
|
113
|
-
(/** @type {any} */ acc, /** @type {any} */ cur) => acc + cur,
|
|
114
|
-
0,
|
|
115
|
-
)
|
|
98
|
+
getSeriesTotalByIndex(index) {
|
|
99
|
+
const seriesAtIndex = this.w.seriesData.series[index]
|
|
100
|
+
if (!Array.isArray(seriesAtIndex)) {
|
|
101
|
+
// pie/donut/polarArea/radialBar called per-index from legend loop
|
|
102
|
+
return seriesAtIndex ?? 0
|
|
116
103
|
}
|
|
104
|
+
// axis charts - supporting multiple series
|
|
105
|
+
return seriesAtIndex.reduce(
|
|
106
|
+
(/** @type {any} */ acc, /** @type {any} */ cur) => acc + cur,
|
|
107
|
+
0,
|
|
108
|
+
)
|
|
117
109
|
}
|
|
118
110
|
|
|
119
111
|
/**
|
|
@@ -328,29 +320,16 @@ class CoreUtils {
|
|
|
328
320
|
}
|
|
329
321
|
|
|
330
322
|
/**
|
|
331
|
-
*
|
|
323
|
+
* Does the series hold no value at all? True for an index that names none.
|
|
324
|
+
* @param {number} index
|
|
332
325
|
*/
|
|
333
|
-
isSeriesNull(index
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const seriesAtIndex = this.w.seriesData.series[index]
|
|
341
|
-
if (Array.isArray(seriesAtIndex)) {
|
|
342
|
-
// axis charts - supporting multiple series
|
|
343
|
-
r = seriesAtIndex.filter((/** @type {any} */ d) => d !== null)
|
|
344
|
-
} else {
|
|
345
|
-
// pie/donut/polarArea/radialBar called per-index from legend loop
|
|
346
|
-
r =
|
|
347
|
-
seriesAtIndex !== null && seriesAtIndex !== undefined
|
|
348
|
-
? [seriesAtIndex]
|
|
349
|
-
: []
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return r.length === 0
|
|
326
|
+
isSeriesNull(index) {
|
|
327
|
+
const seriesAtIndex = this.w.seriesData.series[index]
|
|
328
|
+
// axis charts hold an array per series; pie/donut/polarArea/radialBar a
|
|
329
|
+
// single value, read per index from the legend loop
|
|
330
|
+
return Array.isArray(seriesAtIndex)
|
|
331
|
+
? seriesAtIndex.every((/** @type {any} */ d) => d === null)
|
|
332
|
+
: seriesAtIndex == null
|
|
354
333
|
}
|
|
355
334
|
|
|
356
335
|
/**
|
|
@@ -750,14 +729,15 @@ class CoreUtils {
|
|
|
750
729
|
return 0 // Should be Number.NEGATIVE_INFINITY
|
|
751
730
|
}
|
|
752
731
|
const w = this.w
|
|
732
|
+
const boundsIndex = w.globals.isMultipleYAxis ? seriesIndex : 0
|
|
753
733
|
const min_log_val =
|
|
754
|
-
w.globals.minYArr[
|
|
734
|
+
w.globals.minYArr[boundsIndex] === 0
|
|
755
735
|
? -1 // make sure we dont calculate log of 0
|
|
756
|
-
: this.getBaseLog(b, w.globals.minYArr[
|
|
736
|
+
: this.getBaseLog(b, w.globals.minYArr[boundsIndex])
|
|
757
737
|
const max_log_val =
|
|
758
|
-
w.globals.maxYArr[
|
|
738
|
+
w.globals.maxYArr[boundsIndex] === 0
|
|
759
739
|
? 0 // make sure we dont calculate log of 0
|
|
760
|
-
: this.getBaseLog(b, w.globals.maxYArr[
|
|
740
|
+
: this.getBaseLog(b, w.globals.maxYArr[boundsIndex])
|
|
761
741
|
const number_of_height_levels = max_log_val - min_log_val
|
|
762
742
|
// Values below 1 used to short-circuit to `d / number_of_height_levels`,
|
|
763
743
|
// returning a raw data value where the caller expects a 0..1 fraction. On a
|