diff --git a/README.md b/README.md
index 1438d3d..49bed52 100644
--- a/README.md
+++ b/README.md
@@ -257,22 +257,53 @@ As Vue-ECharts binds events to the ECharts instance by default, there is some ca
### Provide / Inject
-Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `init-options` you can use the provide API like this:
+Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `theme` you can use the provide API like this:
-Vue 3
+Composition API
```js
import { THEME_KEY } from 'vue-echarts'
import { provide } from 'vue'
-// composition API
provide(THEME_KEY, 'dark')
-// options API
-{
- provide: {
- [THEME_KEY]: 'dark'
+// or provide a reactive state
+const theme = ref('dark')
+provide(THEME_KEY, computed(() => theme.value))
+
+// getter is also supported
+provide(THEME_KEY, () => theme.value)
+```
+
+
+
+
+Options API
+
+```js
+import { THEME_KEY } from 'vue-echarts'
+import { computed } from 'vue'
+
+export default {
+ {
+ provide: {
+ [THEME_KEY]: 'dark'
+ }
+ }
+}
+
+// Or make injections reactive
+export default {
+ data() {
+ return {
+ theme: 'dark'
+ }
+ },
+ provide() {
+ return {
+ [THEME_KEY]: computed(() => this.theme)
+ }
}
}
```
diff --git a/src/ECharts.ts b/src/ECharts.ts
index 3ec6ecb..9721246 100644
--- a/src/ECharts.ts
+++ b/src/ECharts.ts
@@ -11,8 +11,7 @@ import {
onBeforeUnmount,
h,
nextTick,
- watchEffect,
- unref
+ watchEffect
} from "vue";
import { init as initChart } from "echarts/core";
@@ -23,7 +22,7 @@ import {
useLoading,
loadingProps
} from "./composables";
-import { isOn, omitOn } from "./utils";
+import { isOn, omitOn, toValue } from "./utils";
import { register, TAG_NAME } from "./wc";
import type { PropType, InjectionKey } from "vue";
@@ -82,12 +81,14 @@ export default defineComponent({
const realOption = computed(
() => manualOption.value || props.option || null
);
- const realTheme = computed(() => props.theme || unref(defaultTheme) || {});
+ const realTheme = computed(
+ () => props.theme || toValue(defaultTheme) || {}
+ );
const realInitOptions = computed(
- () => props.initOptions || unref(defaultInitOptions) || {}
+ () => props.initOptions || toValue(defaultInitOptions) || {}
);
const realUpdateOptions = computed(
- () => props.updateOptions || unref(defaultUpdateOptions) || {}
+ () => props.updateOptions || toValue(defaultUpdateOptions) || {}
);
const nonEventAttrs = computed(() => omitOn(attrs));
const nativeListeners: Record = {};
diff --git a/src/composables/loading.ts b/src/composables/loading.ts
index e0c07f0..37a3341 100644
--- a/src/composables/loading.ts
+++ b/src/composables/loading.ts
@@ -1,4 +1,5 @@
-import { inject, computed, watchEffect, unref } from "vue";
+import { inject, computed, watchEffect } from "vue";
+import { toValue } from "../utils";
import type { Ref, InjectionKey, PropType } from "vue";
import type { EChartsType, LoadingOptions } from "../types";
@@ -15,7 +16,7 @@ export function useLoading(
): void {
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {});
const realLoadingOptions = computed(() => ({
- ...(unref(defaultLoadingOptions) || {}),
+ ...(toValue(defaultLoadingOptions) || {}),
...loadingOptions?.value
}));
diff --git a/src/types.ts b/src/types.ts
index 71f9b49..97e82f7 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,9 +1,18 @@
import { init } from "echarts/core";
import type { SetOptionOpts, ECElementEvent, ElementEvent } from "echarts/core";
-import type { MaybeRef } from "vue";
+import type { Ref, ShallowRef, WritableComputedRef, ComputedRef } from "vue";
-export type Injection = MaybeRef;
+export type MaybeRef =
+ | T
+ | Ref
+ | ShallowRef
+ | WritableComputedRef;
+export type MaybeRefOrGetter =
+ | MaybeRef
+ | ComputedRef
+ | (() => T);
+export type Injection = MaybeRefOrGetter;
type InitType = typeof init;
export type InitParameters = Parameters;
diff --git a/src/utils.ts b/src/utils.ts
index 8ac89ee..8792277 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,3 +1,6 @@
+import type { MaybeRefOrGetter } from "./types";
+import { unref } from "vue";
+
type Attrs = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
@@ -18,3 +21,13 @@ export function omitOn(attrs: Attrs): Attrs {
return result;
}
+
+// Copied from
+// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/shared/src/general.ts#L49-L50
+const isFunction = (val: unknown): val is Function => typeof val === "function";
+
+// Copied from
+// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/reactivity/src/ref.ts#L246-L248
+export function toValue(source: MaybeRefOrGetter): T {
+ return isFunction(source) ? source() : unref(source);
+}