You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/web/routes/uix/components/icon/LazyIcon.svelte

78 lines
1.6 KiB

<script lang="ts">
import type { Component } from 'svelte';
import type { IconSize, IconStrokeWidth } from '$uix/eidos/components/icon/types';
import { loadIconByName } from './icon-loaders';
type Props = {
name: string;
size?: IconSize;
strokeWidth?: IconStrokeWidth;
color?: string;
decorative?: boolean;
title?: string;
};
let {
name,
size = 'md',
strokeWidth = 'auto',
color = 'currentColor',
decorative = true,
title
}: Props = $props();
let host = $state<HTMLElement | null>(null);
let visible = $state(false);
let Glyph = $state<Component | undefined>();
let requestId = 0;
$effect(() => {
const el = host;
if (!el || visible) return;
if (typeof IntersectionObserver === 'undefined') {
visible = true;
return;
}
const observer = new IntersectionObserver(
(entries) => {
if (!entries.some((entry) => entry.isIntersecting)) return;
visible = true;
observer.disconnect();
},
{ rootMargin: '180px' }
);
observer.observe(el);
return () => observer.disconnect();
});
$effect(() => {
const iconName = name;
if (!visible || !iconName) {
Glyph = undefined;
return;
}
const current = ++requestId;
void loadIconByName(iconName).then((component) => {
if (current === requestId) Glyph = component;
});
});
</script>
<span bind:this={host} data-uix-lazy-icon>
{#if Glyph}
{@const Icon = Glyph}
<Icon {size} {strokeWidth} {color} {decorative} {title} />
{/if}
</span>
<style>
[data-uix-lazy-icon] {
display: inline-grid;
place-items: center;
min-inline-size: 1em;
min-block-size: 1em;
}
</style>

Powered by TurnKey Linux.