react-fontawesome-list
Version:
The fontawesome5 icon list component
136 lines (124 loc) • 4.32 kB
JavaScript
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import '../styles/index.less';
import Icon from './Icon';
import icons from '../libs/fontawesome-5.2.0/metadata/icons.json';
class Icons extends Component {
static propTypes = {
onClick: PropTypes.func,
search: PropTypes.bool,
grid: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
icons: PropTypes.array,
icon: PropTypes.object,
selected: PropTypes.bool,
style: PropTypes.object,
iconStyle: PropTypes.object,
}
static defaultProps = {
search: false,
grid: 4,
icons: [],
icon: null,
selected: false,
style: { width: '100%', height: '100%' },
iconStyle: {},
}
state = {
icons: this.props.icons,
icon: this.props.icon,
length: this.props.icons.length,
}
componentWillMount() {
const searchIcons = this.search();
this.setState({
...searchIcons,
});
}
getPrefix = (style) => {
let prefix = 'fas';
if (style === 'brands') {
prefix = 'fab';
} else if (style === 'regular') {
prefix = 'far';
}
return prefix;
}
getIcons = (textSearch) => {
const lowerCase = textSearch.toLowerCase();
const filteredIcons = Object.keys(icons)
.filter(icon => icon.includes(lowerCase) || icons[icon].search.terms.some(term => term.includes(lowerCase)))
.map(icon => ({ [icon]: icons[icon] }));
return {
icons: filteredIcons,
length: filteredIcons.length,
};
}
search = (textSearch) => {
const filteredIcons = this.getIcons(textSearch || '');
this.setState({
...filteredIcons,
});
return filteredIcons;
}
click = (icon) => {
const { onClick } = this.props;
this.setState({
icon,
});
if (onClick) {
const name = Object.keys(icon)[0];
const prefix = this.getPrefix(icon[name].styles[0]);
const { unicode } = icon[name];
const selectedIcon = {
name,
prefix,
unicode,
};
this.setState({
icon: selectedIcon,
});
onClick(selectedIcon);
}
}
render() {
const { search, grid, style, iconStyle } = this.props;
const newIconStyle = {
...iconStyle,
width: `${100 / grid}%`,
};
return (
<div style={style}>
{
search ? (
<div className="rfl-header">
<input placeholder={`Search ${this.state.length} icons for...`} onChange={(e) => { this.search(e.target.value); }} />
</div>
) : null
}
<div className="rfl-body">
{
this.state.icons.map((icon) => {
const name = Object.keys(icon)[0];
const metadata = icon[name];
const prefix = this.getPrefix(metadata.styles[0]);
return (
<div className={`rfl-icon ${this.props.selected && this.state.icon && this.state.icon.name === name ? 'selected' : ''}`} style={newIconStyle} onClick={this.click.bind(this, icon)} key={name}>
<div className="rfl-icon-top">
<Icon name={name} size={3} prefix={prefix} />
</div>
<div className="rfl-icon-bottom">
{name}
</div>
</div>
);
})
}
</div>
</div>
);
}
}
export default Icons;