vue-echarts 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/dist/graphic.js CHANGED
@@ -1,5 +1,5 @@
1
- import { d as parseOnEvent, f as warn$1, i as hasEventHandler, o as isBrowser, r as createEventInvoker, t as registerRuntime } from "./runtime-BSiQKM1W.js";
2
- import { Teleport, defineComponent, getCurrentInstance, h, inject, onBeforeMount, onBeforeUnmount, onMounted, onScopeDispose, onUpdated, provide, shallowRef, watch } from "vue";
1
+ import { a as hasEventHandler, c as isIgnorableWatchChange, f as parseOnEvent, i as createEventInvoker, n as registerRuntime, p as warn$1, t as planUpdate } from "./update-DiQcDAnW.js";
2
+ import { Teleport, defineComponent, getCurrentInstance, h, inject, onBeforeMount, onBeforeUnmount, onMounted, onScopeDispose, onUpdated, provide, queuePostFlushCb, shallowRef, watch } from "vue";
3
3
  import { use } from "echarts/core";
4
4
  import { GraphicComponent } from "echarts/components";
5
5
  const COMMON_PROP_KEYS = [
@@ -459,6 +459,7 @@ function toElement(node, children) {
459
459
  id
460
460
  };
461
461
  for (const key of COMMON_PROP_KEYS) {
462
+ if (key === "id") continue;
462
463
  const value = props[key];
463
464
  if (value !== void 0 && !shapeKeys?.includes(key) && !styleKeys?.includes(key)) out[key] = value;
464
465
  }
@@ -476,6 +477,7 @@ function toElement(node, children) {
476
477
  if (style) out.style = style;
477
478
  return out;
478
479
  }
480
+ /** Build the tree in the order supplied by the collector. */
479
481
  function buildOption(nodes, rootId) {
480
482
  const byParent = /* @__PURE__ */ new Map();
481
483
  const occupiedRootIds = /* @__PURE__ */ new Set();
@@ -489,7 +491,6 @@ function buildOption(nodes, rootId) {
489
491
  byParent.set(node.parentId, [node]);
490
492
  }
491
493
  while (occupiedRootIds.has(rootId)) rootId += "_";
492
- for (const list of byParent.values()) list.sort((a, b) => a.order - b.order);
493
494
  const childrenOf = (parentId) => byParent.get(parentId)?.map((node) => {
494
495
  if (node.type !== "group") return toElement(node);
495
496
  return toElement(node, childrenOf(node.id));
@@ -497,7 +498,6 @@ function buildOption(nodes, rootId) {
497
498
  return { graphic: { elements: [{
498
499
  type: "group",
499
500
  id: rootId,
500
- $action: "replace",
501
501
  children: childrenOf(null) ?? []
502
502
  }] } };
503
503
  }
@@ -507,10 +507,45 @@ function createCollector(onFlush) {
507
507
  const nodes = /* @__PURE__ */ new Map();
508
508
  const seenInPass = /* @__PURE__ */ new Map();
509
509
  const warnedKeys = /* @__PURE__ */ new Set();
510
- let order = 0;
510
+ let version = 0;
511
511
  let pending = false;
512
+ let root;
513
+ let observer;
514
+ const byElement = /* @__PURE__ */ new WeakMap();
515
+ let orderedNodes = [];
516
+ let orderDirty = true;
517
+ function syncOrder() {
518
+ if (!root) return false;
519
+ if (observer?.takeRecords().length) orderDirty = true;
520
+ if (!orderDirty) return false;
521
+ orderDirty = false;
522
+ const nextNodes = [];
523
+ const walker = root.ownerDocument.createTreeWalker(root, 1);
524
+ for (let element = walker.nextNode(); element; element = walker.nextNode()) {
525
+ const node = byElement.get(element);
526
+ if (node && nodes.get(node.id) === node) nextNodes.push(node);
527
+ }
528
+ const changed = nextNodes.length !== orderedNodes.length || nextNodes.some((node, index) => node.id !== orderedNodes[index].id);
529
+ orderedNodes = nextNodes;
530
+ return changed;
531
+ }
532
+ function setRoot(value) {
533
+ observer?.disconnect();
534
+ root = value;
535
+ orderedNodes = [];
536
+ orderDirty = true;
537
+ if (root) {
538
+ observer = new MutationObserver(() => {
539
+ orderDirty = true;
540
+ if (syncOrder()) requestFlush();
541
+ });
542
+ observer.observe(root, {
543
+ childList: true,
544
+ subtree: true
545
+ });
546
+ }
547
+ }
512
548
  function beginPass() {
513
- order = 0;
514
549
  seenInPass.clear();
515
550
  }
516
551
  function warn(message, onceKey) {
@@ -521,30 +556,34 @@ function createCollector(onFlush) {
521
556
  function register(node) {
522
557
  const seenSource = seenInPass.get(node.id);
523
558
  if (seenSource !== void 0 && seenSource !== node.sourceId) warn(`Duplicate graphic id "${node.id}" detected. Updates may be unstable.`, `duplicate-id:${node.id}`);
524
- const nextOrder = node.order ?? order;
525
- order = Math.max(order, nextOrder + 1);
526
559
  const existing = nodes.get(node.id);
527
560
  const sameSource = existing?.sourceId === node.sourceId;
528
- const unchanged = sameSource && existing.type === node.type && existing.parentId === node.parentId && existing.props === node.props && existing.handlers === node.handlers && existing.order === nextOrder;
561
+ const unchanged = sameSource && existing.type === node.type && existing.parentId === node.parentId && existing.props === node.props && isIgnorableWatchChange(existing.handlers, node.handlers) && existing.element === node.element;
529
562
  seenInPass.set(node.id, node.sourceId);
530
563
  if (unchanged) return;
531
- nodes.set(node.id, {
564
+ const registered = {
532
565
  ...node,
533
566
  handlerCache: sameSource ? existing?.handlerCache : void 0,
534
- order: nextOrder
535
- });
567
+ version: ++version
568
+ };
569
+ nodes.set(node.id, registered);
570
+ orderDirty = true;
571
+ if (node.element) byElement.set(node.element, registered);
536
572
  requestFlush();
537
573
  }
538
574
  function unregister(id, sourceId) {
539
575
  const existing = nodes.get(id);
540
576
  if (!existing || existing.sourceId !== sourceId) return;
541
577
  nodes.delete(id);
578
+ orderDirty = true;
542
579
  requestFlush();
543
580
  }
544
- function requestFlush() {
581
+ function requestFlush(id, sourceId) {
582
+ const node = id === void 0 ? void 0 : nodes.get(id);
583
+ if (node && node.sourceId === sourceId) node.version = ++version;
545
584
  if (pending) return;
546
585
  pending = true;
547
- queueMicrotask(() => {
586
+ queuePostFlushCb(() => {
548
587
  if (!pending) return;
549
588
  pending = false;
550
589
  beginPass();
@@ -552,10 +591,17 @@ function createCollector(onFlush) {
552
591
  });
553
592
  }
554
593
  function getNodes() {
555
- return nodes.values();
594
+ syncOrder();
595
+ return root ? orderedNodes : Array.from(nodes.values());
596
+ }
597
+ function dispose() {
598
+ cancelPendingFlush();
599
+ setRoot(void 0);
600
+ nodes.clear();
556
601
  }
557
602
  function cancelPendingFlush() {
558
603
  pending = false;
604
+ syncOrder();
559
605
  beginPass();
560
606
  }
561
607
  return {
@@ -565,87 +611,15 @@ function createCollector(onFlush) {
565
611
  warn,
566
612
  getNodes,
567
613
  requestFlush,
568
- cancelPendingFlush
614
+ cancelPendingFlush,
615
+ setRoot,
616
+ dispose
569
617
  };
570
618
  }
571
619
  //#endregion
572
620
  //#region src/graphic/context.ts
573
621
  const GRAPHIC_COLLECTOR_KEY = Symbol("vue-echarts:graphic-collector");
574
622
  const GRAPHIC_PARENT_ID_KEY = Symbol("vue-echarts:graphic-parent-id");
575
- const GRAPHIC_ORDER_KEY = Symbol("vue-echarts:graphic-order");
576
- //#endregion
577
- //#region src/graphic/identity.ts
578
- function toOrderKey(key) {
579
- return typeof key === "string" ? `key:${key}` : key ?? void 0;
580
- }
581
- function resolveIdentity(propsId, vnodeKey, uid) {
582
- if (propsId != null) {
583
- const id = String(propsId);
584
- return {
585
- id,
586
- orderKey: `id:${id}`
587
- };
588
- }
589
- const orderKey = toOrderKey(vnodeKey);
590
- if (orderKey !== void 0) return {
591
- id: typeof vnodeKey === "string" ? vnodeKey : `__ve_graphic_${uid}`,
592
- orderKey
593
- };
594
- return { id: `__ve_graphic_${uid}` };
595
- }
596
- function resolveOrderKey(propsId, vnodeKey) {
597
- if (propsId != null) return `id:${String(propsId)}`;
598
- return toOrderKey(vnodeKey) ?? null;
599
- }
600
- //#endregion
601
- //#region src/graphic/marker.ts
602
- const GRAPHIC_COMPONENT_MARKER = Symbol("vue-echarts:graphic-component");
603
- //#endregion
604
- //#region src/graphic/order.ts
605
- function isGraphic(vnode) {
606
- const type = vnode.type;
607
- if (!type || typeof type !== "object") return false;
608
- return typeof type[GRAPHIC_COMPONENT_MARKER] === "string";
609
- }
610
- function collect(value, orderMap, order) {
611
- if (Array.isArray(value)) {
612
- for (const child of value) order = collect(child, orderMap, order);
613
- return order;
614
- }
615
- if (!value || typeof value !== "object") return order;
616
- const vnode = value;
617
- const children = vnode.children;
618
- const graphic = isGraphic(vnode);
619
- const type = typeof vnode.type;
620
- const opaqueComponent = !Array.isArray(children) && (type === "object" || type === "function");
621
- const props = vnode.props;
622
- const identity = graphic || opaqueComponent ? resolveOrderKey(props?.id, vnode.key) : null;
623
- if (identity !== null) orderMap.set(identity, order);
624
- if (graphic) return order + 1;
625
- if (identity !== null) order++;
626
- if (Array.isArray(children)) for (const child of children) order = collect(child, orderMap, order);
627
- return order;
628
- }
629
- function isSameOrder(current, next) {
630
- if (current.size !== next.size) return false;
631
- for (const [key, order] of current) if (next.get(key) !== order) return false;
632
- return true;
633
- }
634
- function createOrderTracker() {
635
- let current = /* @__PURE__ */ new Map();
636
- const ref = shallowRef(current);
637
- return {
638
- ref,
639
- update(value) {
640
- const next = /* @__PURE__ */ new Map();
641
- collect(value, next, 0);
642
- if (!isSameOrder(current, next)) {
643
- current = next;
644
- ref.value = current;
645
- }
646
- }
647
- };
648
- }
649
623
  //#endregion
650
624
  //#region src/graphic/mount.ts
651
625
  const GraphicMount = defineComponent({
@@ -659,36 +633,33 @@ const GraphicMount = defineComponent({
659
633
  const { collector } = props;
660
634
  const { beginPass } = collector;
661
635
  const detachedRoot = shallowRef();
662
- const contentReady = shallowRef(isBrowser() && !instance.vnode.el);
636
+ const hydrating = Boolean(instance.vnode.el);
663
637
  const parentId = shallowRef(null);
664
- const order = createOrderTracker();
665
638
  onBeforeMount(() => {
666
639
  const host = instance.parent?.subTree.el;
667
- if (host) {
640
+ if (host && !hydrating) {
668
641
  const target = host.ownerDocument.createElement("div");
669
642
  host.appendChild(target);
670
643
  detachedRoot.value = target;
644
+ collector.setRoot(target);
671
645
  }
672
646
  });
673
647
  onMounted(() => {
674
648
  const ownerDocument = instance.vnode.el.ownerDocument;
675
649
  const target = detachedRoot.value;
676
650
  target?.remove();
677
- if (target?.ownerDocument !== ownerDocument) detachedRoot.value = ownerDocument.createElement("div");
678
- contentReady.value = true;
651
+ if (target?.ownerDocument !== ownerDocument) {
652
+ detachedRoot.value = ownerDocument.createElement("div");
653
+ collector.setRoot(detachedRoot.value);
654
+ }
679
655
  });
680
656
  provide(GRAPHIC_COLLECTOR_KEY, collector);
681
657
  provide(GRAPHIC_PARENT_ID_KEY, parentId);
682
- provide(GRAPHIC_ORDER_KEY, order.ref);
683
658
  return () => {
684
659
  beginPass();
685
- const content = slots.default();
686
- order.update(content);
687
660
  const target = detachedRoot.value;
688
- return h(Teleport, {
689
- to: target ?? "body",
690
- disabled: !target
691
- }, target && contentReady.value ? content : []);
661
+ if (!target) return null;
662
+ return h(Teleport, { to: target }, slots.default());
692
663
  };
693
664
  }
694
665
  });
@@ -701,14 +672,19 @@ function registerExtension() {
701
672
  const { slots, manualUpdate, requestUpdate } = ctx;
702
673
  const collector = createCollector(handleFlush);
703
674
  let hasGraphicSlot = Boolean(slots.graphic);
675
+ let signature;
676
+ let versions = /* @__PURE__ */ new Map();
704
677
  function handleFlush() {
705
678
  if (manualUpdate.value) {
679
+ const nodes = collector.getNodes();
680
+ const changed = !slots.graphic || nodes.length !== versions.size || nodes.some((node) => versions.get(node.id) !== node.version);
681
+ if (!signature || !changed) return;
706
682
  collector.warn("`#graphic` slot updates are ignored when `manual-update` is `true`.", "manual-update-graphic");
707
683
  return;
708
684
  }
709
685
  requestUpdate();
710
686
  }
711
- onScopeDispose(collector.cancelPendingFlush);
687
+ onScopeDispose(collector.dispose);
712
688
  onUpdated(() => {
713
689
  const nextHasGraphicSlot = Boolean(slots.graphic);
714
690
  if (nextHasGraphicSlot === hasGraphicSlot) return;
@@ -717,15 +693,44 @@ function registerExtension() {
717
693
  handleFlush();
718
694
  });
719
695
  return {
720
- patchOption(option) {
696
+ cancelPendingFlush: collector.cancelPendingFlush,
697
+ prepare(option, reset) {
721
698
  hasGraphicSlot = Boolean(slots.graphic);
722
- if (!hasGraphicSlot) return option;
723
- if (option.graphic) collector.warn("`#graphic` slot is provided, so `option.graphic` is ignored. Remove one of them to avoid ambiguity.", "option-graphic-override");
724
- const nextOption = buildOption(collector.getNodes(), ROOT_ID);
725
699
  collector.cancelPendingFlush();
700
+ if (!hasGraphicSlot) return {
701
+ option,
702
+ replace: false,
703
+ commit: () => {
704
+ signature = void 0;
705
+ versions.clear();
706
+ }
707
+ };
708
+ if (option.graphic) collector.warn("`#graphic` slot is provided, so `option.graphic` is ignored. Remove one of them to avoid ambiguity.", "option-graphic-override");
709
+ const nodes = collector.getNodes();
710
+ const nextOption = buildOption(nodes, ROOT_ID);
711
+ const planned = planUpdate(signature, nextOption);
712
+ const replace = reset || !signature || planned.plan.notMerge || Boolean(planned.plan.replaceMerge?.length);
713
+ const nextVersions = new Map(nodes.map((node) => [node.id, node.version]));
714
+ const elements = [];
715
+ function collectChanges(element, parentId) {
716
+ if (nextVersions.has(element.id) && nextVersions.get(element.id) !== versions.get(element.id)) {
717
+ const { children: _, ...props } = element;
718
+ props.parentId = parentId;
719
+ elements.push(props);
720
+ }
721
+ element.children?.forEach((child) => collectChanges(child, element.id));
722
+ }
723
+ if (!replace) nextOption.graphic.elements.forEach((element) => collectChanges(element));
724
+ const patched = { ...option };
725
+ delete patched.graphic;
726
+ if (replace || elements.length) patched.graphic = replace ? nextOption.graphic : { elements };
726
727
  return {
727
- ...option,
728
- graphic: nextOption.graphic
728
+ option: patched,
729
+ replace,
730
+ commit: () => {
731
+ signature = planned.signature;
732
+ versions = nextVersions;
733
+ }
729
734
  };
730
735
  },
731
736
  render() {
@@ -736,67 +741,91 @@ function registerExtension() {
736
741
  });
737
742
  }
738
743
  //#endregion
744
+ //#region src/graphic/identity.ts
745
+ function resolveIdentity(propsId, vnodeKey, uid) {
746
+ if (propsId != null) return String(propsId);
747
+ return typeof vnodeKey === "string" ? vnodeKey : `__ve_graphic_${uid}`;
748
+ }
749
+ //#endregion
739
750
  //#region src/graphic/component-factory.ts
740
- const runtimeProps = {
751
+ const componentProps = {
741
752
  ...commonProps,
742
- ...shapeProps,
743
- width: textPropOverrides.width
753
+ ...shapeProps
744
754
  };
755
+ function getRuntimeProps(type) {
756
+ const keys = COMMON_PROP_KEYS.filter((key) => type !== "text" || key !== "textContent" && key !== "textConfig");
757
+ if (type === "group") keys.push(...GROUP_PROP_KEYS);
758
+ else {
759
+ const shapeKeys = SHAPE_KEYS_BY_TYPE[type];
760
+ const styleKeys = shapeKeys ? PATH_STYLE_KEYS : STYLE_KEYS_BY_TYPE[type];
761
+ const commonStyleKeys = type === "text" ? TEXT_COMMON_STYLE_KEYS : COMMON_STYLE_KEYS;
762
+ keys.push("style", "styleTransition", ...DISPLAYABLE_PROP_KEYS, ...commonStyleKeys, ...styleKeys);
763
+ if (shapeKeys) keys.push("shape", "shapeTransition", ...PATH_PROP_KEYS, ...shapeKeys);
764
+ }
765
+ const definitions = type === "text" ? {
766
+ ...componentProps,
767
+ ...textPropOverrides
768
+ } : {
769
+ ...componentProps,
770
+ r: type === "rect" ? componentProps.r : Number
771
+ };
772
+ return Object.fromEntries(keys.map((key) => [key, definitions[key]]));
773
+ }
745
774
  /* @__NO_SIDE_EFFECTS__ */
746
775
  function createComponent(name, type) {
747
- const component = defineComponent({
776
+ return defineComponent({
748
777
  name,
749
778
  inheritAttrs: false,
750
- props: runtimeProps,
779
+ props: getRuntimeProps(type),
751
780
  emits: {},
752
781
  setup(props, { attrs, slots }) {
753
782
  const instance = getCurrentInstance();
754
783
  const collector = inject(GRAPHIC_COLLECTOR_KEY, null);
755
784
  const parentIdRef = inject(GRAPHIC_PARENT_ID_KEY, null);
756
- const parentOrderRef = inject(GRAPHIC_ORDER_KEY, null);
757
785
  if (!collector) {
758
786
  warn$1(`\`${name}\` must be used inside \`#graphic\` slot.`);
759
787
  return () => null;
760
788
  }
761
789
  const { register: registerNode, unregister, requestFlush } = collector;
762
- let currentId = null;
763
- watch([props, () => attrs], requestFlush, { deep: true });
790
+ let currentId;
791
+ let element;
792
+ watch([props, () => attrs], () => requestFlush(currentId, instance.uid), { deep: true });
764
793
  function register() {
765
- const { id, orderKey } = resolveIdentity(props.id, instance.vnode.key, instance.uid);
766
- if (currentId !== null && currentId !== id) unregister(currentId, instance.uid);
794
+ const id = resolveIdentity(props.id, instance.vnode.key, instance.uid);
795
+ if (currentId !== void 0 && currentId !== id) unregister(currentId, instance.uid);
767
796
  currentId = id;
768
- registerNode({
797
+ if (element) registerNode({
769
798
  id,
770
799
  type,
771
800
  parentId: parentIdRef.value,
772
- order: orderKey !== void 0 ? parentOrderRef?.value.get(orderKey) : void 0,
801
+ element,
773
802
  props,
774
- handlers: attrs,
803
+ handlers: { ...attrs },
775
804
  sourceId: instance.uid
776
805
  });
777
806
  return id;
778
807
  }
808
+ const setElement = (value) => {
809
+ if (value === element) return;
810
+ element = value ?? void 0;
811
+ if (element) register();
812
+ };
779
813
  onBeforeUnmount(() => unregister(currentId, instance.uid));
780
814
  if (type === "group") {
781
815
  const providedParent = shallowRef(null);
782
- const childOrder = createOrderTracker();
783
816
  provide(GRAPHIC_PARENT_ID_KEY, providedParent);
784
- provide(GRAPHIC_ORDER_KEY, childOrder.ref);
785
817
  return () => {
786
818
  providedParent.value = register();
787
- const content = slots.default?.() ?? null;
788
- childOrder.update(content);
789
- return content;
819
+ const content = slots.default?.() ?? [];
820
+ return h("div", { ref: setElement }, content);
790
821
  };
791
822
  }
792
823
  return () => {
793
824
  register();
794
- return null;
825
+ return h("div", { ref: setElement });
795
826
  };
796
827
  }
797
828
  });
798
- component[GRAPHIC_COMPONENT_MARKER] = type;
799
- return component;
800
829
  }
801
830
  //#endregion
802
831
  //#region src/graphic/components.ts