vue-echarts 8.2.0 → 8.3.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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { a as hasZeroDimension, c as isOn, d as parseOnEvent, f as warn$1, i as hasEventHandler, l as isPlainObject, n as useRuntime, o as isBrowser, r as createEventInvoker, s as isIgnorableWatchChange, u as isValidArrayIndex } from "./runtime-BSiQKM1W.js";
1
+ import { a as hasEventHandler, c as isIgnorableWatchChange, d as isValidArrayIndex, f as parseOnEvent, i as createEventInvoker, l as isOn, o as hasZeroDimension, p as warn$1, r as useRuntime, s as isBrowser, t as planUpdate, u as isPlainObject } from "./update-CWPvYl2M.js";
2
2
  import { Teleport, computed, defineComponent, getCurrentInstance, h, inject, nextTick, onBeforeUnmount, onMounted, onScopeDispose, onUpdated, shallowReactive, shallowRef, toRef, toValue, watch, watchSyncEffect } from "vue";
3
- import { ComponentModel, init, throttle } from "echarts/core";
3
+ import { init, throttle } from "echarts/core";
4
4
  //#region src/composables/api.ts
5
5
  const METHOD_NAMES = [
6
6
  "getWidth",
@@ -189,12 +189,12 @@ function useSlotOption(slots, onSlotsChange) {
189
189
  collectSlotNames(true);
190
190
  let slotNames = [];
191
191
  let nextSlotNames = slotNames;
192
- let patchedSlotNames = slotNames;
193
- const hasNewSlots = () => collectSlotNames().some((name) => !slotNames.includes(name));
192
+ const patchedSlotNames = /* @__PURE__ */ new Set();
193
+ const callbacks = /* @__PURE__ */ new Map();
194
194
  function setReady(value) {
195
195
  ready.value = value;
196
196
  if (value) return;
197
- patchedSlotNames = [];
197
+ patchedSlotNames.clear();
198
198
  for (const key of Object.keys(params)) delete params[key];
199
199
  }
200
200
  function syncSlotNames(names) {
@@ -202,6 +202,7 @@ function useSlotOption(slots, onSlotsChange) {
202
202
  for (const key of slotNames) if (!names.includes(key)) {
203
203
  delete params[key];
204
204
  delete containers[key];
205
+ callbacks.delete(key);
205
206
  }
206
207
  slotNames = names;
207
208
  return true;
@@ -224,7 +225,7 @@ function useSlotOption(slots, onSlotsChange) {
224
225
  }, slotContent);
225
226
  }));
226
227
  };
