UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

230 lines (193 loc) 5.74 kB
import { h, computed, getCurrentInstance } from 'vue' import useSize, { useSizeProps } from '../../composables/private/use-size.js' import { createComponent } from '../../utils/private/create.js' import { hSlot, hMergeSlot } from '../../utils/private/render.js' const defaultViewBox = '0 0 24 24' const sameFn = i => i const ionFn = i => `ionicons ${ i }` const libMap = { 'mdi-': i => `mdi ${ i }`, 'icon-': sameFn, // fontawesome equiv 'bt-': i => `bt ${ i }`, 'eva-': i => `eva ${ i }`, 'ion-md': ionFn, 'ion-ios': ionFn, 'ion-logo': ionFn, 'iconfont ': sameFn, 'ti-': i => `themify-icon ${ i }`, 'bi-': i => `bootstrap-icons ${ i }` } const matMap = { o_: '-outlined', r_: '-round', s_: '-sharp' } const symMap = { sym_o_: '-outlined', sym_r_: '-rounded', sym_s_: '-sharp' } const libRE = new RegExp('^(' + Object.keys(libMap).join('|') + ')') const matRE = new RegExp('^(' + Object.keys(matMap).join('|') + ')') const symRE = new RegExp('^(' + Object.keys(symMap).join('|') + ')') const mRE = /^[Mm]\s?[-+]?\.?\d/ const imgRE = /^img:/ const svgUseRE = /^svguse:/ const ionRE = /^ion-/ const faRE = /^(fa-(solid|regular|light|brands|duotone|thin)|[lf]a[srlbdk]?) / export default createComponent({ name: 'QIcon', props: { ...useSizeProps, tag: { type: String, default: 'i' }, name: String, color: String, left: Boolean, right: Boolean }, setup (props, { slots }) { const { proxy: { $q } } = getCurrentInstance() const sizeStyle = useSize(props) const classes = computed(() => 'q-icon' + (props.left === true ? ' on-left' : '') // TODO Qv3: drop this + (props.right === true ? ' on-right' : '') + (props.color !== void 0 ? ` text-${ props.color }` : '') ) const type = computed(() => { let cls let icon = props.name if (icon === 'none' || !icon) { return { none: true } } if ($q.iconMapFn !== null) { const res = $q.iconMapFn(icon) if (res !== void 0) { if (res.icon !== void 0) { icon = res.icon if (icon === 'none' || !icon) { return { none: true } } } else { return { cls: res.cls, content: res.content !== void 0 ? res.content : ' ' } } } } if (mRE.test(icon) === true) { const [ def, viewBox = defaultViewBox ] = icon.split('|') return { svg: true, viewBox, nodes: def.split('&&').map(path => { const [ d, style, transform ] = path.split('@@') return h('path', { style, d, transform }) }) } } if (imgRE.test(icon) === true) { return { img: true, src: icon.substring(4) } } if (svgUseRE.test(icon) === true) { const [ def, viewBox = defaultViewBox ] = icon.split('|') return { svguse: true, src: def.substring(7), viewBox } } let content = ' ' const matches = icon.match(libRE) if (matches !== null) { cls = libMap[ matches[ 1 ] ](icon) } else if (faRE.test(icon) === true) { cls = icon } else if (ionRE.test(icon) === true) { cls = `ionicons ion-${ $q.platform.is.ios === true ? 'ios' : 'md' }${ icon.substring(3) }` } else if (symRE.test(icon) === true) { // "notranslate" class is for Google Translate // to avoid tampering with Material Symbols ligature font // // Caution: To be able to add suffix to the class name, // keep the 'material-symbols' at the end of the string. cls = 'notranslate material-symbols' const matches = icon.match(symRE) if (matches !== null) { icon = icon.substring(6) cls += symMap[ matches[ 1 ] ] } content = icon } else { // "notranslate" class is for Google Translate // to avoid tampering with Material Icons ligature font // // Caution: To be able to add suffix to the class name, // keep the 'material-icons' at the end of the string. cls = 'notranslate material-icons' const matches = icon.match(matRE) if (matches !== null) { icon = icon.substring(2) cls += matMap[ matches[ 1 ] ] } content = icon } return { cls, content } }) return () => { const data = { class: classes.value, style: sizeStyle.value, 'aria-hidden': 'true', role: 'presentation' } if (type.value.none === true) { return h(props.tag, data, hSlot(slots.default)) } if (type.value.img === true) { return h('span', data, hMergeSlot(slots.default, [ h('img', { src: type.value.src }) ])) } if (type.value.svg === true) { return h('span', data, hMergeSlot(slots.default, [ h('svg', { viewBox: type.value.viewBox || '0 0 24 24' }, type.value.nodes) ])) } if (type.value.svguse === true) { return h('span', data, hMergeSlot(slots.default, [ h('svg', { viewBox: type.value.viewBox }, [ h('use', { 'xlink:href': type.value.src }) ]) ])) } if (type.value.cls !== void 0) { data.class += ' ' + type.value.cls } return h(props.tag, data, hMergeSlot(slots.default, [ type.value.content ])) } } })