Templarian / MaterialDesign-React

Dist for Material Design Icons React Component for JS/TypeScript
https://materialdesignicons.com
MIT License
142 stars 20 forks source link

How to use string for path props? #26

Closed lin-zy1229 closed 5 years ago

lin-zy1229 commented 5 years ago

i'd like to use string variable for path. but failing. such like this.

<Icon path="account-off" />

How to do this in React?

Templarian commented 5 years ago

Why? But... the React component has no idea about the actual icon names. So that's not really possible.

If you wanted to use the name of the icon you could.

import { mdiAccountOff } from '@mdi/js`;

const names = {
  'account-off': mdiAccountOff
};

class MyIcon extends React.Component {
  render() {
    return <Icon path={names[this.props.name]}/>;
  }
}

export default MyIcon;
<MyIcon name="account-off"/>

The idea of @mdi/js is that it will tree shake any unused icons. If you make a list like above it will include the icons even if you don't use them. Might be useful in situations where you need a dropdown to select an icon.

lin-zy1229 commented 5 years ago

Thank you so much for fast reply, But, using 'import...' is not desirable,

Any other way to use it directly in path? e.g. <Icon path="@mdi/js/mdiAccountOff" />

please assume if you have icon name list, such like this: ["mdiAccountOff", "mdiRepeat", "mdiAccountClock", ... ]

To use this, how can I do 'import...' stuff for each one?

Any resolution?

Templarian commented 5 years ago

So the @mdi/js is what stores the icon path data. It's really just as simple as export mdiAccount = 'M...Z'; ... in a giant list.

If you have a list of icon names you need to compile the path data into your application.

import { mdiAccountOff, mdiRepeat, mdiAccountClock } from '@mdi/js';

const paths = [mdiAccountOff,   mdiRepeat,   mdiAccountClock, ... ];
const icons = ["mdiAccountOff", "mdiRepeat", "mdiAccountClock", ... ];

function getPathByName(name) {
    const index = paths.indexOf(name);
    if (index == -1) { throw `Icon not in list: ${icons.join(', ')}`; }
    return paths[index];
}

<Icon path={getPathByName('mdiAccountOff')}/>

Disclaimer: Just wrote it in the comment, didn't run it.

Templarian commented 5 years ago

If you want to lazy load SVG files you can use @mdi/svg and get the path data out of those files. Doesn't sound like what you're trying to do though.

lin-zy1229 commented 5 years ago

but, the most thing I dislike and even impossible, is this: import { mdiAccountOff, mdiRepeat, mdiAccountClock } from '@mdi/js';

because i can't know what icon name will come from API.

you understood my concern?

Templarian commented 5 years ago

I get what you mean now. Yeah, we've gotten asked this a couple times.

You're going to need to copy npm install @mdi/svg and copy it to your assets folder. Then you can create a service to request the ${fileName}.svg. Then use some very basic regex to get the path data.

var pathData = "<svg><path d="MstuffZ"/></svg>".match(/d="([^"]+)"/)[1];
Templarian commented 5 years ago

Ideally we provide a nice package for this... I'll create an issue for this. Where we basically just publish individual json files with the path data/name.

lin-zy1229 commented 5 years ago

hmm, this icons package is good, but have difficulty to use. I am not sure what you mean exactly. and it seems too complicated. However, thank you for your kindness.

Templarian commented 5 years ago

http://templarian.com/2018/04/13/scripting-with-nodejs-and-material-design-icons/

For now you could loop the files in a script and write them to a folder.

meta.map(icon => {
  fs.writeFile(`${icon.name}.json`, `{"name": "${icon.name}", "path": "${icon.path}"}`)
});
Templarian commented 5 years ago

I'll try and work on a documentation page that explains this. It has come up a few times. We'll track it over here:

https://github.com/Templarian/MaterialDesign-Site/issues/107