11import Vue from '../../utils/vue'
22import { mergeData } from 'vue-functional-data-merge'
3- import identity from '../../utils/identity'
4- import { isUndefinedOrNull } from '../../utils/inspect'
5- import { toFloat } from '../../utils/number'
63import { kebabCase , pascalCase , trim } from '../../utils/string'
7-
8- // Common icon props (should be cloned/spread before using)
9- export const commonIconProps = {
10- variant : {
11- type : String ,
12- default : null
13- } ,
14- fontScale : {
15- type : [ Number , String ] ,
16- default : 1
17- } ,
18- scale : {
19- type : [ Number , String ] ,
20- default : 1
21- } ,
22- rotate : {
23- type : [ Number , String ] ,
24- default : 0
25- } ,
26- flipH : {
27- type : Boolean ,
28- default : false
29- } ,
30- flipV : {
31- type : Boolean ,
32- default : false
33- } ,
34- shiftH : {
35- type : [ Number , String ] ,
36- default : 0
37- } ,
38- shiftV : {
39- type : [ Number , String ] ,
40- default : 0
41- }
42- }
43-
44- // Base attributes needed on all icons
45- const baseAttrs = {
46- width : '1em' ,
47- height : '1em' ,
48- viewBox : '0 0 20 20' ,
49- focusable : 'false' ,
50- role : 'img' ,
51- alt : 'icon'
52- }
53-
54- // Shared private base component to reduce bundle/runtime size
55- // @vue /component
56- export const BVIconBase = /*#__PURE__*/ Vue . extend ( {
57- name : 'BVIconBase' ,
58- functional : true ,
59- props : {
60- content : {
61- type : String
62- } ,
63- stacked : {
64- type : Boolean ,
65- default : false
66- } ,
67- ...commonIconProps
68- } ,
69- render ( h , { data, props, children } ) {
70- const fontScale = Math . max ( toFloat ( props . fontScale ) || 1 , 0 ) || 1
71- const scale = Math . max ( toFloat ( props . scale ) || 1 , 0 ) || 1
72- const rotate = toFloat ( props . rotate ) || 0
73- const shiftH = toFloat ( props . shiftH ) || 0
74- const shiftV = toFloat ( props . shiftV ) || 0
75- const flipH = props . flipH
76- const flipV = props . flipV
77- // Compute the transforms
78- // Note that order is important as SVG transforms are applied in order from
79- // left to right and we want flipping/scale to occur before rotation
80- // Note shifting is applied separately
81- // Assumes that the viewbox is `0 0 20 20` (`10 10` is the center)
82- const hasScale = flipH || flipV || scale !== 1
83- const hasTransforms = hasScale || rotate
84- const hasShift = shiftH || shiftV
85- const transforms = [
86- hasTransforms ? 'translate(10 10)' : null ,
87- hasScale ? `scale(${ ( flipH ? - 1 : 1 ) * scale } ${ ( flipV ? - 1 : 1 ) * scale } )` : null ,
88- rotate ? `rotate(${ rotate } )` : null ,
89- hasTransforms ? 'translate(-10 -10)' : null
90- ] . filter ( identity )
91-
92- // Handling stacked icons
93- const isStacked = props . stacked
94- const hasContent = ! isUndefinedOrNull ( props . content )
95-
96- // We wrap the content in a `<g>` for handling the transforms (except shift)
97- let $inner = h (
98- 'g' ,
99- {
100- attrs : { transform : transforms . join ( ' ' ) || null } ,
101- domProps : hasContent ? { innerHTML : props . content || '' } : { }
102- } ,
103- children
104- )
105-
106- // If needed, we wrap in an additional `<g>` in order to handle the shifting
107- if ( hasShift ) {
108- $inner = h (
109- 'g' ,
110- { attrs : { transform : `translate(${ ( 20 * shiftH ) / 16 } ${ ( - 20 * shiftV ) / 16 } )` } } ,
111- [ $inner ]
112- )
113- }
114-
115- return h (
116- 'svg' ,
117- mergeData (
118- {
119- staticClass : 'b-icon bi' ,
120- class : { [ `text-${ props . variant } ` ] : ! ! props . variant } ,
121- attrs : baseAttrs ,
122- style : isStacked ? { } : { fontSize : fontScale === 1 ? null : `${ fontScale * 100 } %` }
123- } ,
124- // Merge in user supplied data
125- data ,
126- // If icon is stacked, null out some attrs
127- isStacked ? { attrs : { width : null , height : null , role : null , alt : null } } : { } ,
128- // These cannot be overridden by users
129- {
130- attrs : {
131- xmlns : isStacked ? null : 'http://www.w3.org/2000/svg' ,
132- fill : 'currentColor'
133- }
134- }
135- ) ,
136- [ $inner ]
137- )
138- }
139- } )
4+ import { commonIconProps , BVIconBase } from './icon-base'
1405
1416/**
1427 * Icon component generator function
@@ -152,7 +17,7 @@ export const makeIcon = (name, content) => {
15217 const iconNameClass = `bi-${ kebabCase ( name ) } `
15318 const svgContent = trim ( content || '' )
15419 // Return the icon component definition
155- return Vue . extend ( {
20+ return /*#__PURE__*/ Vue . extend ( {
15621 name : iconName ,
15722 functional : true ,
15823 props : {
0 commit comments