apexcharts 8.2.0 → 8.3.1
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 +19793 -19713
- package/dist/apexcharts.core.min.js +2 -2
- package/dist/apexcharts.css +38 -8
- package/dist/apexcharts.esm.js +1882 -1625
- package/dist/apexcharts.full.js +22044 -21634
- package/dist/apexcharts.full.min.js +2 -2
- package/dist/apexcharts.js +21414 -21124
- package/dist/apexcharts.min.js +2 -2
- package/dist/apexcharts.ssr.common.js +2 -2
- package/dist/apexcharts.ssr.esm.js +21413 -21123
- package/dist/area.common.js +2 -2
- package/dist/area.esm.js +91 -40
- package/dist/bar.common.js +2 -2
- package/dist/bar.esm.js +478 -406
- package/dist/bar.js +2 -2
- package/dist/boxPlot.common.js +2 -2
- package/dist/boxPlot.esm.js +409 -334
- package/dist/bubble.common.js +2 -2
- package/dist/bubble.esm.js +91 -40
- package/dist/candlestick.common.js +2 -2
- package/dist/candlestick.esm.js +409 -334
- package/dist/candlestick.js +2 -2
- package/dist/column.common.js +2 -2
- package/dist/column.esm.js +478 -406
- package/dist/core.common.js +2 -2
- package/dist/core.esm.js +19793 -19713
- package/dist/donut.common.js +2 -2
- package/dist/donut.esm.js +3 -9
- package/dist/dumbbell.common.js +2 -2
- package/dist/dumbbell.esm.js +478 -406
- package/dist/features/all.common.js +2 -2
- package/dist/features/all.esm.js +442 -324
- 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 +4 -2
- 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 +10 -4
- 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 +14 -9
- 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 +2 -2
- package/dist/features/keyboard.esm.js +97 -145
- package/dist/features/keyboard.js +2 -2
- package/dist/features/legend.common.js +2 -2
- package/dist/features/legend.esm.js +64 -44
- 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 +9 -5
- 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 +2 -1
- 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 +48 -14
- package/dist/features/streamgraph.js +2 -2
- package/dist/features/toolbar.common.js +2 -2
- package/dist/features/toolbar.esm.js +148 -18
- package/dist/features/toolbar.js +2 -2
- package/dist/features/trellis.common.js +2 -2
- package/dist/features/trellis.esm.js +150 -63
- package/dist/features/trellis.js +2 -2
- package/dist/features/waterfall.common.js +1 -1
- package/dist/features/waterfall.esm.js +1 -1
- package/dist/features/waterfall.js +1 -1
- 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 +1068 -842
- package/dist/heatmap.common.js +2 -2
- package/dist/heatmap.esm.js +3 -17
- package/dist/heatmap.js +2 -2
- package/dist/histogram.common.js +2 -2
- package/dist/histogram.esm.js +529 -464
- package/dist/icicle.common.js +2 -2
- package/dist/icicle.esm.js +80 -46
- package/dist/icicle.js +2 -2
- package/dist/line.common.js +2 -2
- package/dist/line.esm.js +91 -40
- package/dist/line.js +2 -2
- package/dist/locales/en.json +2 -1
- package/dist/locales/ro.json +3 -2
- package/dist/pictograms.common.js +1 -1
- package/dist/pictograms.esm.js +1 -1
- package/dist/pictograms.js +1 -1
- package/dist/pie.common.js +2 -2
- package/dist/pie.esm.js +3 -9
- package/dist/pie.js +2 -2
- package/dist/polarArea.common.js +2 -2
- package/dist/polarArea.esm.js +3 -9
- package/dist/radar.common.js +2 -2
- package/dist/radar.esm.js +5 -4
- package/dist/radar.js +2 -2
- package/dist/radialBar.common.js +2 -2
- package/dist/radialBar.esm.js +5 -12
- package/dist/radialBar.js +2 -2
- package/dist/raincloud.common.js +2 -2
- package/dist/raincloud.esm.js +97 -52
- package/dist/rangeArea.common.js +2 -2
- package/dist/rangeArea.esm.js +91 -40
- package/dist/rangeBar.common.js +2 -2
- package/dist/rangeBar.esm.js +478 -406
- package/dist/scatter.common.js +2 -2
- package/dist/scatter.esm.js +91 -40
- package/dist/streamgraph.common.js +2 -2
- package/dist/streamgraph.esm.js +138 -53
- package/dist/sunburst.common.js +2 -2
- package/dist/sunburst.esm.js +116 -94
- package/dist/sunburst.js +2 -2
- package/dist/treemap.common.js +2 -2
- package/dist/treemap.esm.js +138 -104
- package/dist/treemap.js +2 -2
- package/dist/unit-shapes.common.js +1 -1
- package/dist/unit-shapes.esm.js +1 -1
- package/dist/unit-shapes.js +1 -1
- package/dist/unit.common.js +2 -2
- package/dist/unit.esm.js +280 -202
- package/dist/unit.js +2 -2
- package/dist/violin.common.js +2 -2
- package/dist/violin.esm.js +72 -26
- package/dist/violin.js +2 -2
- package/dist/waterfall.common.js +2 -2
- package/dist/waterfall.esm.js +477 -405
- package/package.json +1 -1
- package/src/apexcharts.js +40 -59
- package/src/assets/apexcharts.css +38 -8
- package/src/charts/Bar.js +62 -55
- package/src/charts/BarStacked.js +80 -88
- package/src/charts/BoxCandleStick.js +28 -31
- package/src/charts/Icicle.js +68 -47
- package/src/charts/Line.js +118 -42
- package/src/charts/Pie.js +2 -8
- package/src/charts/Radar.js +5 -7
- package/src/charts/Radial.js +2 -6
- package/src/charts/RangeBar.js +47 -43
- package/src/charts/Sunburst.js +101 -98
- package/src/charts/Treemap.js +150 -88
- package/src/charts/Unit.js +368 -250
- package/src/charts/Violin.js +48 -30
- package/src/charts/common/Breadcrumb.js +2 -2
- package/src/charts/common/Hierarchy.js +32 -11
- package/src/charts/common/Jitter.js +32 -7
- package/src/charts/common/Stats.js +30 -23
- package/src/charts/common/bar/DataLabels.js +76 -81
- package/src/charts/common/bar/Helpers.js +43 -7
- package/src/charts/common/line/Helpers.js +12 -15
- package/src/charts/common/partition/NodeTooltip.js +29 -7
- package/src/charts/common/partition/Partition.js +33 -1
- package/src/charts/common/treemap/Helpers.js +3 -11
- 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/locales/en.json +2 -1
- package/src/locales/ro.json +3 -2
- package/src/modules/Animations.js +102 -95
- package/src/modules/AxisMapping.js +47 -12
- package/src/modules/Core.js +4 -0
- package/src/modules/CoreUtils.js +18 -42
- package/src/modules/Data.js +23 -24
- package/src/modules/DataLabels.js +6 -6
- package/src/modules/Exports.js +12 -5
- package/src/modules/Fill.js +17 -8
- package/src/modules/Filters.js +50 -50
- package/src/modules/Graphics.js +69 -51
- package/src/modules/Markers.js +3 -1
- package/src/modules/MorphTypeChange.js +13 -7
- package/src/modules/Range.js +44 -29
- package/src/modules/RendererController.js +17 -3
- package/src/modules/Scales.js +32 -9
- package/src/modules/Series.js +41 -19
- package/src/modules/Theme.js +1 -1
- package/src/modules/Toolbar.js +3 -2
- package/src/modules/UnitMarkRegistry.js +0 -5
- package/src/modules/ZoomPanSelection.js +123 -2
- package/src/modules/accessibility/KeyboardNavigation.js +114 -186
- package/src/modules/animations/Easing.js +2 -1
- package/src/modules/animations/LengthTransition.js +22 -2
- package/src/modules/annotations/Helpers.js +68 -52
- package/src/modules/axes/Grid.js +21 -7
- package/src/modules/axes/YAxis.js +8 -9
- 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 +5 -2
- package/src/modules/helpers/Destroy.js +1 -1
- package/src/modules/helpers/UpdateHelpers.js +33 -15
- package/src/modules/highlightFilter/HighlightFilter.js +8 -9
- package/src/modules/highlightFilter/TreemapPart.js +2 -2
- package/src/modules/legend/HeatmapGradientLegend.js +76 -45
- package/src/modules/legend/Helpers.js +8 -1
- package/src/modules/legend/Legend.js +11 -12
- package/src/modules/license/LicenseEnforcer.js +5 -0
- package/src/modules/settings/Defaults.js +28 -56
- package/src/modules/settings/Globals.js +5 -0
- package/src/modules/settings/Options.js +7 -7
- package/src/modules/settings/TypeAliases.js +33 -16
- package/src/modules/streamgraph/StreamLabels.js +1 -0
- package/src/modules/tooltip/Labels.js +73 -76
- package/src/modules/tooltip/Marker.js +25 -21
- package/src/modules/tooltip/Position.js +88 -51
- package/src/modules/tooltip/Tooltip.js +242 -255
- package/src/modules/tooltip/Utils.js +71 -130
- package/src/modules/tooltip/constants.js +5 -5
- package/src/modules/trellis/Trellis.js +6 -0
- package/src/modules/trellis/TrellisChrome.js +18 -7
- package/src/modules/trellis/TrellisSync.js +2 -0
- package/src/modules/trellis/TrellisTooltip.js +2 -11
- package/src/modules/weave/WeaveHost.js +18 -12
- package/src/renderers/canvas/CanvasGraphics.js +1 -0
- package/src/ssr/DOMShim.js +10 -0
- package/src/svg/SVGFilter.js +26 -17
- package/src/types/internal.d.ts +9 -3
- package/src/utils/Utils.js +0 -14
- package/types/apexcharts.d.ts +33 -12
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
import ApexCharts from '../apexcharts'
|
|
50
50
|
import { registerSeriesTransform } from '../modules/SeriesTransformRegistry'
|
|
51
51
|
import {
|
|
52
|
+
deriveStat,
|
|
52
53
|
derivedStats,
|
|
53
54
|
fiveNumberSummary,
|
|
54
55
|
isDerived,
|
|
@@ -107,22 +108,27 @@ function raincloudTransform(ser, w) {
|
|
|
107
108
|
// as before: beside a hand-supplied density the datum keeps its own.
|
|
108
109
|
const out = { ...y }
|
|
109
110
|
if (needDensity) {
|
|
110
|
-
const est =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
const est = deriveStat(
|
|
112
|
+
ourDensity,
|
|
113
|
+
key,
|
|
114
|
+
values,
|
|
115
|
+
{ bandwidth: kde.bandwidth, resolution: kde.resolution },
|
|
116
|
+
kernelDensity,
|
|
117
|
+
)
|
|
114
118
|
// no density, no cloud: leave the datum as it came
|
|
115
119
|
if (!est) return d
|
|
116
120
|
out.density = est.density
|
|
117
121
|
out.points = values
|
|
118
|
-
ourDensity.set(key, est.density)
|
|
119
122
|
}
|
|
120
123
|
if (needSummary) {
|
|
121
|
-
const est =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
const est = deriveStat(
|
|
125
|
+
ourSummary,
|
|
126
|
+
key,
|
|
127
|
+
values,
|
|
128
|
+
{ whiskers },
|
|
129
|
+
fiveNumberSummary,
|
|
130
|
+
)
|
|
131
|
+
if (est) out.summary = est.summary
|
|
126
132
|
}
|
|
127
133
|
touched = true
|
|
128
134
|
return { ...d, y: out }
|
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
|
package/src/locales/en.json
CHANGED
package/src/locales/ro.json
CHANGED
|
@@ -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/Core.js
CHANGED
|
@@ -446,6 +446,10 @@ export default class Core {
|
|
|
446
446
|
const { config: cnf, globals: gl } = w
|
|
447
447
|
const { line, boxCandlestick, violin } = renderers
|
|
448
448
|
|
|
449
|
+
// A unit chart tweens from the slots of the last render; once another type
|
|
450
|
+
// has drawn over them they are not on screen to tween from.
|
|
451
|
+
if (cnf.chart.type !== 'unit') ctx._unitPrevDots = null
|
|
452
|
+
|
|
449
453
|
let elGraph = []
|
|
450
454
|
|
|
451
455
|
if (gl.comboCharts) {
|