Open ElixirMike opened 4 years ago
Yeah, we need to document this process and how it should work. It unfortunately requires a server-side component if one wants to use all 5k icons or it can become a performance issue for pages with lots of icons.
Do you want to provide all ~5k icons in the icon picker or a subset? We/community need to make some demos of both examples.
I was just looking to create a subset...we've picked out about 800 icons to use. For now, what I did was create a custom object with array of icons, including a tag, name of icon and path.
Like this where I insert the 800 icons. var myicons = [{tag:'phones', name='mdiphone', path: "....full svg path", {}, {}, etc ]
It's lazy loaded on icon picker page..but when a user selects the icon, I simply store the svg path in db/cache.
Then, in the rest of my application, I can simply use the svgpath and display, so it's very fast.
It would be super helpeful to have someway of picking icons you want and then generating this type of object which can be used to display them on icon selection page.
I am trying to use dynamic import from this article But in this article only can import whole file, refer to @mdi/js/mdi.js all icons are stored to this single file. Is there anyway to dynamically import specific icon from this file?
@AmirHosseinKarimi You could use the @mdi/svg
package and fetch the individual SVG's by their icon name in a wrapper <LazyIcon name={iconName}>
. Since <Icon>
takes any path data, you could regex for the path data out of the SVG request and put it into <Icon>
.
const data = body.match(/d="([^"]+)"/)[1];
Obviously write a light cache layer into your component so you don't make unnecessary requests for the path data.
The @mdi/js
package is only really aimed at compile time for tree-shaking. The @mdi/svg
also contains the meta.json
if you need to generate a list of icons (recommend to trim down this file as it could be heavy for use on the web).
Sorry I did not understand
@AmirHosseinKarimi https://github.com/Templarian/MaterialDesign-SVG contains individual SVG files you can deploy. These could be requested by their name in a wrapping component. You only need the SVG path data aka <path d="this content"/>
so that regex will get that (made a typo and edited it above with the correct regex).
So I have created a package (materialdesign-js) to dynamically load an icon. The description is clear about how this package working. This package is a dependency of another package, which I will create for React that automatically load the icon.
Currently if you need a dynamically load icon, you can create the following component:
import React from "react";
import { Icon as MDIcon } from "@mdi/react";
class Icon extends React.Component {
render() {
let icon = require(`materialdesign-js/icons/${this.props.icon}`).default;
if (!icon) {
throw Error(`Could not find materialdesign-js/icons/${icon}`);
}
return <MDIcon path={icon} />;
}
}
export default Icon;
and use like this:
import Icon from "./Icon";
...
<Icon icon="mdiAccount" />
If this package is helped you please give a star:
Also if you like to contribute, just look at the MaterialDesign-JS repository.
We recommend using a peer dependency for @mdi/js
. Referencing a specific version usually doesn't work out in the long run. Learn more:
Yours will be more lightweight than the @mdi/svg
approach, but similar idea loading individual glyphs.
We will work to open source the IndexedDB solution as it will be more ideal performance wise. Also makes it easier in cases where one may need to search all icons in a list.
Good, I create this package because I need dynamic load icons in my current project. So always there is an better idea. I am waiting for IndexedDB solution to try it.
Finally I have find a way which can use dynamic load MDI and also do not decrease the performance of app in development and runtime. Just look at this gist: https://gist.github.com/AmirHosseinKarimi/801931665a0845ccc25ed486431abf72
https://gist.github.com/AmirHosseinKarimi/801931665a0845ccc25ed486431abf72
You're requiring the entire @mdi/js library here, so any development or production build of the app would have to include the whole package (around 2.3MB).
@craigrileyuk Yea you're right. It's a little bit old. But I think the dynamic load example in the MaterialDesign-JS repository readme is correct and working.
maybe a little late but this works for me fine:
import React, { useEffect, useState } from "react";
import { Icon as MDIcon } from "@mdi/react";
type props = {
icon: string,
size: number,
}
const LazyIcon = (props: props) => {
const [iconPath, setIconPath] = useState<string>('');
useEffect(() => {
import('@mdi/js').then((icons:any) => {
if (icons[props.icon]) {
const icon = icons[props.icon];
setIconPath(icon.toString());
}
});
}, [props.icon]);
return (<>{iconPath !== '' ?
<MDIcon path={iconPath} size={props.size}></MDIcon>
: null
}</>);
}
export { LazyIcon };
So, in my app, I want to provide an Icon picker...let the user choose their icon. Once saved, I would use it on other pages in the app.
How do I dynamically import this specific icon on those pages?