227
- function patchOption(src) {
228
+ function prepare(src) {
228
229
  const names = collectSlotNames();
229
230
  syncSlotNames(names);
230
231
  let root;
@@ -232,24 +233,32 @@ function useSlotOption(slots, onSlotsChange) {
232
233
  root ??= { ...src };
233
234
  writePath(root, getSlotPath(key), null, true);
234
235
  }
235
- if (names.length === 0) {
236
- patchedSlotNames = [];
237
- return root ?? src;
238
- }
239
- root ??= { ...src };
236
+ if (names.length) root ??= { ...src };
240
237
  const patchedNames = [];
241
238
  for (const key of names) {
242
- const formatter = (payload) => {
243
- if (!slots[key]) return;
244
- if (key in params && Object.is(params[key], payload)) delete params[key];
245
- params[key] = payload;
246
- return containers[key];
247
- };
248
- if (!writePath(root, getSlotPath(key), formatter)) continue;
239
+ let callback = callbacks.get(key);
240
+ if (!callback) {
241
+ const formatter = (payload) => {
242
+ if (!slots[key]) return;
243
+ if (key in params && Object.is(params[key], payload)) delete params[key];
244
+ params[key] = payload;
245
+ return containers[key];
246
+ };
247
+ callback = {
248
+ path: getSlotPath(key),
249
+ formatter
250
+ };
251
+ callbacks.set(key, callback);
252
+ }
253
+ if (!writePath(root, callback.path, callback.formatter)) continue;
249
254
  patchedNames.push(key);
250
255
  }
251
- patchedSlotNames = patchedNames;
252
- return root;
256
+ return {
257
+ option: root ?? src,
258
+ commit: () => {
259
+ patchedNames.forEach((name) => patchedSlotNames.add(name));
260
+ }
261
+ };
253
262
  }
254
263
  onUpdated(() => {
255
264
  if (syncSlotNames(nextSlotNames)) onSlotsChange();
@@ -260,9 +269,11 @@ function useSlotOption(slots, onSlotsChange) {
260
269
  });
261
270
  return {
262
271
  render,
263
- hasNewSlots,
264
- patchOption,
265
- setReady
272
+ prepare,
273
+ setReady,
274
+ cancelPendingUpdate: () => {
275
+ syncSlotNames(collectSlotNames());
276
+ }
266
277
  };
267
278
  }
268
279
  //#endregion
@@ -303,7 +314,7 @@ function useReactiveChartListeners(chart, attrs) {
303
314
  for (const binding of bindings.values()) binding.emitter.off(binding.event, binding.handler);
304
315
  bindings.clear();
305
316
  }
306
- const stopWatch = watchSyncEffect(() => {
317
+ function sync() {
307
318
  seen.clear();
308
319
  const instance = chart.value;
309
320
  for (const [key, source] of consumedSources) if (attrs[key] !== source) consumedSources.delete(key);
@@ -354,205 +365,30 @@ function useReactiveChartListeners(chart, attrs) {
354
365
  binding.emitter.off(binding.event, binding.handler);
355
366
  bindings.delete(key);
356
367
  }
357
- });
368
+ }
369
+ const stopWatch = watchSyncEffect(sync);
370
+ if (getCurrentInstance()) onUpdated(sync);
358
371
  const stop = () => {
359
372
  stopWatch();
360
373
  clearBindings();
361
374
  };
362
375
  onScopeDispose(stop);
363
- return stop;
364
- }
365
- function useRootAttrs(attrs) {
366
- return computed(() => {
367
- const result = {};
368
- for (const key in attrs) {
369
- if (key.startsWith(NATIVE_EVENT_PREFIX)) {
370
- const event = key.slice(9);
371
- if (event) result[`on:${event}`] = attrs[key];
372
- continue;
373
- }
374
- if (!isOn(key)) result[key] = attrs[key];
375
- }
376
- return result;
377
- });
378
- }
379
- //#endregion
380
- //#region src/update.ts
381
- function toIdentity(value) {
382
- return typeof value === "string" || typeof value === "number" ? String(value) : void 0;
383
- }
384
- function buildShape(value, context, mode) {
385
- if (!isPlainObject(value)) return true;
386
- const shape = Object.create(null);
387
- for (const key of Object.keys(value)) {
388
- const child = value[key];
389
- if (child === void 0) continue;
390
- if (mode === "graphic" && key === "$action") context.hasAction = true;
391
- if (mode === "graphic" && (key === "elements" || key === "children") && Array.isArray(child)) {
392
- shape[key] = analyzeItems(child, context, "graphic", true);
393
- continue;
394
- }
395
- if (mode === "option") {
396
- const componentItems = ComponentModel.hasClass(key);
397
- if (Array.isArray(child) || componentItems && isPlainObject(child)) {
398
- shape[key] = analyzeItems(Array.isArray(child) ? child : [child], context, key === "graphic" ? "graphic" : void 0, componentItems);
399
- continue;
400
- }
401
- }
402
- shape[key] = mode === "media" && key === "option" ? buildShape(child, context, "option") : buildShape(child, context);
403
- }
404
- return shape;
405
- }
406
- function analyzeItems(items, context, mode, componentItems) {
407
- const shapes = [];
408
- for (const item of items) {
409
- const identity = componentItems ? item : void 0;
410
- shapes.push({
411
- id: toIdentity(identity?.id),
412
- name: toIdentity(identity?.name),
413
- shape: buildShape(item, context, mode)
414
- });
415
- }
416
- return shapes;
417
- }
418
- /**
419
- * Build a structural signature that retains component identities but not option payload values.
420
- * Data arrays inside component items remain leaves. Graphic element trees and nested option units
421
- * (`baseOption`, timeline options, and media options) reuse collection summaries.
422
- */
423
- function buildSignature(option) {
424
- const opt = option;
425
- const context = { hasAction: false };
426
- const collections = Object.create(null);
427
- const objectShapes = Object.create(null);
428
- const leaves = [];
429
- for (const key of Object.keys(opt)) {
430
- const value = opt[key];
431
- const componentItems = ComponentModel.hasClass(key);
432
- if (Array.isArray(value) || componentItems && isPlainObject(value)) {
433
- const mode = key === "options" ? "option" : key === "media" ? "media" : key === "graphic" ? "graphic" : void 0;
434
- collections[key] = analyzeItems(Array.isArray(value) ? value : [value], context, mode, componentItems);
435
- continue;
436
- }
437
- if (isPlainObject(value)) {
438
- objectShapes[key] = buildShape(value, context, key === "baseOption" ? "option" : void 0);
439
- continue;
440
- }
441
- if (value !== void 0 && !componentItems) leaves.push(key);
442
- }
443
376
  return {
444
- collections,
445
- objectShapes,
446
- leaves,
447
- hasAction: context.hasAction
377
+ sync,
378
+ stop
448
379
  };
449
380
  }
