175 lines
4.5 KiB
JavaScript
Executable File
175 lines
4.5 KiB
JavaScript
Executable File
import { parse as faParse, icon as faIcon } from '@fortawesome/fontawesome-svg-core';
|
|
import { h, defineComponent } from 'vue'; // import { IconDefinition } from '@fortawesome/fontawesome-common-types';
|
|
|
|
import { camelize } from '../../../utils/helpers';
|
|
import { mergeClasses } from '../../../utils/mergeClasses';
|
|
import { BIcon } from '../../icon';
|
|
import { BIconPropsDefinition } from '../../icon/BIcon'; //replace iconDefinition with actual definition from fontawesome. causing some typescript issues at the moment
|
|
|
|
function objectWithKey(key, value) {
|
|
return Array.isArray(value) && value.length > 0 || !Array.isArray(value) && value ? {
|
|
[key]: value
|
|
} : {};
|
|
} // eslint-disable-next-line
|
|
|
|
|
|
function classList(props) {
|
|
const classes = {
|
|
'fa-spin': props.spin,
|
|
'fa-pulse': props.pulse,
|
|
'fa-fw': props.fixedWidth,
|
|
'fa-border': props.border,
|
|
'fa-li': props.listItem,
|
|
'fa-inverse': props.inverse,
|
|
'fa-flip-horizontal': props.flip === 'horizontal' || props.flip === 'both',
|
|
'fa-flip-vertical': props.flip === 'vertical' || props.flip === 'both',
|
|
[`fa-${props.size}`]: props.size !== undefined,
|
|
[`fa-rotate-${props.rotation}`]: props.rotation !== undefined,
|
|
[`fa-pull-${props.pull}`]: props.pull !== undefined,
|
|
'fa-swap-opacity': props.swapOpacity
|
|
};
|
|
return Object.keys(classes).map(key => classes[key] ? key : null).filter(key => key);
|
|
}
|
|
|
|
function styleToObject(style) {
|
|
return style.split(';').map(s => s.trim()).filter(s => s).reduce((acc, pair) => {
|
|
const i = pair.indexOf(':');
|
|
const prop = camelize(pair.slice(0, i));
|
|
const value = pair.slice(i + 1).trim();
|
|
acc[prop] = value;
|
|
return acc;
|
|
}, {}); // eslint-disable-line
|
|
}
|
|
|
|
function classToObject(cls) {
|
|
return cls.split(/\s+/).reduce((acc, c) => {
|
|
acc[c] = true;
|
|
return acc;
|
|
}, {}); // eslint-disable-line
|
|
} // eslint-disable-next-line
|
|
|
|
|
|
function 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
|
|
};
|
|
}
|
|
} // eslint-disable-next-line
|
|
|
|
|
|
function convert(element, attrs = {}) {
|
|
if (typeof element === 'string') {
|
|
return h(element);
|
|
}
|
|
|
|
const mixins = Object.keys(element.attributes || {}).reduce((acc, key) => {
|
|
const val = element.attributes[key];
|
|
|
|
switch (key) {
|
|
case 'class':
|
|
acc['class'] = classToObject(val);
|
|
break;
|
|
|
|
case 'style':
|
|
acc['style'] = styleToObject(val);
|
|
break;
|
|
|
|
default:
|
|
acc[key] = val;
|
|
}
|
|
|
|
return acc;
|
|
}, {
|
|
class: {},
|
|
style: {}
|
|
} // eslint-disable-line
|
|
);
|
|
const {
|
|
class: dClass = {},
|
|
style: dStyle = {},
|
|
...remainingData
|
|
} = attrs;
|
|
const {
|
|
class: mClass = {},
|
|
style: mStyle = {},
|
|
...mRemainingData
|
|
} = mixins;
|
|
return h(element.tag, { ...attrs,
|
|
class: mergeClasses(mClass, dClass),
|
|
style: { ...mStyle,
|
|
...dStyle
|
|
},
|
|
...mRemainingData,
|
|
...remainingData
|
|
}, (element.children || []).map(convert));
|
|
} // eslint-disable-next-line
|
|
|
|
|
|
function useFontAwesomeIconComponent_(iconArgs) {
|
|
return function FontAwesomeIcon(_, {
|
|
attrs
|
|
}) {
|
|
const {
|
|
mask: maskArgs,
|
|
symbol,
|
|
title
|
|
} = attrs; // eslint-disable-line
|
|
|
|
const icon = normalizeIconArgs(iconArgs);
|
|
const classes = objectWithKey('classes', classList(attrs));
|
|
const transform = objectWithKey('transform', typeof attrs.transform === 'string' ? faParse.transform(attrs.transform) : attrs.transform);
|
|
const mask = objectWithKey('mask', normalizeIconArgs(maskArgs));
|
|
const {
|
|
abstract
|
|
} = faIcon(icon, { ...classes,
|
|
...transform,
|
|
...mask,
|
|
symbol,
|
|
title
|
|
});
|
|
return convert(abstract[0], attrs);
|
|
};
|
|
}
|
|
|
|
const SIZE_MAP = {
|
|
'is-small': '',
|
|
'': '',
|
|
'is-medium': 'fa-lg',
|
|
'is-large': 'fa-2x'
|
|
}; // eslint-disable-next-line
|
|
|
|
export function useFontAwesomeIconComponent(name, iconDefinition) {
|
|
const icon = useFontAwesomeIconComponent_(iconDefinition);
|
|
return defineComponent({
|
|
props: { ...BIconPropsDefinition,
|
|
iconClass: {
|
|
type: String
|
|
}
|
|
},
|
|
|
|
setup(props) {
|
|
return () => h(BIcon, props, () => h(icon, {
|
|
class: [props.iconClass, SIZE_MAP[props.size]]
|
|
}));
|
|
}
|
|
|
|
}); // eslint-disable-line
|
|
}
|
|
//# sourceMappingURL=useFontAwesomeIconComponent.js.map
|