diff --git a/components/vue/package.json b/components/vue/package.json
index 0e03849..f6dbe4e 100644
--- a/components/vue/package.json
+++ b/components/vue/package.json
@@ -2,7 +2,10 @@
"name": "@iconify/vue",
"description": "Iconify icon component for Vue 3.",
"author": "Vjacheslav Trushkin",
- "version": "4.1.3-beta.1",
+ "version": "4.2.0-dev.1",
+ "publishConfig": {
+ "tag": "next"
+ },
"license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/",
diff --git a/components/vue/src/iconify.ts b/components/vue/src/iconify.ts
index 71a20e0..097aad0 100644
--- a/components/vue/src/iconify.ts
+++ b/components/vue/src/iconify.ts
@@ -32,6 +32,10 @@ import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
// API
+import type {
+ IconifyCustomIconLoader,
+ IconifyCustomIconsLoader,
+} from '@iconify/core/lib/api/types';
import type {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@@ -64,6 +68,10 @@ import type {
IconifyIconLoaderAbort,
} from '@iconify/core/lib/api/icons';
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
+import {
+ setCustomIconLoader,
+ setCustomIconsLoader,
+} from '@iconify/core/lib/api/loaders';
import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache
@@ -124,6 +132,8 @@ export {
PartialIconifyAPIConfig,
IconifyAPIQueryParams,
IconifyAPICustomQueryParams,
+ IconifyCustomIconLoader,
+ IconifyCustomIconsLoader,
};
// Builder functions
@@ -423,7 +433,13 @@ const _api: IconifyAPIInternalFunctions = {
export { _api };
// IconifyAPIFunctions
-export { addAPIProvider, loadIcons, loadIcon };
+export {
+ addAPIProvider,
+ loadIcons,
+ loadIcon,
+ setCustomIconLoader,
+ setCustomIconsLoader,
+};
// IconifyStorageFunctions
export {
diff --git a/components/vue/tests/api/20-rendering-from-api-test.ts b/components/vue/tests/api/20-rendering-from-api-test.ts
index 0fa2c9f..0a49630 100644
--- a/components/vue/tests/api/20-rendering-from-api-test.ts
+++ b/components/vue/tests/api/20-rendering-from-api-test.ts
@@ -1,6 +1,6 @@
import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
-import { Icon, loadIcons, iconLoaded } from '../../';
+import { Icon, loadIcons, iconLoaded, setCustomIconLoader } from '../../';
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
import { provider, nextPrefix } from './load';
import { defaultIconResult } from '../empty';
@@ -218,4 +218,72 @@ describe('Rendering icon', () => {
const wrapper = mount(Wrapper, {});
});
});
+
+ test('custom loader', () => {
+ return new Promise((fulfill, reject) => {
+ const prefix = nextPrefix();
+ const name = 'render-test';
+ const iconName = `@${provider}:${prefix}:${name}`;
+ const className = `iconify iconify--${prefix} iconify--${provider}`;
+ let onLoadCalled = false;
+
+ setCustomIconLoader(
+ () => {
+ return iconData;
+ },
+ prefix,
+ provider
+ );
+
+ // Check if icon has been loaded
+ expect(iconLoaded(iconName)).toEqual(false);
+
+ // Load icon
+ loadIcons([iconName], (loaded, missing, pending) => {
+ // Make sure icon has been loaded
+ expect(loaded).toMatchObject([
+ {
+ provider,
+ prefix,
+ name,
+ },
+ ]);
+ expect(missing).toMatchObject([]);
+ expect(pending).toMatchObject([]);
+ expect(iconLoaded(iconName)).toEqual(true);
+
+ // Render component
+ const Wrapper = {
+ components: { Icon },
+ // Also test class string
+ template: ``,
+ methods: {
+ onLoad(name) {
+ expect(name).toEqual(iconName);
+ expect(onLoadCalled).toEqual(false);
+ onLoadCalled = true;
+ },
+ },
+ };
+ const wrapper = mount(Wrapper, {});
+
+ // Check HTML on next tick
+ nextTick()
+ .then(() => {
+ const html = wrapper.html().replace(/\s*\n\s*/g, '');
+ expect(html).toEqual(
+ ''
+ );
+
+ // Make sure onLoad has been called
+ expect(onLoadCalled).toEqual(true);
+
+ fulfill(true);
+ })
+ .catch(reject);
+ });
+ });
+ });
});