mirror of
https://github.com/pheralb/svgl.git
synced 2025-02-11 09:40:31 +08:00
🚀 Add copy as web component + use new `templates
` utils
This commit is contained in:
parent
b9db482f0c
commit
313d293ba6
@ -9,19 +9,24 @@
|
|||||||
import { buttonStyles } from '@/ui/styles';
|
import { buttonStyles } from '@/ui/styles';
|
||||||
|
|
||||||
// Utils:
|
// Utils:
|
||||||
import { getSvgContent } from '@/utils/getSvgContent';
|
import { cn } from '@/utils/cn';
|
||||||
import { getReactComponentCode } from '@/utils/getReactComponentCode';
|
|
||||||
import { clipboard } from '@/utils/clipboard';
|
import { clipboard } from '@/utils/clipboard';
|
||||||
import { copyToClipboard as figmaCopyToClipboard } from '@/figma/copy-to-clipboard';
|
import { copyToClipboard as figmaCopyToClipboard } from '@/figma/copy-to-clipboard';
|
||||||
import { cn } from '@/utils/cn';
|
|
||||||
import { componentTemplate } from '@/utils/componentTemplate';
|
// Templates:
|
||||||
import { generateAngularComponent } from '@/utils/generateAngularComponent';
|
import { getSource } from '@/templates/getSource';
|
||||||
|
import { getReactCode } from '@/templates/getReactCode';
|
||||||
|
import { getVueCode } from '@/templates/getVueCode';
|
||||||
|
import { getSvelteCode } from '@/templates/getSvelteCode';
|
||||||
|
import { getAngularCode } from '@/templates/getAngularCode';
|
||||||
|
import { getWebComponent } from '@/templates/getWebComponent';
|
||||||
|
|
||||||
//Icons:
|
//Icons:
|
||||||
import ReactIcon from '@/components/icons/reactIcon.svelte';
|
import ReactIcon from '@/components/icons/reactIcon.svelte';
|
||||||
import VueIcon from '@/components/icons/vueIcon.svelte';
|
import VueIcon from '@/components/icons/vueIcon.svelte';
|
||||||
import SvelteIcon from '@/components/icons/svelteIcon.svelte';
|
import SvelteIcon from '@/components/icons/svelteIcon.svelte';
|
||||||
import AngularIcon from '@/components/icons/angularIcon.svelte';
|
import AngularIcon from '@/components/icons/angularIcon.svelte';
|
||||||
|
import WebComponentIcon from './icons/webComponentIcon.svelte';
|
||||||
|
|
||||||
// Props:
|
// Props:
|
||||||
interface CopySVG {
|
interface CopySVG {
|
||||||
@ -87,7 +92,9 @@
|
|||||||
const svgUrlToCopy = getSvgUrl();
|
const svgUrlToCopy = getSvgUrl();
|
||||||
optionsOpen = false;
|
optionsOpen = false;
|
||||||
|
|
||||||
const content = await getSvgContent(svgUrlToCopy);
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
|
|
||||||
if (isInFigma) {
|
if (isInFigma) {
|
||||||
figmaCopyToClipboard(content);
|
figmaCopyToClipboard(content);
|
||||||
@ -126,9 +133,11 @@
|
|||||||
isLoading = true;
|
isLoading = true;
|
||||||
|
|
||||||
const title = svgInfo.title.split(' ').join('');
|
const title = svgInfo.title.split(' ').join('');
|
||||||
const content = await getSvgContent(svgUrlToCopy);
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
const dataComponent = { code: content, typescript: tsx, name: title };
|
const dataComponent = { code: content, typescript: tsx, name: title };
|
||||||
const { data, error } = await getReactComponentCode(dataComponent);
|
const { data, error } = await getReactCode(dataComponent);
|
||||||
|
|
||||||
if (error || !data) {
|
if (error || !data) {
|
||||||
toast.error('Failed to fetch React component', {
|
toast.error('Failed to fetch React component', {
|
||||||
@ -148,16 +157,21 @@
|
|||||||
isLoading = false;
|
isLoading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Copy as either Vue or Svelte component:
|
// Copy SVG as Vue Component:
|
||||||
const copySvgComponent = async (ts: boolean, framework: 'Vue' | 'Svelte') => {
|
const convertSvgVueComponent = async (ts: boolean) => {
|
||||||
try {
|
try {
|
||||||
const svgUrlToCopy = getSvgUrl();
|
const svgUrlToCopy = getSvgUrl();
|
||||||
|
|
||||||
optionsOpen = false;
|
optionsOpen = false;
|
||||||
|
|
||||||
const content = await getSvgContent(svgUrlToCopy);
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
|
|
||||||
const copyCode = componentTemplate(ts ? 'ts' : '', content, framework);
|
const copyCode = getVueCode({
|
||||||
|
content: content,
|
||||||
|
lang: ts ? 'ts' : 'js'
|
||||||
|
});
|
||||||
|
|
||||||
if (copyCode) {
|
if (copyCode) {
|
||||||
await clipboard(copyCode);
|
await clipboard(copyCode);
|
||||||
@ -167,12 +181,45 @@
|
|||||||
? svgInfo.category.sort().join(' - ')
|
? svgInfo.category.sort().join(' - ')
|
||||||
: svgInfo.category;
|
: svgInfo.category;
|
||||||
|
|
||||||
toast.success(`Copied as ${framework} ${ts ? 'TS' : 'JS'} component`, {
|
toast.success(`Copied as Vue ${ts ? 'TS' : 'JS'} component`, {
|
||||||
description: `${svgInfo?.title} - ${category}`
|
description: `${svgInfo?.title} - ${category}`
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error copying ${framework} component:`, err);
|
console.error(`Error copying Vue component:`, err);
|
||||||
toast.error(`Failed to copy ${framework} component`);
|
toast.error(`Failed to copy Vue component`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy SVG as Svelte Component:
|
||||||
|
const convertSvgSvelteComponent = async (ts: boolean) => {
|
||||||
|
try {
|
||||||
|
const svgUrlToCopy = getSvgUrl();
|
||||||
|
|
||||||
|
optionsOpen = false;
|
||||||
|
|
||||||
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
|
|
||||||
|
const copyCode = getSvelteCode({
|
||||||
|
content: content,
|
||||||
|
lang: ts ? 'ts' : 'js'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (copyCode) {
|
||||||
|
await clipboard(copyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
const category = Array.isArray(svgInfo?.category)
|
||||||
|
? svgInfo.category.sort().join(' - ')
|
||||||
|
: svgInfo.category;
|
||||||
|
|
||||||
|
toast.success(`Copied as Svelte ${ts ? 'TS' : 'JS'} component`, {
|
||||||
|
description: `${svgInfo?.title} - ${category}`
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error copying Svelte component:`, err);
|
||||||
|
toast.error(`Failed to copy Svelte component`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,7 +230,9 @@
|
|||||||
|
|
||||||
const title = svgInfo.title.split(' ').join('');
|
const title = svgInfo.title.split(' ').join('');
|
||||||
const svgUrlToCopy = getSvgUrl();
|
const svgUrlToCopy = getSvgUrl();
|
||||||
const content = await getSvgContent(svgUrlToCopy);
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
toast.error('Failed to fetch the SVG content', {
|
toast.error('Failed to fetch the SVG content', {
|
||||||
@ -193,7 +242,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const angularComponent = generateAngularComponent(content, title);
|
const angularComponent = getAngularCode({
|
||||||
|
componentName: title,
|
||||||
|
svgContent: content
|
||||||
|
});
|
||||||
|
|
||||||
await clipboard(angularComponent);
|
await clipboard(angularComponent);
|
||||||
|
|
||||||
toast.success(`Copied as Standalone Angular component`, {
|
toast.success(`Copied as Standalone Angular component`, {
|
||||||
@ -202,6 +255,39 @@
|
|||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Copy SVG as Standalone Angular component:
|
||||||
|
const convertSvgWebComponent = async () => {
|
||||||
|
isLoading = true;
|
||||||
|
optionsOpen = false;
|
||||||
|
|
||||||
|
const title = svgInfo.title.split(' ').join('');
|
||||||
|
const svgUrlToCopy = getSvgUrl();
|
||||||
|
const content = await getSource({
|
||||||
|
url: svgUrlToCopy
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
toast.error('Failed to fetch the SVG content', {
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
isLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const webComponentCode = getWebComponent({
|
||||||
|
name: title,
|
||||||
|
content: content
|
||||||
|
});
|
||||||
|
|
||||||
|
await clipboard(webComponentCode);
|
||||||
|
|
||||||
|
toast.success(`Copied as Web Component`, {
|
||||||
|
description: `${svgInfo.title} - ${svgInfo.category}`
|
||||||
|
});
|
||||||
|
|
||||||
|
isLoading = false;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Popover.Root open={optionsOpen} onOpenChange={(isOpen) => (optionsOpen = isOpen)}>
|
<Popover.Root open={optionsOpen} onOpenChange={(isOpen) => (optionsOpen = isOpen)}>
|
||||||
@ -218,13 +304,14 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
<Popover.Content class="flex flex-col space-y-2 p-3" sideOffset={2}>
|
<Popover.Content class="flex flex-col space-y-2 p-3" sideOffset={2}>
|
||||||
<Tabs.Root value="source" class="w-full">
|
<Tabs.Root value="source">
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Trigger value="source">Source</Tabs.Trigger>
|
<Tabs.Trigger value="source">Source</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="react">React</Tabs.Trigger>
|
<Tabs.Trigger value="react">React</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="vue">Vue</Tabs.Trigger>
|
<Tabs.Trigger value="vue">Vue</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="svelte">Svelte</Tabs.Trigger>
|
<Tabs.Trigger value="svelte">Svelte</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="angular">Angular</Tabs.Trigger>
|
<Tabs.Trigger value="angular">Angular</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="webcomponent">Web Component</Tabs.Trigger>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
<Tabs.Content value="source">
|
<Tabs.Content value="source">
|
||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
@ -266,7 +353,7 @@
|
|||||||
class={cn(buttonStyles, 'w-full rounded-md')}
|
class={cn(buttonStyles, 'w-full rounded-md')}
|
||||||
title="Copy as Svelte component"
|
title="Copy as Svelte component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => copySvgComponent(false, 'Svelte')}
|
onclick={() => convertSvgSvelteComponent(false)}
|
||||||
>
|
>
|
||||||
<SvelteIcon iconSize={18} />
|
<SvelteIcon iconSize={18} />
|
||||||
<span>Copy JS</span>
|
<span>Copy JS</span>
|
||||||
@ -276,7 +363,7 @@
|
|||||||
class={cn(buttonStyles, 'w-full rounded-md')}
|
class={cn(buttonStyles, 'w-full rounded-md')}
|
||||||
title="Copy as Svelte component"
|
title="Copy as Svelte component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => copySvgComponent(true, 'Svelte')}
|
onclick={() => convertSvgSvelteComponent(true)}
|
||||||
>
|
>
|
||||||
<SvelteIcon iconSize={18} />
|
<SvelteIcon iconSize={18} />
|
||||||
<span>Copy TS</span>
|
<span>Copy TS</span>
|
||||||
@ -289,7 +376,7 @@
|
|||||||
class={cn(buttonStyles, 'w-full rounded-md')}
|
class={cn(buttonStyles, 'w-full rounded-md')}
|
||||||
title="Copy as Vue component"
|
title="Copy as Vue component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => copySvgComponent(false, 'Vue')}
|
onclick={() => convertSvgVueComponent(false)}
|
||||||
>
|
>
|
||||||
<VueIcon iconSize={18} />
|
<VueIcon iconSize={18} />
|
||||||
<span>Copy JS</span>
|
<span>Copy JS</span>
|
||||||
@ -298,7 +385,7 @@
|
|||||||
class={cn(buttonStyles, 'w-full rounded-md')}
|
class={cn(buttonStyles, 'w-full rounded-md')}
|
||||||
title="Copy as Vue component"
|
title="Copy as Vue component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => copySvgComponent(true, 'Vue')}
|
onclick={() => convertSvgVueComponent(true)}
|
||||||
>
|
>
|
||||||
<VueIcon iconSize={18} />
|
<VueIcon iconSize={18} />
|
||||||
<span>Copy TS</span>
|
<span>Copy TS</span>
|
||||||
@ -318,6 +405,19 @@
|
|||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
|
<Tabs.Content value="webcomponent">
|
||||||
|
<section class="flex flex-col space-y-2">
|
||||||
|
<button
|
||||||
|
class={cn(buttonStyles, 'w-full rounded-md')}
|
||||||
|
title="Copy Web Component"
|
||||||
|
disabled={isLoading}
|
||||||
|
onclick={() => convertSvgWebComponent()}
|
||||||
|
>
|
||||||
|
<WebComponentIcon iconSize={18} />
|
||||||
|
<span>Copy Web Component</span>
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</Tabs.Content>
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
<div
|
<div
|
||||||
class="mt-1 flex w-full items-center text-center text-[12px] text-neutral-600 dark:text-neutral-400"
|
class="mt-1 flex w-full items-center text-center text-[12px] text-neutral-600 dark:text-neutral-400"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user