Skip to content

Commit

Permalink
Merge pull request #46 from oktaysenkan/feat/load-sync
Browse files Browse the repository at this point in the history
feat: load icons synchronously
  • Loading branch information
oktaysenkan authored Nov 5, 2024
2 parents 466bb80 + bf84d7e commit d76d88c
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 127 deletions.
21 changes: 21 additions & 0 deletions .changeset/gentle-squids-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"@monicon/icon-loader": patch
"@monicon/native": patch
"@monicon/svelte": patch
"@monicon/react": patch
"@monicon/qwik": patch
"@monicon/vue": patch
"@monicon/qwik-app": patch
"@monicon/babel-plugin": patch
"@monicon/core": patch
"@monicon/esbuild": patch
"@monicon/metro": patch
"@monicon/nuxt": patch
"@monicon/rollup": patch
"@monicon/rspack": patch
"@monicon/typescript-config": patch
"@monicon/vite": patch
"@monicon/webpack": patch
---

load icons synchronously
23 changes: 5 additions & 18 deletions packages/icon-loader/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Icon } from "@monicon/core";
import { parseSync, stringify } from "svgson";
// @ts-ignore
import icons from "@monicon/runtime";

export type MoniconProps = {
name: string;
Expand All @@ -20,22 +22,7 @@ export const fallbackIcon: Icon = {
height: 32,
};

const importIcons = async () =>
new Promise<Record<string, Icon> | null>(async (resolve) => {
try {
// @ts-ignore
const iconsImport = await import("@monicon/runtime");
const icons = iconsImport.default ?? iconsImport;

return resolve(icons);
} catch (error) {
return resolve(null);
}
});

const loadIcon = async (iconName: string) => {
const icons = await importIcons();

const loadIcon = (iconName: string) => {
const icon = icons?.[iconName];

if (icon) return icon;
Expand All @@ -47,8 +34,8 @@ const loadIcon = async (iconName: string) => {
return fallbackIcon;
};

export const getIconDetails = async (props: MoniconProps) => {
const loadedIcon = await loadIcon(props.name);
export const getIconDetails = (props: MoniconProps) => {
const loadedIcon = loadIcon(props.name);

const icon = { ...loadedIcon };

Expand Down
1 change: 1 addition & 0 deletions packages/icon-loader/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default defineConfig((options: Options) => ({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
external: ["@monicon/runtime"],
...options,
}));
45 changes: 18 additions & 27 deletions packages/native/src/Monicon.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,25 @@ import React from "react";
import { getIconDetails, MoniconProps } from "@monicon/icon-loader";
import { SvgXml } from "react-native-svg";

export const Monicon = React.memo((props: MoniconProps) => {
const [Component, setComponent] = React.useState<React.ReactNode | null>(
null
export const Monicon = (props: MoniconProps) => {
const details = React.useMemo(
() =>
getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
}),
[props.name, props.size, props.color, props.strokeWidth]
);

const loadComponent = React.useCallback(async () => {
const details = await getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});

setComponent(
<SvgXml
{...details}
xml={details.svg}
width={details.attributes.width}
height={details.attributes.height}
/>
);
}, [props.name, props.size, props.color, props.strokeWidth]);

React.useEffect(() => {
loadComponent();
}, [loadComponent]);

return Component;
});
return (
<SvgXml
xml={details.svg}
width={details.attributes.width}
height={details.attributes.height}
/>
);
};

export default Monicon;
42 changes: 17 additions & 25 deletions packages/native/src/Monicon.web.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import React from "react";
import { getIconDetails, MoniconProps } from "@monicon/icon-loader";

export const Monicon = React.memo((props: MoniconProps) => {
const [Component, setComponent] = React.useState<React.ReactNode | null>(
null
export const Monicon = (props: MoniconProps) => {
const details = React.useMemo(
() =>
getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
}),
[props.name, props.size, props.color, props.strokeWidth]
);

const loadComponent = React.useCallback(async () => {
const details = await getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});

setComponent(
<svg
{...details.attributes}
dangerouslySetInnerHTML={{ __html: details.innerHtml }}
/>
);
}, [props.name, props.size, props.color, props.strokeWidth]);

React.useEffect(() => {
loadComponent();
}, [loadComponent]);

return Component;
});
return (
<svg
{...details.attributes}
dangerouslySetInnerHTML={{ __html: details.innerHtml }}
/>
);
};

export default Monicon;
31 changes: 7 additions & 24 deletions packages/qwik/src/components/monicon/monicon.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
import { component$, useResource$, Resource } from "@builder.io/qwik";
import { component$ } from "@builder.io/qwik";
import { getIconDetails, MoniconProps } from "@monicon/icon-loader";

export const Monicon = component$((props: MoniconProps) => {
const iconResource = useResource$(async ({ track }) => {
track(() => props.name);
track(() => props.size);
track(() => props.color);
track(() => props.strokeWidth);

const details = await getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});

return details;
const details = getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});

return (
<Resource
value={iconResource}
onResolved={(details) => (
<svg
{...details.attributes}
dangerouslySetInnerHTML={details.innerHtml}
/>
)}
/>
<svg {...details.attributes} dangerouslySetInnerHTML={details.innerHtml} />
);
});

Expand Down
38 changes: 15 additions & 23 deletions packages/react/src/Monicon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@ import React from "react";
import { getIconDetails, MoniconProps } from "@monicon/icon-loader";

export const Monicon = (props: MoniconProps) => {
const [Component, setComponent] = React.useState<React.ReactElement | null>(
null
const details = React.useMemo(
() =>
getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
}),
[props.name, props.size, props.color, props.strokeWidth]
);

const loadComponent = React.useCallback(async () => {
const details = await getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});

setComponent(
<svg
{...details.attributes}
dangerouslySetInnerHTML={{ __html: details.innerHtml }}
/>
);
}, [props.name, props.size, props.color, props.strokeWidth]);

React.useEffect(() => {
loadComponent();
}, [loadComponent]);

return Component;
return (
<svg
{...details.attributes}
dangerouslySetInnerHTML={{ __html: details.innerHtml }}
/>
);
};

export default Monicon;
8 changes: 1 addition & 7 deletions packages/svelte/src/lib/Monicon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@
export let color: MoniconProps["color"] = undefined;
export let strokeWidth: MoniconProps["strokeWidth"] = undefined;
let details: IconDetails | null = null;
const loadIcons = async () => {
details = await getIconDetails({ name, color, size, strokeWidth });
};
$: $$props, loadIcons();
$: details = getIconDetails({ name, color, size, strokeWidth });
</script>

{#if details}
Expand Down
5 changes: 2 additions & 3 deletions packages/vue/src/monicon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ const props = defineProps<MoniconProps>();
const details = ref<IconDetails | null>(null);
const loadIcons = async () => {
details.value = await getIconDetails({
details.value = getIconDetails({
name: props.name,
size: props.size,
color: props.color,
strokeWidth: props.strokeWidth,
});
};
watch(props, loadIcons);
onMounted(loadIcons);
watch(props, loadIcons, { immediate: true });
</script>

<template>
Expand Down

0 comments on commit d76d88c

Please sign in to comment.