diff --git a/components/svelte/src/Icon.svelte b/components/svelte/src/Icon.svelte
index ed832a5..c1c40cb 100644
--- a/components/svelte/src/Icon.svelte
+++ b/components/svelte/src/Icon.svelte
@@ -16,6 +16,8 @@ import {
buildIcon,
loadIcons,
loadIcon,
+ setCustomIconLoader,
+ setCustomIconsLoader,
addAPIProvider,
_api
} from './functions';
@@ -34,6 +36,8 @@ export {
buildIcon,
loadIcons,
loadIcon,
+ setCustomIconLoader,
+ setCustomIconsLoader,
addAPIProvider,
_api
}
@@ -79,7 +83,8 @@ export {
// Generate data
$: {
counter;
- const iconData = checkIconState($$props.icon, state, mounted, loaded, onLoad);
+ const isMounted = !!$$props.ssr || mounted;
+ const iconData = checkIconState($$props.icon, state, isMounted, loaded, onLoad);
data = iconData ? generateIcon(iconData.data, $$props) : null;
if (data && iconData.classes) {
// Add classes
diff --git a/components/svelte/src/functions.ts b/components/svelte/src/functions.ts
index 93bc749..c58b405 100644
--- a/components/svelte/src/functions.ts
+++ b/components/svelte/src/functions.ts
@@ -22,6 +22,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,
@@ -54,6 +58,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
@@ -112,6 +120,8 @@ export {
PartialIconifyAPIConfig,
IconifyAPIQueryParams,
IconifyAPICustomQueryParams,
+ IconifyCustomIconLoader,
+ IconifyCustomIconsLoader,
};
// Builder functions
@@ -360,7 +370,13 @@ const _api: IconifyAPIInternalFunctions = {
export { _api };
// IconifyAPIFunctions
-export { addAPIProvider, loadIcons, loadIcon };
+export {
+ addAPIProvider,
+ loadIcons,
+ loadIcon,
+ setCustomIconLoader,
+ setCustomIconsLoader,
+};
// IconifyStorageFunctions
export {
diff --git a/components/svelte/src/iconify.ts b/components/svelte/src/iconify.ts
index 3c836ef..b891190 100644
--- a/components/svelte/src/iconify.ts
+++ b/components/svelte/src/iconify.ts
@@ -34,6 +34,8 @@ export {
PartialIconifyAPIConfig,
IconifyAPIQueryParams,
IconifyAPICustomQueryParams,
+ IconifyCustomIconLoader,
+ IconifyCustomIconsLoader,
} from './functions';
// Builder functions
@@ -60,4 +62,11 @@ export {
export { calculateSize, replaceIDs, buildIcon } from './functions';
-export { loadIcons, loadIcon, addAPIProvider, _api } from './functions';
+export {
+ addAPIProvider,
+ loadIcons,
+ loadIcon,
+ setCustomIconLoader,
+ setCustomIconsLoader,
+ _api,
+} from './functions';
diff --git a/components/svelte/src/props.ts b/components/svelte/src/props.ts
index 53182d7..8d03515 100644
--- a/components/svelte/src/props.ts
+++ b/components/svelte/src/props.ts
@@ -21,6 +21,9 @@ export type IconifyIconCustomisations = RawIconifyIconCustomisations & {
// Inline mode
inline?: boolean;
+
+ // SSR: render icon instantly without waiting for component to mount
+ ssr?: boolean;
};
export const defaultExtendedIconCustomisations = {
diff --git a/components/svelte/src/render.ts b/components/svelte/src/render.ts
index efa7f8c..c759fad 100644
--- a/components/svelte/src/render.ts
+++ b/components/svelte/src/render.ts
@@ -112,6 +112,7 @@ export function render(
case 'style':
case 'onLoad':
case 'mode':
+ case 'ssr':
break;
// Boolean attributes
diff --git a/components/svelte/tests/iconify/10-basic.test.ts b/components/svelte/tests/iconify/10-basic.test.ts
index 697c2c3..3bc36b8 100644
--- a/components/svelte/tests/iconify/10-basic.test.ts
+++ b/components/svelte/tests/iconify/10-basic.test.ts
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';
import { render } from '@testing-library/svelte';
-import Icon from '../../';
+import Icon, { setCustomIconLoader, loadIcon } from '../../';
const iconData = {
body: '',
@@ -35,4 +35,42 @@ describe('Creating component', () => {
const style = node.style;
expect(typeof style).toBe('object');
});
+
+ test('custom loader', async () => {
+ const prefix = 'customLoader';
+ const name = 'TestIcon';
+
+ // Set custom loader and load icon data
+ setCustomIconLoader(() => {
+ return iconData;
+ }, prefix);
+ await loadIcon(`${prefix}:${name}`);
+
+ // Create component
+ const component = render(Icon, {
+ 'icon': `${prefix}:${name}`,
+ 'ssr': true,
+ 'on:load': () => {
+ // Should be called only for icons loaded from API
+ throw new Error('onLoad called for object!');
+ },
+ });
+ const node = component.container.querySelector('svg')!;
+ expect(node).not.toBeNull();
+ expect(node.parentNode).not.toBeNull();
+ const html = (node.parentNode as HTMLDivElement).innerHTML;
+
+ // Check HTML
+ expect(html.replace(//gm, '')).toBe(
+ ``
+ );
+
+ // Make sure getAttribute() works, used in other tests
+ expect(node.getAttribute('xmlns')).toBe('http://www.w3.org/2000/svg');
+ expect(node.getAttribute('aria-hidden')).toBe('true');
+
+ // Make sure style exists
+ const style = node.style;
+ expect(typeof style).toBe('object');
+ });
});