proper support for tree-shakeable Lit components

This commit is contained in:
ArjixWasTaken
2025-10-12 03:16:12 +03:00
parent c6c71bea9f
commit 86a4a1b41e
3 changed files with 65 additions and 38 deletions

View File

@ -6,6 +6,7 @@ import { IconChevronRight } from '@mdui/icons/chevron-right.js';
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import { LitElementWrapper } from '@/solit';
export default createPlugin({
name: () => t('plugins.navigation.name'),
@ -17,9 +18,6 @@ export default createPlugin({
renderer: {
buttonContainer: document.createElement('div'),
start() {
const doNotTreeShake = [IconChevronLeft, IconChevronRight];
((a) => {})(doNotTreeShake);
if (!this.buttonContainer) {
this.buttonContainer = document.createElement('div');
}
@ -31,8 +29,9 @@ export default createPlugin({
content={t('plugins.navigation.templates.back.title')}
>
<mdui-button-icon onClick={() => history.back()}>
<mdui-icon-chevron-left
style={{ padding: '5px', scale: '1.5' }}
<LitElementWrapper
elementClass={IconChevronLeft}
props={{ style: { padding: '5px', scale: '1.5' } }}
/>
</mdui-button-icon>
</mdui-tooltip>
@ -40,8 +39,9 @@ export default createPlugin({
content={t('plugins.navigation.templates.forward.title')}
>
<mdui-button-icon onClick={() => history.forward()}>
<mdui-icon-chevron-right
style={{ padding: '5px', scale: '1.5' }}
<LitElementWrapper
elementClass={IconChevronRight}
props={{ style: { padding: '5px', scale: '1.5' } }}
/>
</mdui-button-icon>
</mdui-tooltip>

View File

@ -23,6 +23,8 @@ import { IconError } from '@mdui/icons/error.js';
import { IconStar } from '@mdui/icons/star.js';
import { IconStarBorder } from '@mdui/icons/star-border.js';
import { LitElementWrapper } from '@/solit';
import {
type ProviderName,
ProviderNames,
@ -58,7 +60,9 @@ const providerBias = (p: ProviderName) =>
(lyricsStore.lyrics[p].state === 'done' ? 1 : -1) +
(lyricsStore.lyrics[p].data?.lines?.length ? 2 : -1) +
// eslint-disable-next-line prettier/prettier
(lyricsStore.lyrics[p].data?.lines?.length && p === ProviderNames.YTMusic ? 1 : 0) +
(lyricsStore.lyrics[p].data?.lines?.length && p === ProviderNames.YTMusic
? 1
: 0) +
(lyricsStore.lyrics[p].data?.lyrics ? 1 : -1);
const pickBestProvider = () => {
@ -82,17 +86,6 @@ const [hasManuallySwitchedProvider, setHasManuallySwitchedProvider] =
export const LyricsPicker = (props: {
setStickRef: Setter<HTMLElement | null>;
}) => {
const doNotTreeShake = [
IconChevronLeft,
IconChevronRight,
IconCheckCircle,
IconWarning,
IconError,
IconStar,
IconStarBorder,
];
((a) => {})(doNotTreeShake);
const [videoId, setVideoId] = createSignal<string | null>(null);
const [starredProvider, setStarredProvider] =
createSignal<ProviderName | null>(null);
@ -200,10 +193,13 @@ export const LyricsPicker = (props: {
<div class="lyrics-picker" ref={props.setStickRef}>
<div class="lyrics-picker-left">
<mdui-button-icon>
<mdui-icon-chevron-left
onClick={previous}
role="button"
style={{ padding: '5px' }}
<LitElementWrapper
elementClass={IconChevronLeft}
props={{
onClick: previous,
role: 'button',
style: { padding: '5px' },
}}
/>
</mdui-button-icon>
</div>
@ -234,9 +230,9 @@ export const LyricsPicker = (props: {
/>
</Match>
<Match when={currentLyrics().state === 'error'}>
<mdui-icon-error
style={{ padding: '5px', scale: '0.8' }}
tabindex="-1"
<LitElementWrapper
elementClass={IconError}
props={{ style: { padding: '5px', scale: '0.8' } }}
/>
</Match>
<Match
@ -246,9 +242,9 @@ export const LyricsPicker = (props: {
currentLyrics().data?.lyrics)
}
>
<mdui-icon-check-circle
style={{ padding: '5px', scale: '0.8' }}
tabindex="-1"
<LitElementWrapper
elementClass={IconCheckCircle}
props={{ style: { padding: '5px', scale: '0.8' } }}
/>
</Match>
<Match
@ -258,9 +254,9 @@ export const LyricsPicker = (props: {
!currentLyrics().data?.lyrics
}
>
<mdui-icon-warning
style={{ padding: '5px', scale: '0.8' }}
tabindex="-1"
<LitElementWrapper
elementClass={IconWarning}
props={{ style: { padding: '5px', scale: '0.8' } }}
/>
</Match>
</Switch>
@ -270,10 +266,12 @@ export const LyricsPicker = (props: {
/>
<mdui-button-icon onClick={toggleStar} tabindex={-1}>
<Show
fallback={<mdui-icon-star-border />}
fallback={
<LitElementWrapper elementClass={IconStarBorder} />
}
when={starredProvider() === provider()}
>
<mdui-icon-star />
<LitElementWrapper elementClass={IconStar} />
</Show>
</mdui-button-icon>
</div>
@ -298,10 +296,13 @@ export const LyricsPicker = (props: {
<div class="lyrics-picker-left">
<mdui-button-icon>
<mdui-icon-chevron-right
onClick={next}
role="button"
style={{ padding: '5px' }}
<LitElementWrapper
elementClass={IconChevronRight}
props={{
onClick: next,
role: 'button',
style: { padding: '5px' },
}}
/>
</mdui-button-icon>
</div>

26
src/solit.tsx Normal file
View File

@ -0,0 +1,26 @@
// A SolidJS wrapper for a LitElement
import { createSignal, onMount, Show } from 'solid-js';
import { Dynamic } from 'solid-js/web';
export interface LitElementWrapperProps {
elementClass: CustomElementConstructor;
props?: Record<string, unknown>;
}
export const LitElementWrapper = (props: LitElementWrapperProps) => {
const [tagName, setTagName] = createSignal<string | null>(null);
onMount(() => {
// Create instance to discover tag name
const el = new props.elementClass();
setTagName(el.tagName.toLowerCase());
el.remove();
});
return (
<Show when={tagName()}>
<Dynamic component={tagName()!} {...(props.props || {})} />
</Show>
);
};