Created
April 7, 2018 15:50
-
-
Save danalloway/40402632adfb4bf5d9578210cd3dbc14 to your computer and use it in GitHub Desktop.
Revisions
-
danalloway revised this gist
Apr 7, 2018 . No changes.There are no files selected for viewing
-
danalloway created this gist
Apr 7, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,149 @@ import { h, createElement } from 'preact' import humps from 'humps' import fontawesome from '@fortawesome/fontawesome' // icons import faClipboardList from '@fortawesome/fontawesome-pro-solid/faClipboardList' import faPlus from '@fortawesome/fontawesome-pro-solid/faPlus' fontawesome.library.add(faClipboardList, faPlus) const Icon = props => { const { icon: iconArgs, mask: maskArgs, symbol, class: className } = props const icon = normalizeIconArgs(iconArgs) const classes = objectWithKey('classes', [ ...classList(props), ...className.split(' ') ]) const transform = objectWithKey( 'transform', typeof props.transform === 'string' ? fontawesome.parse.transform(props.transform) : props.transform ) const mask = objectWithKey('mask', normalizeIconArgs(maskArgs)) const renderedIcon = fontawesome.icon(icon, { ...classes, ...transform, ...mask, symbol }) const { abstract } = renderedIcon const convertCurry = convert.bind(null, createElement) const extraProps = {} Object.keys(props).forEach(key => { if (!Icon.defaultProps.hasOwnProperty(key)) extraProps[key] = props[key] }) return convertCurry(abstract[0], extraProps) } const normalizeIconArgs = icon => { if (icon === null) { return null } if (typeof icon === 'object' && icon.prefix && icon.iconName) { return icon } if (Array.isArray(icon) && icon.length === 2) { return { prefix: icon[0], iconName: icon[1] } } if (typeof icon === 'string') { return { prefix: 'fas', iconName: icon } } } const objectWithKey = (key, value) => { return (Array.isArray(value) && value.length > 0) || (!Array.isArray(value) && value) ? { [key]: value } : {} } const classList = props => { let classes = { 'fa-spin': props.spin, 'fa-pulse': props.pulse, 'fa-fw': props.fixedWidth, 'fa-border': props.border, 'fa-li': props.listItem, 'fa-flip-horizontal': props.flip === 'horizontal' || props.flip === 'both', 'fa-flip-vertical': props.flip === 'vertical' || props.flip === 'both', [`fa-${props.size}`]: props.size !== null, [`fa-rotate-${props.rotation}`]: props.rotation !== null, [`fa-pull-${props.pull}`]: props.pull !== null } return Object.keys(classes) .map(key => (classes[key] ? key : null)) .filter(key => key) } const convert = (createElement, element, extraProps = {}) => { const children = (element.children || []).map( convert.bind(null, createElement) ) const mixins = Object.keys(element.attributes || {}).reduce( (acc, key) => { const val = element.attributes[key] switch (key) { case 'class': acc.attrs['className'] = val delete element.attributes['class'] break case 'style': acc.attrs['style'] = styleToObject(val) break default: if ( key.indexOf('aria-') === 0 || key.indexOf('data-') === 0 ) { acc.attrs[key.toLowerCase()] = val } else { acc.attrs[humps.camelize(key)] = val } } return acc }, { attrs: {} } ) const { style: existingStyle = {}, ...remaining } = extraProps mixins.attrs['style'] = { ...mixins.attrs['style'], ...existingStyle } return createElement( element.tag, { ...mixins.attrs, ...remaining }, ...children ) } Icon.defaultProps = { border: false, class: '', mask: null, fixedWidth: false, flip: null, icon: null, listItem: false, pull: null, pulse: false, name: '', rotation: null, size: null, spin: false, symbol: false, transform: null } export default Icon