import Vue from 'vue' import { Component, Prop } from 'vue-property-decorator' import { IconDefinition, library } from "@fortawesome/fontawesome-svg-core" import { Dictionary } from "../../utils"; import { faBullhorn, faCheck, faCheckDouble, faChevronCircleUp, faChevronDown, faChevronUp, faClock, faCog, faExclamationTriangle, faHistory, faHourglassHalf, faInfoCircle, faMapMarkerAlt, faMoon, faQuestionCircle, faQuestionSquare, faSearch, faSign, faStar, faSync, faTimes, faTrashAlt } from "@fortawesome/pro-light-svg-icons"; import { faClock as faClockBold, faCodeCommit, faMinus, faPlus, faSpinnerThird } from "@fortawesome/pro-regular-svg-icons"; import { faExclamationTriangle as faSolidExclamationTriangle, faWalking } from "@fortawesome/pro-solid-svg-icons"; import { fac } from "../../icons"; import { FontAwesomeIcon, FontAwesomeLayers, FontAwesomeLayersText } from "@fortawesome/vue-fontawesome"; type IconDescription = { icon: IconDefinition, [prop: string]: any } type SimpleIcon = { type: 'simple', } & IconDescription; type StackedIcon = { type: 'stacked', icons: IconDescription[], } export type Icon = SimpleIcon | StackedIcon; const simple = (icon: IconDefinition, props: any = {}): SimpleIcon => ({ icon, ...props, type: "simple" }); const stack = (icons: IconDescription[]): StackedIcon => ({ type: "stacked", icons }); const lineTypeIcons = Object .values(fac) .map<[string, Icon]>(icon => [`line-${ icon.iconName }`, simple(icon)]) .reduce((acc, [icon, definition]) => ({ ...acc, [icon]: definition }), {}) const messageTypeIcons: Dictionary = { 'message-breakdown': simple(faExclamationTriangle), 'message-info': simple(faInfoCircle), 'message-unknown': simple(faQuestionCircle), }; const definitions = { 'favourite': simple(faStar), 'unknown': simple(faQuestionSquare), 'add': simple(faCheck), 'add-all': simple(faCheckDouble), 'remove-stop': simple(faTimes), 'delete': simple(faTrashAlt), 'messages': simple(faBullhorn), 'timetable': simple(faClock), 'settings': simple(faCog), 'refresh': simple(faSync), 'chevron-down': simple(faChevronDown), 'chevron-up': simple(faChevronUp), 'search': simple(faSearch), 'info': simple(faInfoCircle), 'warning': simple(faExclamationTriangle), 'night': simple(faMoon), 'fast': simple(faWalking), 'track': simple(faCodeCommit), 'info-hide': simple(faChevronCircleUp), 'map': simple(faMapMarkerAlt), 'stop': simple(faSign), 'spinner': simple(faSpinnerThird, { spin: true }), 'increment': simple(faPlus, { "fixed-width": true }), 'decrement': simple(faMinus, { "fixed-width": true }), 'relative-time': simple(faHourglassHalf), 'departure-warning': stack([ { icon: faClockBold }, { icon: faSolidExclamationTriangle, transform: "shrink-5 down-4 right-6" } ]), 'close': simple(faTimes), 'history': simple(faHistory), ...lineTypeIcons, ...messageTypeIcons, }; export type PredefinedIcon = keyof typeof definitions; const extractAllIcons = (icons: Icon[]) => icons.map(icon => { switch (icon.type) { case "simple": return [icon.icon]; case "stacked": return icon.icons.map(stacked => stacked.icon); } }).reduce((acc, cur) => [...acc, ...cur]); library.add(...extractAllIcons(Object.values(definitions))); @Component({ template: require('../../../components/ui/icon.html'), components: { fa: FontAwesomeIcon, faLayers: FontAwesomeLayers, faText: FontAwesomeLayersText, } }) export class UiIcon extends Vue { @Prop({ type: [String, Object], validator: value => typeof value === "object" || Object.keys(definitions).includes(value), required: true, }) icon: PredefinedIcon | IconDefinition; get definition(): Icon { return typeof this.icon === "string" ? definitions[this.icon] || definitions['unknown'] : { icon: this.icon as IconDefinition, type: "simple" }; } get attrs() { return { ...this.definition, ...this.$attrs }; } get type() { return this.definition.type; } } Vue.component('UiIcon', UiIcon);