450
- function hasCollectionRemoval(prev, next) {
451
- if (!next) return prev.length > 0;
452
- return next.length < prev.length;
453
- }
454
- function getItemIdentity(item) {
455
- return item.id !== void 0 ? `id:${item.id}` : item.name !== void 0 ? `name:${item.name}` : void 0;
456
- }
457
- function hasIdentityChange(prev, next) {
458
- const length = Math.min(prev.length, next.length);
459
- for (let index = 0; index < length; index++) {
460
- const previous = getItemIdentity(prev[index]);
461
- const current = getItemIdentity(next[index]);
462
- if (previous !== current && (previous !== void 0 || current !== void 0)) return true;
463
- }
464
- return false;
465
- }
466
- function preservesReplacementOrder(prev, next) {
467
- const positions = /* @__PURE__ */ new Map();
468
- for (let index = 0; index < prev.length; index++) {
469
- const item = prev[index];
470
- if (item.id !== void 0) positions.set(item.id, index);
471
- }
472
- return next.every((item, index) => {
473
- const previousIndex = item.id === void 0 ? void 0 : positions.get(item.id);
474
- return previousIndex === void 0 || previousIndex === index;
475
- });
476
- }
477
- function hasShapeRemoval(prev, next) {
478
- if (prev === true || next === true) return false;
479
- const prevIsCollection = Array.isArray(prev);
480
- const nextIsCollection = Array.isArray(next);
481
- if (prevIsCollection || nextIsCollection) return !prevIsCollection || !nextIsCollection || hasCollectionRemoval(prev, next) || hasIdentityChange(prev, next) || findItemShapeRemoval(prev, next) !== void 0;
482
- for (const key in prev) {
483
- const nextChild = next[key];
484
- if (nextChild === void 0 || hasShapeRemoval(prev[key], nextChild)) return true;
485
- }
486
- return false;
487
- }
488
- function findItemShapeRemoval(prev, next) {
489
- let anonymousRemoval;
490
- for (let index = 0; index < prev.length; index++) {
491
- const item = prev[index];
492
- let nextShape;
493
- if (item.id !== void 0) nextShape = next.find((candidate) => candidate.id === item.id)?.shape;
494
- else nextShape = next[index]?.shape;
495
- if (nextShape && hasShapeRemoval(item.shape, nextShape)) {
496
- if (item.id !== void 0) return item;
497
- anonymousRemoval ??= item;
498
- }
499
- }
500
- return anonymousRemoval;
501
- }
502
- /** Returns replacements, undefined for a plain merge, or null when a rebuild is required. */
503
- function collectReplacements(prev, next) {
504
- let replaceMerge;
505
- if (next.objectShapes.aria && !prev.objectShapes.aria) return null;
506
- for (const key in next.collections) if (!prev.collections[key] && !prev.objectShapes[key] && !prev.leaves.includes(key) && !ComponentModel.hasClass(key)) return null;
507
- for (const key in prev.objectShapes) {
508
- const prevShape = prev.objectShapes[key];
509
- const nextShape = next.objectShapes[key];
510
- if (prevShape && nextShape) {
511
- if (hasShapeRemoval(prevShape, nextShape)) return null;
381
+ function getRootAttrs(attrs) {
382
+ const result = {};
383
+ for (const key in attrs) {
384
+ if (key.startsWith(NATIVE_EVENT_PREFIX)) {
385
+ const event = key.slice(9);
386
+ if (event) result[`on:${event}`] = attrs[key];
512
387
  continue;
513
388
  }
514
- if (!next.leaves.includes(key)) return null;
515
- }
516
- for (const key of prev.leaves) if (!next.leaves.includes(key) && next.collections[key] === void 0 && next.objectShapes[key] === void 0) return null;
517
- for (const key in prev.collections) {
518
- const prevCollection = prev.collections[key];
519
- if (key === "graphic" && next.hasAction) continue;
520
- const nextCollection = next.collections[key];
521
- if (!nextCollection && !ComponentModel.hasClass(key)) return null;
522
- const collectionRemoval = hasCollectionRemoval(prevCollection, nextCollection);
523
- const identityChange = nextCollection && !collectionRemoval && hasIdentityChange(prevCollection, nextCollection);
524
- const shapeRemoval = nextCollection ? findItemShapeRemoval(prevCollection, nextCollection) : void 0;
525
- if (shapeRemoval?.id !== void 0) return null;
526
- if (!shapeRemoval && !collectionRemoval && !identityChange) continue;
527
- if (!ComponentModel.hasClass(key)) return null;
528
- if (nextCollection && !preservesReplacementOrder(prevCollection, nextCollection)) return null;
529
- (replaceMerge ??= []).push(key);
389
+ if (!isOn(key)) result[key] = attrs[key];
530
390
  }
531
- return replaceMerge;
532
- }
533
- /**
534
- * Produce an update plan that preserves option structure and initialization semantics.
535
- * Falls back to `notMerge: true` when the change looks complex.
536
- */
537
- function planUpdate(prev, option) {
538
- const next = buildSignature(option);
539
- if (!prev) return {
540
- signature: next,
541
- plan: { notMerge: false }
542
- };
543
- const replaceMerge = collectReplacements(prev, next);
544
- if (replaceMerge === null) return {
545
- signature: next,
546
- plan: { notMerge: !next.hasAction }
547
- };
548
- replaceMerge?.sort();
549
- return {
550
- signature: next,
551
- plan: replaceMerge ? {
552
- notMerge: false,
553
- replaceMerge
554
- } : { notMerge: false }
555
- };
391
+ return result;
556
392
  }
557
393
  //#endregion
558
394
  //#region src/style.css?raw
@@ -596,8 +432,8 @@ var src_default = /* @__PURE__ */ defineComponent({
596
432
  const root = shallowRef();
597
433
  const chartHost = shallowRef();
598
434
  const chart = shallowRef();
599
- const themeRevision = shallowRef(0);
600
- const initOptionsRevision = shallowRef(0);
435
+ const updateRequest = shallowRef(0);
436
+ let pendingUpdate = 0;
601
437
  const defaultTheme = inject(THEME_KEY, null);
602
438
  const defaultInitOptions = inject(INIT_OPTIONS_KEY, null);
603
439
  const defaultUpdateOptions = inject(UPDATE_OPTIONS_KEY, null);
@@ -609,95 +445,131 @@ var src_default = /* @__PURE__ */ defineComponent({
609
445
  const realTheme = computed(() => props.theme ?? toValue(defaultTheme) ?? void 0);
610
446
  const realInitOptions = computed(() => props.initOptions ?? toValue(defaultInitOptions) ?? void 0);
611
447
  const realUpdateOptions = computed(() => props.updateOptions ?? toValue(defaultUpdateOptions));
612
- const rootAttrs = useRootAttrs(attrs);
613
448
  const terminallyDisposed = shallowRef(false);
614
- const { render: renderSlot, hasNewSlots, patchOption, setReady: setSlotsReady } = useSlotOption(slots, requestUpdate);
615
- const { patchOption: patchGraphicOption, render: renderGraphic } = useRuntime({
449
+ const { render: renderSlot, prepare: prepareSlots, setReady: setSlotsReady, cancelPendingUpdate: cancelSlotUpdate } = useSlotOption(slots, requestUpdate);
450
+ const graphic = useRuntime({
616
451
  slots,
617
452
  manualUpdate,
618
- requestUpdate: () => requestUpdate("graphic")
619
- }) ?? {};
453
+ requestUpdate: () => requestUpdate(2)
454
+ });
620
455
  let lastSignature;
621
456
  let lastAutoOption;
622
457
  let themeApplied = false;
623
- let initOptionsInvalidated = false;
624
458
  let optionApplied = false;
625
- let manualUpdateAtInit = manualUpdate.value;
626
459
  let initDeferred = false;
627
460
  let graphicSlotApplied = false;
628
- const updateFlush = patchGraphicOption ? "post" : "pre";
461
+ let updateRevision = 0;
462
+ let modelValid = false;
629
463
  function getAutoOption() {
630
- return props.option ?? (patchGraphicOption && (slots.graphic || graphicSlotApplied) ? {} : void 0);
464
+ return props.option ?? (graphic && (slots.graphic || graphicSlotApplied) ? {} : void 0);
631
465
  }
632
466
  function isCurrent(instance) {
633
467
  return instance !== void 0 && chart.value === instance && !terminallyDisposed.value;
634
468
  }
469
+ function runUpdate(instance, update, signature) {
470
+ const revision = ++updateRevision;
471
+ lastSignature = null;
472
+ modelValid = false;
473
+ update();
474
+ if (!isCurrent(instance) || updateRevision !== revision) return false;
475
+ lastSignature = signature;
476
+ modelValid = true;
477
+ return true;
478
+ }
635
479
  function applyTheme(instance) {
636
480
  if (!optionApplied || themeApplied) return false;
481
+ const revision = updateRevision + 1;
637
482
  themeApplied = true;
638
- instance.setTheme(realTheme.value || {});
639
- return isCurrent(instance);
483
+ try {
484
+ return runUpdate(instance, () => instance.setTheme(realTheme.value || {}), lastSignature === void 0 ? void 0 : null);
485
+ } catch (error) {
486
+ if (updateRevision === revision) themeApplied = false;
487
+ throw error;
488
+ }
640
489
  }
641
490
  function applyOption(instance, option, mode, manualOptions) {
642
491
  const manual = mode === "manual";
643
492
  initDeferred = false;
644
- const slotted = patchOption(option);
645
- const patched = patchGraphicOption ? patchGraphicOption(slotted) : slotted;
646
- const forceGraphic = mode === "graphic";
647
- const skipPlanning = manual || forceGraphic;
648
- let updateOptions;
649
- let nextSignature;
650
- if (skipPlanning) updateOptions = forceGraphic ? realUpdateOptions.value ?? void 0 : manualOptions;
651
- else if (realUpdateOptions.value) {
652
- updateOptions = realUpdateOptions.value;
653
- nextSignature = null;
654
- } else {
655
- const planned = planUpdate(lastSignature ?? void 0, slotted);
656
- updateOptions = !planned.signature.hasAction && (lastSignature === null || mode === "theme") ? {
493
+ const preparedSlots = prepareSlots(option);
494
+ const slotted = preparedSlots.option;
495
+ const hasGraphicSlot = Boolean(graphic && slots.graphic);
496
+ const source = hasGraphicSlot ? {
497
+ ...slotted,
498
+ graphic: void 0
499
+ } : slotted;
500
+ let updateOptions = manual ? manualOptions : realUpdateOptions.value ?? void 0;
501
+ let nextSignature = null;
502
+ const graphicOnly = mode === "graphic" && hasGraphicSlot && graphicSlotApplied && modelValid;
503
+ if (graphicOnly) nextSignature = lastSignature ?? null;
504
+ else if (!manual && !updateOptions) {
505
+ const planned = planUpdate(lastSignature ?? void 0, source);
506
+ updateOptions = !planned.signature.hasAction && lastSignature === null ? {
657
507
  ...planned.plan,
658
508
  notMerge: true
659
509
  } : planned.plan;
660
510
  nextSignature = planned.signature;
661
511
  }
662
- const hasGraphicSlot = Boolean(patchGraphicOption && slots.graphic);
663
- if ((forceGraphic || graphicSlotApplied || hasGraphicSlot) && !updateOptions?.notMerge) {
664
- const replaceMerge = updateOptions?.replaceMerge;
665
- const replacements = typeof replaceMerge === "string" ? [replaceMerge] : replaceMerge;
666
- if (!replacements?.includes("graphic")) updateOptions = {
667
- ...updateOptions,
668
- replaceMerge: replacements ? [...replacements, "graphic"] : ["graphic"]
669
- };
670
- }
512
+ const replaceMerge = updateOptions?.replaceMerge;
513
+ const replacements = typeof replaceMerge === "string" ? [replaceMerge] : replaceMerge ?? [];
514
+ const preparedGraphic = graphic?.prepare(slotted, !modelValid || !graphicSlotApplied || Boolean(updateOptions?.notMerge) || replacements.includes("graphic") || manual);
515
+ let patched = preparedGraphic?.option ?? slotted;
516
+ if ((preparedGraphic?.replace || graphicSlotApplied && !hasGraphicSlot) && !updateOptions?.notMerge && !replacements.includes("graphic")) updateOptions = {
517
+ ...updateOptions,
518
+ replaceMerge: [...replacements, "graphic"]
519
+ };
520
+ const replacesSource = replacements.some((key) => key !== "graphic");
521
+ if (graphicOnly && !updateOptions?.notMerge && !replacesSource) patched = { graphic: patched.graphic };
522
+ syncListeners();
523
+ if (!runUpdate(instance, () => instance.setOption(patched, updateOptions), nextSignature)) return;
524
+ preparedSlots.commit();
525
+ preparedGraphic?.commit();
671
526
  graphicSlotApplied = hasGraphicSlot;
672
527
  optionApplied = true;
673
- if (!skipPlanning) lastSignature = nextSignature;
674
528
  if (!manual) lastAutoOption = option;
675
- instance.setOption(patched, updateOptions);
676
- if (!isCurrent(instance) || mode === "theme") return;
677
- if (applyTheme(instance) && !manual) applyOption(instance, option, "theme");
529
+ if (applyTheme(instance) && !manual) applyOption(instance, option);
530
+ }
531
+ function scheduleUpdate(reason) {
532
+ pendingUpdate |= reason;
533
+ updateRequest.value++;
678
534
  }
679
- function requestUpdate(mode) {
535
+ function requestUpdate(reason = 1) {
536
+ if (!manualUpdate.value && !initDeferred && !terminallyDisposed.value) scheduleUpdate(reason);
537
+ }
538
+ function flushUpdate() {
539
+ const reasons = pendingUpdate;
540
+ pendingUpdate = 0;
680
541
  const instance = chart.value;
681
- if (!isCurrent(instance) || manualUpdate.value || initDeferred) return;
682
- const option = getAutoOption() ?? lastAutoOption;
683
- if (!option) return;
684
- applyOption(instance, option, mode);
542
+ if (!reasons || !isCurrent(instance)) return;
543
+ if (reasons & 8) {
544
+ cleanup();
545
+ init$1();
546
+ return;
547
+ }
548
+ if (initDeferred) return;
549
+ syncListeners();
550
+ const option = reasons & 3 ? getAutoOption() ?? lastAutoOption : lastAutoOption;
551
+ const needsTheme = !themeApplied && optionApplied;
552
+ if (needsTheme && !applyTheme(instance)) return;
553
+ if (!manualUpdate.value && option) applyOption(instance, option, reasons === 2 && !needsTheme ? "graphic" : void 0);
685
554
  }
686
- if (slots.graphic && !patchGraphicOption) warn$1("Detected `#graphic` slot but no extension is registered. Import from `vue-echarts/graphic` to enable it.");
687
- const stopListeners = useReactiveChartListeners(chart, attrs);
555
+ if (slots.graphic && !graphic) warn$1("Detected `#graphic` slot but no extension is registered. Import from `vue-echarts/graphic` to enable it.");
556
+ const { sync: syncListeners, stop: stopListeners } = useReactiveChartListeners(chart, attrs);
688
557
  function cleanup() {
558
+ pendingUpdate = 0;
559
+ graphic?.cancelPendingFlush();
560
+ updateRevision++;
689
561
  const instance = chart.value;
690
562
  chart.value = void 0;
691
563
  setSlotsReady(false);
692
564
  lastSignature = void 0;
565
+ modelValid = false;
693
566
  lastAutoOption = void 0;
694
567
  initDeferred = false;
695
568
  graphicSlotApplied = false;
696
569
  instance?.dispose();
697
570
  }
698
571
  function init$1() {
699
- initOptionsInvalidated = false;
700
- manualUpdateAtInit = manualUpdate.value;
572
+ pendingUpdate = 0;
701
573
  optionApplied = false;
702
574
  const host = chartHost.value;
703
575
  const instance = init(host, realTheme.value, realInitOptions.value);
@@ -741,46 +613,26 @@ var src_default = /* @__PURE__ */ defineComponent({
741
613
  };
742
614
  const stopThemeWatch = watch(realTheme, (theme, previousTheme) => {
743
615
  if (isIgnorableWatchChange(theme, previousTheme)) return;
744
- themeRevision.value++;
745
616
  themeApplied = false;
617
+ scheduleUpdate(4);
746
618
  }, {
747
619
  deep: true,
748
620
  flush: "sync"
749
621
  });
750
622
  const stopInitOptionsWatch = watch(realInitOptions, (options, previousOptions) => {
751
- if (!isIgnorableWatchChange(options, previousOptions)) {
752
- initOptionsInvalidated = true;
753
- initOptionsRevision.value++;
754
- }
623
+ if (!isIgnorableWatchChange(options, previousOptions)) scheduleUpdate(8);
755
624
  }, {
756
625
  deep: true,
757
626
  flush: "sync"
758
627
  });
759
- const stopOptionWatch = watch(() => manualUpdate.value ? SKIP_AUTO_UPDATE : props.option, (option, previousOption) => {
760
- if (option === SKIP_AUTO_UPDATE || previousOption === SKIP_AUTO_UPDATE) return;
761
- const nextOption = option ?? getAutoOption();
762
- if (!nextOption) return;
763
- const instance = chart.value;
764
- if (initOptionsInvalidated || !isCurrent(instance) || initDeferred) return;
765
- if (hasNewSlots()) return;
766
- applyOption(instance, nextOption);
767
- }, {
768
- deep: true,
769
- flush: updateFlush
770
- });
771
- const stopReinitWatch = watch([manualUpdate, initOptionsRevision], () => {
772
- if (!chart.value) return;
773
- cleanup();
774
- init$1();
775
- });
776
- const stopThemeApplyWatch = watch(themeRevision, () => {
777
- const instance = chart.value;
778
- if (!initOptionsInvalidated && manualUpdate.value === manualUpdateAtInit && isCurrent(instance) && !themeApplied) {
779
- if (!applyTheme(instance)) return;
780
- const option = lastAutoOption;
781
- if (option && !manualUpdate.value && !initDeferred && !hasNewSlots()) applyOption(instance, option, "theme");
782
- }
783
- }, { flush: updateFlush });
628
+ function watchOption() {
629
+ return watch(() => manualUpdate.value ? SKIP_AUTO_UPDATE : props.option, (option, previousOption) => {
630
+ if (option !== SKIP_AUTO_UPDATE && previousOption !== SKIP_AUTO_UPDATE && (option ?? getAutoOption())) requestUpdate();
631
+ }, { deep: true });
632
+ }
633
+ let stopOptionWatch = watchOption();
634
+ const stopModeWatch = watch(manualUpdate, () => scheduleUpdate(8), { flush: "sync" });
635
+ const stopUpdateWatch = watch(updateRequest, flushUpdate, { flush: "post" });
784
636
  const stopGroupWatch = watchSyncEffect(() => {
785
637
  const instance = chart.value;
786
638
  if (isCurrent(instance)) instance.group = props.group ?? "";
@@ -793,8 +645,8 @@ var src_default = /* @__PURE__ */ defineComponent({
793
645
  stopThemeWatch();
794
646
  stopInitOptionsWatch();
795
647
  stopOptionWatch();
796
- stopReinitWatch();
797
- stopThemeApplyWatch();
648
+ stopModeWatch();
649
+ stopUpdateWatch();
798
650
  stopGroupWatch();
799
651
  stopLoading();
800
652
  stopAutoresize();
@@ -807,14 +659,22 @@ var src_default = /* @__PURE__ */ defineComponent({
807
659
  const instance = chart.value;
808
660
  if (!isCurrent(instance)) return guardedClear();
809
661
  initDeferred = false;
810
- lastSignature = void 0;
811
- lastAutoOption = void 0;
812
- instance.clear();
662
+ pendingUpdate = 0;
663
+ graphic?.cancelPendingFlush();
664
+ cancelSlotUpdate();
665
+ stopOptionWatch();
666
+ stopOptionWatch = watchOption();
667
+ if (runUpdate(instance, () => instance.clear(), void 0)) {
668
+ lastAutoOption = void 0;
669
+ graphicSlotApplied = false;
670
+ optionApplied = true;
671
+ }
813
672
  };
814
673
  onMounted(() => {
815
674
  if (!terminallyDisposed.value) init$1();
816
675
  });
817
676
  onBeforeUnmount(() => {
677
+ stopOptionWatch();
818
678
  if (terminallyDisposed.value) return;
819
679
  terminallyDisposed.value = true;
820
680
  const element = root.value;
@@ -842,12 +702,10 @@ var src_default = /* @__PURE__ */ defineComponent({
842
702
  if (!terminallyDisposed.value) {
843
703
  const teleported = renderSlot();
844
704
  if (teleported) children.push(teleported);
845
- if (renderGraphic) {
846
- const graphic = renderGraphic();
847
- if (graphic) children.push(graphic);
848
- }
705
+ const graphicContent = graphic?.render();
706
+ if (graphicContent) children.push(graphicContent);
849
707
  }
850
- const forwardedAttrs = rootAttrs.value;
708
+ const forwardedAttrs = getRootAttrs(attrs);
851
709
  return h(TAG_NAME, {
852
710
  ...forwardedAttrs,
853
711
  ref: root,