apexcharts 7.3.0 → 7.5.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/LICENSE +39 -11
- package/dist/apexcharts.common.js +2 -2
- package/dist/apexcharts.core.js +579 -467
- package/dist/apexcharts.core.min.js +2 -2
- package/dist/apexcharts.esm.js +1347 -810
- package/dist/apexcharts.js +896 -267
- package/dist/apexcharts.min.js +2 -2
- package/dist/apexcharts.ssr.common.js +2 -2
- package/dist/apexcharts.ssr.esm.js +896 -267
- package/dist/area.common.js +1 -1
- package/dist/area.esm.js +1 -1
- package/dist/bar.common.js +2 -2
- package/dist/bar.esm.js +20 -10
- package/dist/bar.js +2 -2
- package/dist/boxPlot.common.js +2 -2
- package/dist/boxPlot.esm.js +20 -10
- package/dist/bubble.common.js +1 -1
- package/dist/bubble.esm.js +1 -1
- package/dist/candlestick.common.js +2 -2
- package/dist/candlestick.esm.js +20 -10
- package/dist/candlestick.js +2 -2
- package/dist/column.common.js +2 -2
- package/dist/column.esm.js +20 -10
- package/dist/core.common.js +2 -2
- package/dist/core.esm.js +579 -467
- package/dist/donut.common.js +1 -1
- package/dist/donut.esm.js +1 -1
- package/dist/dumbbell.common.js +2 -2
- package/dist/dumbbell.esm.js +20 -10
- package/dist/features/all.common.js +2 -2
- package/dist/features/all.esm.js +536 -34
- package/dist/features/annotations.common.js +1 -1
- package/dist/features/annotations.esm.js +1 -1
- package/dist/features/annotations.js +1 -1
- 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 +1 -1
- package/dist/features/drilldown.esm.js +1 -1
- package/dist/features/drilldown.js +1 -1
- 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 +12 -14
- 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/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 +14 -1
- package/dist/features/keyboard.js +2 -2
- package/dist/features/legend.common.js +1 -1
- package/dist/features/legend.esm.js +1 -1
- package/dist/features/legend.js +1 -1
- package/dist/features/link.common.js +1 -1
- package/dist/features/link.esm.js +38 -38
- 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 +1 -1
- package/dist/features/morph.esm.js +1 -1
- package/dist/features/morph.js +1 -1
- package/dist/features/perspectives.common.js +1 -1
- package/dist/features/perspectives.esm.js +11 -11
- package/dist/features/perspectives.js +1 -1
- package/dist/features/raincloud.common.js +1 -1
- package/dist/features/raincloud.esm.js +1 -1
- package/dist/features/raincloud.js +1 -1
- package/dist/features/renderer-canvas.common.js +1 -1
- package/dist/features/renderer-canvas.esm.js +1 -1
- package/dist/features/renderer-canvas.js +1 -1
- package/dist/features/stats.common.js +1 -1
- package/dist/features/stats.esm.js +1 -1
- package/dist/features/stats.js +1 -1
- package/dist/features/storyboard.common.js +1 -1
- package/dist/features/storyboard.esm.js +11 -11
- package/dist/features/storyboard.js +1 -1
- package/dist/features/streamgraph.common.js +1 -1
- package/dist/features/streamgraph.esm.js +1 -1
- package/dist/features/streamgraph.js +1 -1
- package/dist/features/toolbar.common.js +2 -2
- package/dist/features/toolbar.esm.js +172 -25
- package/dist/features/toolbar.js +2 -2
- package/dist/features/trellis.common.js +1 -1
- package/dist/features/trellis.esm.js +1 -1
- package/dist/features/trellis.js +1 -1
- 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 +352 -10
- package/dist/features/weave.js +2 -2
- package/dist/heatmap.common.js +1 -1
- package/dist/heatmap.esm.js +1 -1
- package/dist/heatmap.js +1 -1
- package/dist/histogram.common.js +2 -2
- package/dist/histogram.esm.js +20 -10
- package/dist/line.common.js +1 -1
- package/dist/line.esm.js +1 -1
- package/dist/line.js +1 -1
- 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 +1 -1
- package/dist/pie.esm.js +1 -1
- package/dist/pie.js +1 -1
- package/dist/polarArea.common.js +1 -1
- package/dist/polarArea.esm.js +1 -1
- package/dist/radar.common.js +1 -1
- package/dist/radar.esm.js +1 -1
- package/dist/radar.js +1 -1
- package/dist/radialBar.common.js +2 -2
- package/dist/radialBar.esm.js +27 -2
- package/dist/radialBar.js +2 -2
- package/dist/raincloud.common.js +2 -2
- package/dist/raincloud.esm.js +20 -10
- package/dist/rangeArea.common.js +1 -1
- package/dist/rangeArea.esm.js +1 -1
- package/dist/rangeBar.common.js +2 -2
- package/dist/rangeBar.esm.js +20 -10
- package/dist/scatter.common.js +1 -1
- package/dist/scatter.esm.js +1 -1
- package/dist/streamgraph.common.js +1 -1
- package/dist/streamgraph.esm.js +1 -1
- package/dist/sunburst.common.js +1 -1
- package/dist/sunburst.esm.js +1 -1
- package/dist/sunburst.js +1 -1
- package/dist/treemap.common.js +1 -1
- package/dist/treemap.esm.js +1 -1
- package/dist/treemap.js +1 -1
- 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 +1 -1
- package/dist/unit.esm.js +79 -79
- package/dist/unit.js +1 -1
- package/dist/violin.common.js +2 -2
- package/dist/violin.esm.js +20 -10
- package/dist/violin.js +2 -2
- package/dist/waterfall.common.js +2 -2
- package/dist/waterfall.esm.js +20 -10
- package/package.json +2 -2
- package/src/apexcharts.js +39 -15
- package/src/charts/Radial.js +12 -3
- package/src/charts/common/bar/Helpers.js +31 -12
- package/src/modules/Data.js +8 -2
- package/src/modules/DataLabels.js +14 -4
- package/src/modules/Exports.js +14 -12
- package/src/modules/Formatters.js +24 -1
- package/src/modules/Graphics.js +10 -0
- package/src/modules/Range.js +28 -1
- package/src/modules/Toolbar.js +112 -2
- package/src/modules/ZoomPanSelection.js +85 -7
- package/src/modules/accessibility/KeyboardNavigation.js +14 -0
- package/src/modules/axes/YAxis.js +12 -15
- package/src/modules/helpers/UpdateHelpers.js +25 -8
- package/src/modules/settings/Globals.js +5 -10
- package/src/modules/settings/Options.js +15 -0
- package/src/modules/weave/Claims.js +231 -0
- package/src/modules/weave/Drawn.js +169 -0
- package/src/modules/weave/PluginAPI.js +195 -4
- package/src/modules/weave/WeaveHost.js +76 -3
- package/src/ssr/DOMShim.js +50 -0
- package/src/types/internal.d.ts +1 -1
- package/src/utils/Utils.js +6 -9
- package/types/apexcharts.d.ts +92 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
import { addClaim, normaliseEntries, releaseClaim } from './Claims'
|
|
3
|
+
import { collectDrawn } from './Drawn'
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
6
|
* The frozen facade handed to each Weave plugin. Plugins NEVER receive raw `w`,
|
|
4
7
|
* internal module instances, or the `__apex_*` internals: only this stable,
|
|
@@ -25,12 +28,56 @@
|
|
|
25
28
|
* tooltip and its `dataPoint*` events; before this a plugin either re-derived
|
|
26
29
|
* it from raw pixels or did without.
|
|
27
30
|
*
|
|
31
|
+
* v5 added `api.info.stroke`, the caller's own `stroke.dashArray`. That option
|
|
32
|
+
* is indexed by series position, so a plugin that wants its own derived series
|
|
33
|
+
* dashed must write the whole array; reporting the current value is what lets
|
|
34
|
+
* it put back what it found instead of flattening the caller's dashed lines.
|
|
35
|
+
*
|
|
36
|
+
* v6 also added `api.info.title` (the name the page already gave this chart, so
|
|
37
|
+
* a readout naming several charts has something better than a container id) and
|
|
38
|
+
* `modifiers` on the pointer payload (so a gesture can be shift-click).
|
|
39
|
+
*
|
|
40
|
+
* v6 added three larger pieces, each closing a class rather than one incident.
|
|
41
|
+
* `api.capabilities` / `api.can()` replace the typeof-sniffing below with
|
|
42
|
+
* something a plugin can ask. `api.claim()` generalises what v5 only reported,
|
|
43
|
+
* so a plugin sets a positional option for ITS OWN series and the host resolves
|
|
44
|
+
* it where the option is read, writing nothing. `api.drawn()` / `api.declare()`
|
|
45
|
+
* publish what is on the chart, including other features' output, which is the
|
|
46
|
+
* question a layers panel and an export summary both ask. See
|
|
47
|
+
* `plans/26-weave-capabilities.md`.
|
|
48
|
+
*
|
|
28
49
|
* Feature-detect rather than bumping `apiVersion` unless the plugin genuinely
|
|
29
50
|
* cannot work without the new surface: a plugin declaring v3 is SKIPPED
|
|
30
|
-
* outright on a v2 host, so `apiVersion: 2` plus
|
|
31
|
-
*
|
|
51
|
+
* outright on a v2 host, so `apiVersion: 2` plus a capability check keeps one
|
|
52
|
+
* build working on both.
|
|
32
53
|
*/
|
|
33
|
-
export const WEAVE_API_VERSION =
|
|
54
|
+
export const WEAVE_API_VERSION = 6
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* What this host can do, for plugins that must run against older ones too.
|
|
58
|
+
*
|
|
59
|
+
* The version integer cannot answer this. A plugin declaring a version newer
|
|
60
|
+
* than the host is skipped outright, so a plugin supporting several hosts
|
|
61
|
+
* declares the LOWEST version it can run on and then has to discover anything
|
|
62
|
+
* above that. Until now it did so by sniffing the facade for function members.
|
|
63
|
+
*
|
|
64
|
+
* Named for the capability rather than the version that introduced it, and
|
|
65
|
+
* permanent once published: removing a name is a breaking change on the same
|
|
66
|
+
* terms as removing a member.
|
|
67
|
+
*
|
|
68
|
+
* `scales` is deliberately absent. It is null for non-axis charts, which is a
|
|
69
|
+
* property of the chart rather than of the host, and advertising it here would
|
|
70
|
+
* tell a plugin on a pie chart that projection is available.
|
|
71
|
+
*/
|
|
72
|
+
export const WEAVE_CAPABILITIES = Object.freeze([
|
|
73
|
+
'layer',
|
|
74
|
+
'derived',
|
|
75
|
+
'reserve',
|
|
76
|
+
'pointer',
|
|
77
|
+
'stroke-info',
|
|
78
|
+
'claim',
|
|
79
|
+
'drawn',
|
|
80
|
+
])
|
|
34
81
|
|
|
35
82
|
/**
|
|
36
83
|
* Public chart methods safe to expose to plugins (each bound to ctx). Excludes
|
|
@@ -307,6 +354,31 @@ export function buildPluginAPI(host, record) {
|
|
|
307
354
|
? w.config.dataLabels.enabledOnSeries.slice()
|
|
308
355
|
: null,
|
|
309
356
|
}),
|
|
357
|
+
// The caller's own dashing, reported for the same reason and against
|
|
358
|
+
// the same trap (v5). `stroke.dashArray` is indexed by series position
|
|
359
|
+
// with no per-series escape hatch, so a plugin that wants ITS OWN
|
|
360
|
+
// computed series dashed has to write the whole array, and writing one
|
|
361
|
+
// without knowing what was there discards the caller's dashed lines
|
|
362
|
+
// with nothing to restore them from.
|
|
363
|
+
//
|
|
364
|
+
// A scalar applies to every series and an array is per series. There is
|
|
365
|
+
// no "unset" to report: the option defaults to 0, and 0 already means
|
|
366
|
+
// no dashing, so restoring it restores exactly what was there.
|
|
367
|
+
stroke: Object.freeze({
|
|
368
|
+
dashArray: Array.isArray(w.config.stroke && w.config.stroke.dashArray)
|
|
369
|
+
? w.config.stroke.dashArray.slice()
|
|
370
|
+
: (w.config.stroke && w.config.stroke.dashArray) || 0,
|
|
371
|
+
}),
|
|
372
|
+
// What the chart calls itself, where the caller titled it (v6).
|
|
373
|
+
//
|
|
374
|
+
// For a plugin that has to NAME this chart to somebody: a page-level
|
|
375
|
+
// readout listing several charts otherwise has only the container's id
|
|
376
|
+
// to head each row with, which is a string written for a stylesheet.
|
|
377
|
+
// The title is the name the page already chose and put on screen.
|
|
378
|
+
//
|
|
379
|
+
// Empty string rather than undefined for an untitled chart, so a
|
|
380
|
+
// caller can use it directly in a template; falsy either way.
|
|
381
|
+
title: String((w.config.title && w.config.title.text) || ''),
|
|
310
382
|
})
|
|
311
383
|
},
|
|
312
384
|
|
|
@@ -377,6 +449,88 @@ export function buildPluginAPI(host, record) {
|
|
|
377
449
|
return api
|
|
378
450
|
},
|
|
379
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Set a positional option for your own series, without writing the
|
|
454
|
+
* caller's config.
|
|
455
|
+
*
|
|
456
|
+
* Some options are indexed by series position with no per-series escape
|
|
457
|
+
* hatch, so setting one for a single series has always meant writing the
|
|
458
|
+
* array that covers all of them, then putting the caller's value back. A
|
|
459
|
+
* claim says what this plugin wants instead, and the host answers with it
|
|
460
|
+
* where the option is READ. Nothing is written, so releasing is a deletion
|
|
461
|
+
* rather than a restore, and a caller's own `updateOptions` composes with
|
|
462
|
+
* the claim instead of being reverted by it.
|
|
463
|
+
*
|
|
464
|
+
* const claim = api.claim('stroke.dashArray', [
|
|
465
|
+
* { series: 'Revenue (forecast)', value: 6 },
|
|
466
|
+
* ])
|
|
467
|
+
* claim.release()
|
|
468
|
+
*
|
|
469
|
+
* Name the series rather than its position where you can: a name is
|
|
470
|
+
* resolved each time the option is read, so the claim follows the series
|
|
471
|
+
* through the caller adding, removing or reordering others.
|
|
472
|
+
*
|
|
473
|
+
* Claimable options are an allowlist (see `CLAIMABLE`). An option that is
|
|
474
|
+
* not on it returns null rather than throwing, so a plugin written against
|
|
475
|
+
* a newer host degrades. Every claim is released on teardown, on destroy,
|
|
476
|
+
* and if the host disables this plugin after repeated failures.
|
|
477
|
+
*
|
|
478
|
+
* @param {string} option
|
|
479
|
+
* @param {Array<{series: string|number, value: any}>} entries
|
|
480
|
+
* @returns {{release: () => void, update: (entries: Array<{series: string|number, value: any}>) => void}|null}
|
|
481
|
+
* @since Weave v6
|
|
482
|
+
*/
|
|
483
|
+
claim(option, entries) {
|
|
484
|
+
const claim = addClaim(w, record.def.name, option, entries)
|
|
485
|
+
if (!claim) return null
|
|
486
|
+
return Object.freeze({
|
|
487
|
+
release() {
|
|
488
|
+
releaseClaim(w, claim)
|
|
489
|
+
},
|
|
490
|
+
update(next) {
|
|
491
|
+
claim.entries = normaliseEntries(option, next)
|
|
492
|
+
},
|
|
493
|
+
})
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Everything drawn on this chart, including what other features drew.
|
|
498
|
+
*
|
|
499
|
+
* The chart's series, the caller's annotations (ink strokes among them,
|
|
500
|
+
* since an ink stroke is an annotation), and whatever plugins have
|
|
501
|
+
* declared. Each entry names its `owner`, because the list is only as
|
|
502
|
+
* complete as the features that opted into it: a reader can say what it
|
|
503
|
+
* covers instead of assuming it is everything.
|
|
504
|
+
*
|
|
505
|
+
* Read only. Removing or hiding another feature's output is a much larger
|
|
506
|
+
* promise than this platform makes, and is deliberately not here.
|
|
507
|
+
*
|
|
508
|
+
* Rebuilt per call: it is a projection of live state, and a remembered
|
|
509
|
+
* inventory is a list of what WAS drawn.
|
|
510
|
+
*
|
|
511
|
+
* @returns {ReadonlyArray<{id: string, kind: 'series'|'annotation'|'overlay', label: string, owner: string, visible: boolean}>}
|
|
512
|
+
* @since Weave v6
|
|
513
|
+
*/
|
|
514
|
+
drawn() {
|
|
515
|
+
return Object.freeze(collectDrawn(w, host).map((i) => Object.freeze(i)))
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Say what this plugin has drawn, so it appears in `api.drawn()`.
|
|
520
|
+
*
|
|
521
|
+
* Declare from your draw handler, on the same terms as the drawing itself:
|
|
522
|
+
* declarations are cleared with the layers at the start of every draw, so
|
|
523
|
+
* an inventory cannot outlive what it describes. Declaring the same id
|
|
524
|
+
* twice replaces it rather than adding a second row.
|
|
525
|
+
*
|
|
526
|
+
* @param {{id: string, label?: string, visible?: boolean}} item
|
|
527
|
+
* @since Weave v6
|
|
528
|
+
*/
|
|
529
|
+
declare(item) {
|
|
530
|
+
host._declare(record.def.name, item)
|
|
531
|
+
return api
|
|
532
|
+
},
|
|
533
|
+
|
|
380
534
|
/**
|
|
381
535
|
* Subscribe to the data point a viewer is pointing at.
|
|
382
536
|
*
|
|
@@ -400,7 +554,12 @@ export function buildPluginAPI(host, record) {
|
|
|
400
554
|
* and a handler that throws is contained rather than allowed to break the
|
|
401
555
|
* interaction it was watching.
|
|
402
556
|
*
|
|
403
|
-
*
|
|
557
|
+
* `modifiers` (v6) reports the keys held during the interaction, for the
|
|
558
|
+
* gestures that need them: shift-click to add to a selection is the one
|
|
559
|
+
* page-level coordination wants. All four are false when the interaction
|
|
560
|
+
* came from somewhere with no DOM event, such as the keyboard.
|
|
561
|
+
*
|
|
562
|
+
* @param {(e: {type: 'enter'|'leave'|'select', seriesIndex: number, dataPointIndex: number, category: string|undefined, seriesName: string|undefined, selected: boolean|undefined, modifiers: {shift: boolean, ctrl: boolean, alt: boolean, meta: boolean}}) => void} fn
|
|
404
563
|
* @returns {() => void} unsubscribe
|
|
405
564
|
* @since Weave v4
|
|
406
565
|
*/
|
|
@@ -428,5 +587,37 @@ export function buildPluginAPI(host, record) {
|
|
|
428
587
|
},
|
|
429
588
|
}
|
|
430
589
|
|
|
590
|
+
// Probed off the facade that was actually built rather than copied from the
|
|
591
|
+
// constant, so a member that is ever made conditional drops out instead of
|
|
592
|
+
// being advertised and then missing.
|
|
593
|
+
//
|
|
594
|
+
// An ARRAY rather than a Set, because a frozen Set is not actually read-only:
|
|
595
|
+
// Object.freeze does not touch internal slots, so `add()` and `delete()` keep
|
|
596
|
+
// working and one plugin could edit what every later one is told. The Set
|
|
597
|
+
// stays in the closure and `can()` is the lookup.
|
|
598
|
+
const probes = /** @type {Record<string, (a: any) => boolean>} */ (WIRED)
|
|
599
|
+
const granted = WEAVE_CAPABILITIES.filter((name) => probes[name](api))
|
|
600
|
+
const grantedSet = new Set(granted)
|
|
601
|
+
const extras = /** @type {any} */ (api)
|
|
602
|
+
extras.capabilities = Object.freeze(granted)
|
|
603
|
+
/** Whether this host supports a named capability. @since Weave v6 */
|
|
604
|
+
extras.can = (/** @type {string} */ name) => grantedSet.has(name)
|
|
605
|
+
|
|
431
606
|
return Object.freeze(api)
|
|
432
607
|
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* How each capability name is confirmed present. One entry per member of
|
|
611
|
+
* {@link WEAVE_CAPABILITIES}; a name with no probe would always be advertised,
|
|
612
|
+
* which is the failure this table exists to prevent.
|
|
613
|
+
*/
|
|
614
|
+
const WIRED = {
|
|
615
|
+
layer: (/** @type {any} */ a) => typeof a.layer === 'function',
|
|
616
|
+
derived: (/** @type {any} */ a) => typeof a.markDerived === 'function',
|
|
617
|
+
reserve: (/** @type {any} */ a) => typeof a.reserve === 'function',
|
|
618
|
+
pointer: (/** @type {any} */ a) => typeof a.pointer === 'function',
|
|
619
|
+
'stroke-info': (/** @type {any} */ a) => !!(a.info && a.info.stroke),
|
|
620
|
+
claim: (/** @type {any} */ a) => typeof a.claim === 'function',
|
|
621
|
+
drawn: (/** @type {any} */ a) =>
|
|
622
|
+
typeof a.drawn === 'function' && typeof a.declare === 'function',
|
|
623
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { getPlugin } from './PluginRegistry'
|
|
3
3
|
import { buildPluginAPI, makeLayerHandle, WEAVE_API_VERSION } from './PluginAPI'
|
|
4
|
+
import { releaseOwner } from './Claims'
|
|
4
5
|
|
|
5
6
|
export { WEAVE_API_VERSION }
|
|
6
7
|
|
|
@@ -52,6 +53,8 @@ export default class WeaveHost {
|
|
|
52
53
|
this._reserveTimer = null
|
|
53
54
|
/** @type {Map<string, Function[]>|null} plugin name -> pointer handlers */
|
|
54
55
|
this._pointerSubs = null
|
|
56
|
+
/** @type {Map<string, any[]>|null} plugin name -> what it says it drew */
|
|
57
|
+
this._declared = null
|
|
55
58
|
/** @type {Array<[string, Function]>|null} chart listeners to remove on teardown */
|
|
56
59
|
this._pointerWired = null
|
|
57
60
|
|
|
@@ -185,6 +188,11 @@ export default class WeaveHost {
|
|
|
185
188
|
record.failures = (record.failures || 0) + 1
|
|
186
189
|
if (record.failures >= 3) {
|
|
187
190
|
record.disabled = true
|
|
191
|
+
// Its claims go with it. A disabled plugin has stopped running, so a
|
|
192
|
+
// claim it left behind would go on answering for an option nobody is
|
|
193
|
+
// maintaining, which is the permanent-leak case claims exist to rule
|
|
194
|
+
// out (see weave/Claims).
|
|
195
|
+
releaseOwner(this.w, record.def.name)
|
|
188
196
|
console.error(
|
|
189
197
|
`[apexcharts] plugin "${record.def.name}" disabled after repeated errors.`,
|
|
190
198
|
)
|
|
@@ -431,8 +439,11 @@ export default class WeaveHost {
|
|
|
431
439
|
]
|
|
432
440
|
this._pointerWired = []
|
|
433
441
|
for (const [type, name] of map) {
|
|
434
|
-
|
|
435
|
-
|
|
442
|
+
// The DOM event is carried through rather than dropped: it is the only
|
|
443
|
+
// place the modifier keys exist, and a gesture like shift-click to add to
|
|
444
|
+
// a selection cannot be expressed without them. See `_emitPointer`.
|
|
445
|
+
const handler = (/** @type {any} */ e, /** @type {any} */ _ctx, /** @type {any} */ opts) => {
|
|
446
|
+
this._emitPointer(type, opts, e)
|
|
436
447
|
}
|
|
437
448
|
this.ctx.addEventListener(name, handler)
|
|
438
449
|
this._pointerWired.push([name, handler])
|
|
@@ -449,8 +460,9 @@ export default class WeaveHost {
|
|
|
449
460
|
*
|
|
450
461
|
* @param {'enter'|'leave'|'select'} type
|
|
451
462
|
* @param {any} opts
|
|
463
|
+
* @param {any} [e] the DOM event, where the interaction came from one
|
|
452
464
|
*/
|
|
453
|
-
_emitPointer(type, opts) {
|
|
465
|
+
_emitPointer(type, opts, e) {
|
|
454
466
|
if (!this._pointerSubs || !this._pointerSubs.size) return
|
|
455
467
|
const seriesIndex = opts && typeof opts.seriesIndex === 'number' ? opts.seriesIndex : -1
|
|
456
468
|
const dataPointIndex =
|
|
@@ -475,6 +487,14 @@ export default class WeaveHost {
|
|
|
475
487
|
// set, and what a plugin wants to know is whether THIS point is now in
|
|
476
488
|
// it, so a second click reads as a deselect rather than another select.
|
|
477
489
|
selected: type === 'select' ? WeaveHost._isSelected(opts, seriesIndex, dataPointIndex) : undefined,
|
|
490
|
+
// The modifier keys held during the interaction (v6), for the gestures
|
|
491
|
+
// that need them: shift-click to add to a selection is the one page mode
|
|
492
|
+
// wants, and a plugin cannot invent it from anything else here.
|
|
493
|
+
//
|
|
494
|
+
// All false when the interaction came from somewhere with no DOM event
|
|
495
|
+
// (the keyboard, a programmatic selection), which is the honest answer:
|
|
496
|
+
// no key was held.
|
|
497
|
+
modifiers: WeaveHost._modifiers(e),
|
|
478
498
|
}
|
|
479
499
|
for (const [name, handlers] of this._pointerSubs) {
|
|
480
500
|
for (const fn of handlers.slice()) {
|
|
@@ -526,6 +546,24 @@ export default class WeaveHost {
|
|
|
526
546
|
return mine.indexOf(dataPointIndex) > -1
|
|
527
547
|
}
|
|
528
548
|
|
|
549
|
+
/**
|
|
550
|
+
* Which modifier keys were held, read off the DOM event.
|
|
551
|
+
*
|
|
552
|
+
* Always the same four booleans, never undefined and never a partial object:
|
|
553
|
+
* a plugin writes `if (e.modifiers.shift)` without a guard, and a shape that
|
|
554
|
+
* sometimes lacks a key is how that becomes a crash inside a viewer's click.
|
|
555
|
+
*
|
|
556
|
+
* @param {any} e
|
|
557
|
+
*/
|
|
558
|
+
static _modifiers(e) {
|
|
559
|
+
return Object.freeze({
|
|
560
|
+
shift: !!(e && e.shiftKey),
|
|
561
|
+
ctrl: !!(e && e.ctrlKey),
|
|
562
|
+
alt: !!(e && e.altKey),
|
|
563
|
+
meta: !!(e && e.metaKey),
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
|
|
529
567
|
/**
|
|
530
568
|
* Record a plugin's container reservation and re-render if it changed.
|
|
531
569
|
*
|
|
@@ -730,6 +768,39 @@ export default class WeaveHost {
|
|
|
730
768
|
Array.prototype.forEach.call(groups, (/** @type {any} */ n) => n.remove())
|
|
731
769
|
}
|
|
732
770
|
this._layers.clear()
|
|
771
|
+
// Declarations go with the drawing they describe. A plugin repaints its
|
|
772
|
+
// overlays from state on every draw, and it declares them the same way, so
|
|
773
|
+
// an inventory can never outlive what it is an inventory OF.
|
|
774
|
+
this._declared = null
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Record one thing a plugin has drawn, for `api.drawn()`.
|
|
779
|
+
*
|
|
780
|
+
* Replaced by id rather than appended, so a plugin declaring the same overlay
|
|
781
|
+
* on every draw (which is the pattern this expects) produces one entry.
|
|
782
|
+
*
|
|
783
|
+
* @param {string} name plugin
|
|
784
|
+
* @param {{id: string, label?: string, visible?: boolean}} item
|
|
785
|
+
*/
|
|
786
|
+
_declare(name, item) {
|
|
787
|
+
if (!item || typeof item.id !== 'string' || !item.id) {
|
|
788
|
+
console.warn(
|
|
789
|
+
`[apexcharts] plugin "${name}" declared something with no id; ignored.`,
|
|
790
|
+
)
|
|
791
|
+
return
|
|
792
|
+
}
|
|
793
|
+
if (!this._declared) this._declared = new Map()
|
|
794
|
+
const mine = this._declared.get(name) || []
|
|
795
|
+
const entry = {
|
|
796
|
+
id: item.id,
|
|
797
|
+
label: item.label ? String(item.label) : item.id,
|
|
798
|
+
visible: item.visible !== false,
|
|
799
|
+
}
|
|
800
|
+
const at = mine.findIndex((/** @type {any} */ d) => d.id === entry.id)
|
|
801
|
+
if (at > -1) mine[at] = entry
|
|
802
|
+
else mine.push(entry)
|
|
803
|
+
this._declared.set(name, mine)
|
|
733
804
|
}
|
|
734
805
|
|
|
735
806
|
// ─── Config-change reconciliation ───────────────────────────────────────
|
|
@@ -795,10 +866,12 @@ export default class WeaveHost {
|
|
|
795
866
|
for (const record of this.active) {
|
|
796
867
|
this._guard(record, 'destroy', () => record.def.destroy && record.def.destroy(record.api))
|
|
797
868
|
}
|
|
869
|
+
for (const record of this.active) releaseOwner(this.w, record.def.name)
|
|
798
870
|
this.active = []
|
|
799
871
|
this._derived = null
|
|
800
872
|
this._reserved = null
|
|
801
873
|
this._pointerSubs = null
|
|
874
|
+
this._declared = null
|
|
802
875
|
if (this._pointerWired) {
|
|
803
876
|
for (const [name, handler] of this._pointerWired) {
|
|
804
877
|
this.ctx.removeEventListener && this.ctx.removeEventListener(name, handler)
|
package/src/ssr/DOMShim.js
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
* Provides just enough SVG element emulation to create chart structure without full DOM
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
// Approximate sans-serif metrics, in em, used to estimate SVG text bounds when
|
|
8
|
+
// no font engine is available to measure the glyphs.
|
|
9
|
+
const CHAR_WIDTH_EM = 0.55
|
|
10
|
+
const ASCENT_EM = 0.917
|
|
11
|
+
const DESCENT_EM = 0.25
|
|
12
|
+
const LINE_HEIGHT_EM = 1.1
|
|
13
|
+
const DEFAULT_FONT_SIZE = 11
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* Mock SVG element for SSR environment
|
|
9
17
|
*/
|
|
@@ -148,6 +156,48 @@ class SSRElement {
|
|
|
148
156
|
}
|
|
149
157
|
}
|
|
150
158
|
|
|
159
|
+
getBBox() {
|
|
160
|
+
if (this.nodeName !== 'text' && this.nodeName !== 'tspan') {
|
|
161
|
+
return { x: 0, y: 0, width: 0, height: 0 }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const lines = this._textLines()
|
|
165
|
+
const longest = lines.reduce((acc, line) => Math.max(acc, line.length), 0)
|
|
166
|
+
if (!longest) {
|
|
167
|
+
return { x: 0, y: 0, width: 0, height: 0 }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const fontSize =
|
|
171
|
+
parseFloat(this.attributes.get('font-size')) || DEFAULT_FONT_SIZE
|
|
172
|
+
const width = longest * fontSize * CHAR_WIDTH_EM
|
|
173
|
+
const height =
|
|
174
|
+
fontSize * (ASCENT_EM + DESCENT_EM) +
|
|
175
|
+
(lines.length - 1) * fontSize * LINE_HEIGHT_EM
|
|
176
|
+
|
|
177
|
+
const anchor = this.attributes.get('text-anchor')
|
|
178
|
+
const x = parseFloat(this.attributes.get('x')) || 0
|
|
179
|
+
const y = parseFloat(this.attributes.get('y')) || 0
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
x: anchor === 'middle' ? x - width / 2 : anchor === 'end' ? x - width : x,
|
|
183
|
+
y: y - fontSize * ASCENT_EM,
|
|
184
|
+
width,
|
|
185
|
+
height,
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Text of this element, one entry per rendered line
|
|
191
|
+
* @returns {string[]}
|
|
192
|
+
*/
|
|
193
|
+
_textLines() {
|
|
194
|
+
const tspans = this.children.filter((child) => child.nodeName === 'tspan')
|
|
195
|
+
if (tspans.length) {
|
|
196
|
+
return tspans.map((tspan) => String(tspan.textContent ?? ''))
|
|
197
|
+
}
|
|
198
|
+
return [String(this.textContent ?? '')]
|
|
199
|
+
}
|
|
200
|
+
|
|
151
201
|
getRootNode() {
|
|
152
202
|
/** @type {SSRElement} */
|
|
153
203
|
let root = this
|
package/src/types/internal.d.ts
CHANGED
|
@@ -802,7 +802,7 @@ export interface ChartContext {
|
|
|
802
802
|
eventList: string[]
|
|
803
803
|
|
|
804
804
|
// Public methods on the ApexCharts instance
|
|
805
|
-
update(options?: any): Promise<any>
|
|
805
|
+
update(options?: any, overwriteInitialSeries?: boolean): Promise<any>
|
|
806
806
|
getSyncedCharts(): any[]
|
|
807
807
|
getGroupedCharts(): any[]
|
|
808
808
|
fastUpdate(animate?: boolean, prevAxisScaleSig?: string): Promise<any>
|
package/src/utils/Utils.js
CHANGED
|
@@ -75,15 +75,12 @@ class Utils {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// A per-series shallow copy: the series OBJECTS are copied, their data arrays
|
|
78
|
-
// are shared.
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
// this way because the series object was copied at capture time.
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
// note above defineLazyInitialSeries(). This is the same cheap shape
|
|
85
|
-
// `globals.initialSeries` captures, so snapshotting a config stays O(n)
|
|
86
|
-
// instead of deep-cloning every point.
|
|
78
|
+
// are shared. Every internal "mutation" of a series' data is a property
|
|
79
|
+
// REPLACEMENT (`series[i].data = []` on legend collapse, `series[i] = 0` for
|
|
80
|
+
// non-axis charts, appendData's concat), and those cannot reach a copy made
|
|
81
|
+
// this way because the series object was copied at capture time. This is the
|
|
82
|
+
// same cheap shape `globals.initialSeries` captures, so snapshotting a config
|
|
83
|
+
// stays O(n) instead of deep-cloning every point.
|
|
87
84
|
/**
|
|
88
85
|
* @param {any} series
|
|
89
86
|
*/
|
package/types/apexcharts.d.ts
CHANGED
|
@@ -850,6 +850,81 @@ interface ApexPluginAPI {
|
|
|
850
850
|
*/
|
|
851
851
|
emit(name: string, detail?: any): void
|
|
852
852
|
readonly el: Element
|
|
853
|
+
/**
|
|
854
|
+
* What this host supports, for a plugin that has to run against older ones
|
|
855
|
+
* too. A plugin targeting several hosts declares the lowest `apiVersion` it
|
|
856
|
+
* can run on (a newer one is skipped outright) and asks this for the rest.
|
|
857
|
+
*
|
|
858
|
+
* @since Weave v6
|
|
859
|
+
*/
|
|
860
|
+
can(name: string): boolean
|
|
861
|
+
/** The same list, for logging and support. Frozen. @since Weave v6 */
|
|
862
|
+
readonly capabilities: readonly string[]
|
|
863
|
+
/**
|
|
864
|
+
* Set a positional option for your own series without writing the caller's
|
|
865
|
+
* config.
|
|
866
|
+
*
|
|
867
|
+
* Options like `stroke.dashArray` are indexed by series position with no
|
|
868
|
+
* per-series alternative, so setting one for a single series has meant
|
|
869
|
+
* writing the whole array and restoring the caller's afterwards. A claim is
|
|
870
|
+
* resolved where the option is READ instead: nothing is written, releasing is
|
|
871
|
+
* a deletion rather than a restore, and a caller's own `updateOptions`
|
|
872
|
+
* composes with the claim instead of being reverted by it.
|
|
873
|
+
*
|
|
874
|
+
* Name the series rather than its position where you can: the name is
|
|
875
|
+
* resolved each time the option is read, so the claim follows that series
|
|
876
|
+
* when others are added, removed or reordered.
|
|
877
|
+
*
|
|
878
|
+
* Returns null for an option that is not claimable, so a plugin written
|
|
879
|
+
* against a newer host degrades instead of throwing. Every claim is released
|
|
880
|
+
* on teardown, on destroy, and if the host disables the plugin.
|
|
881
|
+
*
|
|
882
|
+
* @since Weave v6
|
|
883
|
+
*/
|
|
884
|
+
claim(
|
|
885
|
+
option: 'stroke.dashArray' | 'dataLabels.enabledOnSeries' | (string & {}),
|
|
886
|
+
entries: Array<{ series: string | number; value: any }>
|
|
887
|
+
): ApexPluginClaim | null
|
|
888
|
+
/**
|
|
889
|
+
* Everything drawn on this chart, including other features' output: the
|
|
890
|
+
* series, the caller's annotations (ink strokes among them), and whatever
|
|
891
|
+
* plugins have declared.
|
|
892
|
+
*
|
|
893
|
+
* Read only. Every entry names its `owner`, because the list is only as
|
|
894
|
+
* complete as the features that opted in, and a reader should be able to say
|
|
895
|
+
* what it covers rather than assume it is exhaustive.
|
|
896
|
+
*
|
|
897
|
+
* @since Weave v6
|
|
898
|
+
*/
|
|
899
|
+
drawn(): ReadonlyArray<ApexDrawnItem>
|
|
900
|
+
/**
|
|
901
|
+
* Say what this plugin has drawn, so it appears in `drawn()`. Declare from
|
|
902
|
+
* your draw handler: declarations are cleared with the layers at the start of
|
|
903
|
+
* every draw, so an inventory cannot outlive what it describes.
|
|
904
|
+
*
|
|
905
|
+
* @since Weave v6
|
|
906
|
+
*/
|
|
907
|
+
declare(item: { id: string; label?: string; visible?: boolean }): ApexPluginAPI
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/** One thing drawn on a chart. @since Weave v6 */
|
|
911
|
+
interface ApexDrawnItem {
|
|
912
|
+
/** Stable within this chart, opaque to readers. */
|
|
913
|
+
readonly id: string
|
|
914
|
+
readonly kind: 'series' | 'annotation' | 'overlay'
|
|
915
|
+
/** A human name where one exists. */
|
|
916
|
+
readonly label: string
|
|
917
|
+
/** 'core', or the plugin that put it there. */
|
|
918
|
+
readonly owner: string
|
|
919
|
+
readonly visible: boolean
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/** A live claim over one positional option. @since Weave v6 */
|
|
923
|
+
interface ApexPluginClaim {
|
|
924
|
+
/** Drop the claim. Idempotent. */
|
|
925
|
+
release(): void
|
|
926
|
+
/** Replace this claim's entries, keeping its place in the resolution order. */
|
|
927
|
+
update(entries: Array<{ series: string | number; value: any }>): void
|
|
853
928
|
}
|
|
854
929
|
|
|
855
930
|
interface ApexPlugin {
|
|
@@ -1878,6 +1953,17 @@ type ApexChart = {
|
|
|
1878
1953
|
* @default 'auto'
|
|
1879
1954
|
*/
|
|
1880
1955
|
pinch?: boolean | 'auto'
|
|
1956
|
+
/**
|
|
1957
|
+
* The way back out of a zoom on a chart whose toolbar is hidden. While the
|
|
1958
|
+
* chart is zoomed and nothing else on screen can reset it, one reset
|
|
1959
|
+
* control is drawn where the toolbar would have been, and it goes when the
|
|
1960
|
+
* range does; `Escape` resets the zoom as well. `'auto'` supplies both only
|
|
1961
|
+
* where there is no reset button already, `true` also forces the control on
|
|
1962
|
+
* where `toolbar.tools.reset` is off, and `false` turns both off for a page
|
|
1963
|
+
* that supplies its own reset. Requires `enabled: true`.
|
|
1964
|
+
* @default 'auto'
|
|
1965
|
+
*/
|
|
1966
|
+
resetControl?: boolean | 'auto'
|
|
1881
1967
|
zoomedArea?: {
|
|
1882
1968
|
fill?: {
|
|
1883
1969
|
color?: string
|
|
@@ -2656,6 +2742,12 @@ type ApexPlotOptions = {
|
|
|
2656
2742
|
distributed?: boolean
|
|
2657
2743
|
borderRadius?: number;
|
|
2658
2744
|
borderRadiusApplication?: 'around' | 'end';
|
|
2745
|
+
/**
|
|
2746
|
+
* Which segments of a stack round. 'all' (default) caps both ends of the
|
|
2747
|
+
* stack, the baseline and the far end; 'last' caps only the far end so
|
|
2748
|
+
* the stack sits square on the baseline. Stacked bar/column only.
|
|
2749
|
+
*/
|
|
2750
|
+
borderRadiusWhenStacked?: 'all' | 'last';
|
|
2659
2751
|
hideZeroBarsWhenGrouped?: boolean
|
|
2660
2752
|
rangeBarOverlap?: boolean
|
|
2661
2753
|
rangeBarGroupRows?: boolean
|