Skip to content

Commit

Permalink
feat: use icon-loader from ui packages
Browse files Browse the repository at this point in the history
  • Loading branch information
oktaysenkan committed Oct 5, 2024
1 parent 1f4b78a commit c2a53ab
Show file tree
Hide file tree
Showing 24 changed files with 88 additions and 243 deletions.
1 change: 1 addition & 0 deletions apps/react-native-app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function App() {
<Iconify name="feather:activity" />
<Iconify name="logos:active-campaign" size={30} />
<Iconify name="logos:apache-superset-icon" />
<Iconify name="invalid:icon" />
</View>
);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/rspack-react/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "./App.css";
function App() {
return (
<div className="App">
<Iconify name="mdi:home" />
<Iconify name="mdi:home" size={32} />
<Iconify name="invalid:icon" />
</div>
);
Expand Down
5 changes: 0 additions & 5 deletions packages/icon-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./constants": {
"import": "./dist/constants.mjs",
"require": "./dist/constants.js",
"types": "./dist/constants.d.mts"
}
},
"publishConfig": {
Expand Down
43 changes: 26 additions & 17 deletions packages/icon-loader/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import type { Icon } from "@oktaytest/core";
import { Icon } from "@oktaytest/core";
import { parseSync, stringify } from "svgson";

// @ts-ignore
import _icons from "oktay";

const icons = _icons as Record<string, Icon>;

export const fallbackIcon: Icon = {
svg: '<svg width="32" height="32" viewBox="0 0 24 24" > <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10m0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16m-1-5h2v2h-2zm2-1.645V14h-2v-1.5a1 1 0 0 1 1-1a1.5 1.5 0 1 0-1.471-1.794l-1.962-.393A3.501 3.501 0 1 1 13 13.355" /> </svg>',
width: 32,
height: 32,
};

export type IconProps = {
export type IconifyProps = {
name: string;
size?: number;
color?: string;
};

export type GetIconDetailsOptions = {
icon: Icon;
props: IconProps;
props: IconifyProps;
};

const loadIcon = (iconName: string) => {
export const fallbackIcon: Icon = {
svg: '<svg width="32" height="32" viewBox="0 0 24 24" > <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10m0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16m-1-5h2v2h-2zm2-1.645V14h-2v-1.5a1 1 0 0 1 1-1a1.5 1.5 0 1 0-1.471-1.794l-1.962-.393A3.501 3.501 0 1 1 13 13.355" /> </svg>',
width: 32,
height: 32,
};

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

if (icon) return icon;
Expand All @@ -35,8 +30,11 @@ const loadIcon = (iconName: string) => {
return fallbackIcon;
};

export const getIconDetails = (props: IconProps) => {
const icon = loadIcon(props.name);
export const getIconDetails = (
props: IconifyProps,
icons: Record<string, Icon>
) => {
const icon = loadIcon(props.name, icons);

const parsed = parseSync(icon.svg);

Expand All @@ -58,8 +56,19 @@ export const getIconDetails = (props: IconProps) => {
height: `${height}px`,
};

parsed.attributes = attributes;

icon.svg = icon.svg
.replace(/width="([^"]+)"/, `width="${width}"`)
.replace(/height="([^"]+)"/, `height="${height}"`);

if (props.color) {
icon.svg = icon.svg.replace(/fill="([^"]+)"/, `fill="${props.color}"`);
}

return {
innerHtml,
attributes,
svg: icon.svg,
};
};
2 changes: 0 additions & 2 deletions packages/icon-loader/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { defineConfig, Options } from "tsup";

export default defineConfig((options: Options) => ({
entry: ["src/index.ts"],
clean: true,
format: ["cjs", "esm"],
external: ["oktay"],
dts: true,
...options,
}));
9 changes: 5 additions & 4 deletions packages/native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./iconify": {
"import": "./dist/iconify.mjs",
"require": "./dist/iconify.js"
"./Iconify": {
"import": "./dist/Iconify.mjs",
"require": "./dist/Iconify.js"
}
},
"scripts": {
Expand All @@ -35,7 +35,8 @@
},
"dependencies": {
"html-react-parser": "^5.1.16",
"@oktaytest/core": "*"
"@oktaytest/core": "*",
"@oktaytest/icon-loader": "*"
},
"peerDependencies": {
"react": ">=18.2.0",
Expand Down
5 changes: 0 additions & 5 deletions packages/native/src/constants.ts

This file was deleted.

70 changes: 22 additions & 48 deletions packages/native/src/iconify.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React from "react";

import { IconifyProps, RuntimeIcon, RuntimeIconifyProps } from "./types";
import { setAttributes } from "./utils";
import { fallbackIcon } from "./constants";
import { getIconDetails, IconifyProps } from "@oktaytest/icon-loader";

const isReactNative = async () => {
try {
Expand All @@ -16,59 +13,34 @@ const isReactNative = async () => {
}
};

const getIcon = (iconName: string) =>
new Promise<RuntimeIcon>(async (resolve, reject) => {
try {
// todo: add error handling
// @ts-ignore
const iconsImport = await import("oktay");

const icons = iconsImport.default ?? iconsImport;

let icon = icons[iconName];

if (!icon) {
console.warn(
`[Iconify] The icon "${iconName}" is missing from the configuration. To resolve this, ensure it is added to the 'icons' array within the Iconify plugin's configuration.`
);

icon = fallbackIcon;
}

resolve(icon);
} catch (error) {
reject(error);
}
});

const nativeIcon = async (props: RuntimeIconifyProps) => {
const nativeIcon = async (props: ReturnType<typeof getIconDetails>) => {
const { SvgXml } = require("react-native-svg");

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

const webIcon = async (props: RuntimeIconifyProps) => {
// @ts-ignore
const parse = await import("html-react-parser");

return parse.default(props.icon.svg);
const webIcon = async (props: ReturnType<typeof getIconDetails>) => {
return (
<svg
{...props.attributes}
dangerouslySetInnerHTML={{ __html: props.innerHtml }}
/>
);
};

const getComponent = async (props: RuntimeIconifyProps) => {
const formatted = setAttributes(props);

const getComponent = async (props: ReturnType<typeof getIconDetails>) => {
const isNative = await isReactNative();

if (isNative) return nativeIcon(formatted);
if (isNative) return nativeIcon(props);

return webIcon(formatted);
return webIcon(props);
};

export const Iconify = (props: IconifyProps) => {
Expand All @@ -77,12 +49,14 @@ export const Iconify = (props: IconifyProps) => {
);

const renderIcon = async () => {
const icon = await getIcon(props.name);
// @ts-ignore
const iconsImport = await import("oktay");

const icons = iconsImport.default ?? iconsImport;

const details = getIconDetails(props, icons);

const component = await getComponent({
...props,
icon,
});
const component = await getComponent(details);

setComponent(component);
};
Expand Down
1 change: 1 addition & 0 deletions packages/native/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Iconify } from "./Iconify";
2 changes: 0 additions & 2 deletions packages/native/src/index.tsx

This file was deleted.

15 changes: 0 additions & 15 deletions packages/native/src/types.ts

This file was deleted.

30 changes: 0 additions & 30 deletions packages/native/src/utils.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/native/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineConfig, Options } from "tsup";

export default defineConfig((options: Options) => ({
entry: ["src/index.tsx", "src/iconify.tsx"],
entry: ["src/index.ts", "src/Iconify.tsx"],
banner: {
js: "'use client'",
},
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/iconify.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";
import { getIconDetails } from "@oktaytest/icon-loader";
import { getIconDetails, IconifyProps } from "@oktaytest/icon-loader";

import { IconifyProps } from "./types";
// @ts-ignore
import icons from "oktay";

export const Iconify = (props: IconifyProps) => {
const details = getIconDetails(props);
const details = getIconDetails(props, icons);

return (
<svg
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { Iconify } from "./iconify";
export { type IconifyProps } from "./types";
export { type IconifyProps } from "@oktaytest/icon-loader";
5 changes: 0 additions & 5 deletions packages/react/src/types.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"@oktaytest/vite": "*"
},
"dependencies": {
"svgson": "^5.3.1"
"svgson": "^5.3.1",
"@oktaytest/icon-loader": "*"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
45 changes: 10 additions & 35 deletions packages/svelte/src/lib/Iconify.svelte
Original file line number Diff line number Diff line change
@@ -1,45 +1,20 @@
<script lang="ts">
import { parseSync, stringify } from "svgson";
import { fallbackIcon } from "@oktaytest/core/constants";
// @ts-ignore
import icons from "oktay";
import type { Icon } from "@oktaytest/core";
import { getIconDetails } from "@oktaytest/icon-loader";
export let name: string;
export let size: number | undefined = undefined;
export let color: string | undefined = undefined;
$: icon = icons[name] || fallbackIcon;
if (!icons[name]) {
console.warn(
`[Iconify] The icon "${name}" is missing from the configuration. To resolve this, ensure it is added to the 'icons' array within the Iconify plugin's configuration.`
);
}
$: parsed = parseSync(icon.svg);
$: children = parsed.children.map((child) => {
if (child.name !== "path" || !child.attributes.fill || !color) return child;
child.attributes.fill = color;
return child;
});
$: html = stringify(children as any);
$: ratio = icon.width / icon.height;
$: height = size ? Number(size) : icon.height;
$: width = size ? Number(size) * ratio : icon.width;
// @ts-ignore
import icons from "oktay";
$: attributes = {
...parsed.attributes,
width,
height,
};
$: details = getIconDetails(
{ name, color, size },
icons as Record<string, Icon>
);
</script>

<svg {...attributes}>
{@html html}
<svg {...details.attributes}>
{@html details.innerHtml}
</svg>
Loading

0 comments on commit c2a53ab

Please sign in to comment.