diff --git a/CHANGELOG.md b/CHANGELOG.md index c523ebf4..fe17ce7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +### Fixes + +- Fixed TypeScript declaration generation for libraries that re-export or wrap Vue ECharts components. The public type exports are `Component`, `Exposed`, and `Slots`; `Exposed` includes all exposed chart methods and read-only state. + ## 8.3.0 ### Improvements diff --git a/README.md b/README.md index 0f0c3aac..d44f3887 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,10 @@ const chart = ref | null>(null); Vue 3.5's `useTemplateRef` can infer this type automatically. +`Exposed` describes the chart methods and read-only `chart` and `root` properties exposed through a template ref. It includes `setOption` and the other methods listed below; use `InstanceType` when you also need Vue's component instance properties. + +Libraries can re-export or wrap `VChart` and the `vue-echarts/graphic` components while emitting their own TypeScript declarations. The root entry exports `Component`, the shared Vue component definition helper, and `Slots`, the Vue `SlotsType` metadata used by `VChart`, so inferred declarations can reference public types. The graphic entry exports its corresponding `GraphicComponent` type. For callable slots, use `InstanceType["$slots"]`; augment `VChartSlotsExtension` in `vue-echarts` to declare additional slots. The graphic entry re-exports the same extension interface. + ### Events You can bind events with Vue's `v-on` directive. diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 57ebbf36..76d47741 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -224,6 +224,10 @@ const chart = ref | null>(null); Vue 3.5 的 `useTemplateRef` 可以自动推导此类型。 +`Exposed` 描述通过模板 ref 暴露的图表方法及只读的 `chart`、`root` 属性,包含 `setOption` 和下文列出的其它方法。如果还需要 Vue 组件实例属性,请使用 `InstanceType`。 + +组件库可以重新导出或包装 `VChart` 及 `vue-echarts/graphic` 组件,并生成自己的 TypeScript 声明。根入口导出共享的 Vue 组件定义辅助类型 `Component` 和 `VChart` 使用的 Vue `SlotsType` 元数据 `Slots`,使推导出的声明能够引用公开类型。graphic 入口导出对应的 `GraphicComponent` 类型。需要可调用的插槽类型时,使用 `InstanceType["$slots"]`;需要声明额外插槽时,在 `vue-echarts` 模块中扩展 `VChartSlotsExtension`。graphic 入口重新导出的是同一个扩展接口。 + ### 事件 可以使用 Vue 的 `v-on` 指令绑定事件。 diff --git a/package-tests/consumer-declaration-emit.test-d.ts b/package-tests/consumer-declaration-emit.test-d.ts index e3cde60a..6346015a 100644 --- a/package-tests/consumer-declaration-emit.test-d.ts +++ b/package-tests/consumer-declaration-emit.test-d.ts @@ -1,4 +1,5 @@ import ECharts from "vue-echarts"; +import { GGroup, GRect } from "vue-echarts/graphic"; // Simulates a library that re-exports the component and emits its own `.d.ts`. // Fails with TS4023 / TS2742 if the component type reaches a name no entry point exports. @@ -7,3 +8,7 @@ export const ReExportedChart = ECharts; export const WrappedChart = { component: ECharts, } as const; + +// Graphic components share the component definition helper with the root entry. +export const ReExportedGroup = GGroup; +export const WrappedGraphic = { component: GRect } as const; diff --git a/package-tests/public-component-types.test-d.ts b/package-tests/public-component-types.test-d.ts new file mode 100644 index 00000000..7bdc96b2 --- /dev/null +++ b/package-tests/public-component-types.test-d.ts @@ -0,0 +1,51 @@ +import VChart, { + type Component, + type Exposed, + type VChartSlotsExtension, + type Slots, +} from "vue-echarts"; +import type { VChartSlotsExtension as GraphicSlotsExtension } from "vue-echarts/graphic"; +import type { SlotsType as VueSlotsType } from "vue"; +import type { EChartsType } from "echarts/core"; + +declare module "vue-echarts" { + interface VChartSlotsExtension { + custom?: (props: { value: number }) => unknown; + } +} + +type Assert = T; +type IsEqual = + (() => T extends A ? 1 : 2) extends () => T extends B ? 1 : 2 ? true : false; +type Instance = InstanceType; +type InstanceSlots = Instance["$slots"]; + +export type ExposedMatchesInstance = Assert< + IsEqual, { [K in keyof Exposed]: Exposed[K] }> +>; +export type ExposedIncludesSetOption = Assert< + IsEqual +>; +export type ExposedPreservesZRender = Assert>; +export type ExposedStateIsReadonly = Assert< + IsEqual, Readonly>> +>; +export type CustomSlotProps = Assert< + IsEqual>[0], { value: number }> +>; +export type GraphicSlotIsPreserved = Assert<"graphic" extends keyof InstanceSlots ? true : false>; +export type GraphicUsesSameExtension = Assert>; +export type SlotMetadataIsPreserved = Assert< + Slots extends VueSlotsType ? true : false +>; +export type InferredPropsArePreserved = Assert< + IsEqual +>; + +// All exported names remain usable in consumers that emit their own declarations. +export type WrapperComponent = Component< + Record, + Exposed, + Record, + Slots +>; diff --git a/src/ECharts.ts b/src/ECharts.ts index 0bf29ee8..34683d99 100644 --- a/src/ECharts.ts +++ b/src/ECharts.ts @@ -19,7 +19,7 @@ import type { InjectionKey, PropType, VNodeChild } from "vue"; import { usePublicAPI, type PublicMethods } from "./composables/api"; import { useAutoresize, autoresizeProps } from "./composables/autoresize"; import { useLoading, loadingProps } from "./composables/loading"; -import { useSlotOption, type SlotsTypes } from "./composables/slot"; +import { useSlotOption, type Slots } from "./composables/slot"; import { hasZeroDimension, isIgnorableWatchChange, warn } from "./utils"; import { register, TAG_NAME } from "./wc"; import { useRuntime as useGraphic } from "./graphic/runtime"; @@ -38,7 +38,7 @@ import type { UpdateOptions, UpdateOptionsInjection, Emits, - PublicComponent, + Component, } from "./types"; import type { EChartsElement } from "./wc"; @@ -72,7 +72,8 @@ const chartProps = { ...loadingProps, }; -type Bindings = { +/** Methods and read-only state exposed by VChart through a template ref. */ +export type Exposed = { setOption: SetOptionType; readonly root: HTMLElement | undefined; readonly chart: EChartsType | undefined; @@ -83,7 +84,7 @@ const ECharts = /* @__PURE__ */ defineComponent({ inheritAttrs: false, props: chartProps, emits: {} as Emits, - slots: Object as SlotsTypes, + slots: Object as Slots, setup(props, { attrs, expose, slots }) { const root = shallowRef(); const chartHost = shallowRef(); @@ -533,6 +534,6 @@ const ECharts = /* @__PURE__ */ defineComponent({ ); }) as unknown as typeof exposed & PublicMethods; }, -}) as PublicComponent; +}) as Component; export default ECharts; diff --git a/src/composables/slot.ts b/src/composables/slot.ts index ab657f2d..ea3159fc 100644 --- a/src/composables/slot.ts +++ b/src/composables/slot.ts @@ -7,7 +7,7 @@ import { shallowRef, shallowReactive, } from "vue"; -import type { Slots, SlotsType } from "vue"; +import type { Slots as VueSlots, SlotsType as VueSlotsType } from "vue"; import type { Option } from "../types"; import { isPlainObject, isValidArrayIndex, warn } from "../utils"; import type { TooltipComponentFormatterCallbackParams } from "echarts"; @@ -110,7 +110,7 @@ function writePath( return true; } -export function useSlotOption(slots: Slots, onSlotsChange: () => void) { +export function useSlotOption(slots: VueSlots, onSlotsChange: () => void) { const instance = getCurrentInstance()!; let detachedRoot: HTMLDivElement | undefined; const containers = shallowReactive>({}); @@ -275,7 +275,8 @@ export function useSlotOption(slots: Slots, onSlotsChange: () => void) { }; } -export type SlotsTypes = SlotsType< +/** Vue SlotsType metadata for VChart, including VChartSlotsExtension augmentations. */ +export type Slots = VueSlotsType< Record<"tooltip" | `tooltip-${string}`, TooltipComponentFormatterCallbackParams> & Record<"dataView" | `dataView-${string}`, Option> & VChartSlotsExtension diff --git a/src/graphic/component-factory.ts b/src/graphic/component-factory.ts index 2f805432..8a38b44b 100644 --- a/src/graphic/component-factory.ts +++ b/src/graphic/component-factory.ts @@ -11,7 +11,7 @@ import { watch, } from "vue"; -import type { PublicComponent } from "../types"; +import type { Component } from "../types"; import { warn } from "../utils"; import { GRAPHIC_COLLECTOR_KEY, GRAPHIC_PARENT_ID_KEY } from "./context"; import { resolveIdentity } from "./identity"; @@ -201,7 +201,7 @@ export function createComponent( }) as GraphicComponent; } -export type GraphicComponent = PublicComponent< +export type GraphicComponent = Component< ComponentProps, Record, GraphicEmits, diff --git a/src/graphic/index.ts b/src/graphic/index.ts index 9a00a428..1032b0b8 100644 --- a/src/graphic/index.ts +++ b/src/graphic/index.ts @@ -3,6 +3,7 @@ import { registerExtension } from "./extension"; registerExtension(); export type { VChartSlotsExtension } from "../index"; +export type { GraphicComponent } from "./component-factory"; export type { GraphicEmits, GraphicEventName, GraphicOnEventName } from "./types"; export type { GraphicCommonProps } from "./props-common"; export type { GraphicShapeProps } from "./props-shape"; diff --git a/src/index.ts b/src/index.ts index 26c185ad..9eddcd6e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,5 @@ export interface VChartSlotsExtension { export default ECharts; export * from "./ECharts"; -export type { AutoResize, LoadingOptions, PublicComponent } from "./types"; -export type { PublicMethods } from "./composables/api"; -export type { SlotsTypes } from "./composables/slot"; +export type { AutoResize, LoadingOptions, Component } from "./types"; +export type { Slots } from "./composables/slot"; diff --git a/src/types.ts b/src/types.ts index 31f93156..69f67c3c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,8 +29,9 @@ type EventProps = { : never; }; +/** Shared component definition for VChart and graphic components across supported Vue versions. */ // The first 13 DefineComponent parameters are stable across the supported Vue versions. -export type PublicComponent< +export type Component< Props extends ComponentPropsOptions, Bindings, Events extends EmitsOptions,