11import Vue from '../../utils/vue'
22import { mergeData } from 'vue-functional-data-merge'
33import identity from '../../utils/identity'
4- import { kebabCase , pascalCase , trim } from '../../utils/string '
4+ import { isUndefinedOrNull } from '../../utils/inspect '
55import { toFloat } from '../../utils/number'
6+ import { kebabCase , pascalCase , trim } from '../../utils/string'
67
78// Common icon props (should be cloned/spread before using)
89export const commonIconProps = {
@@ -52,28 +53,32 @@ const baseAttrs = {
5253
5354// Shared private base component to reduce bundle/runtime size
5455// @vue /component
55- const BVIconBase = {
56+ export const BVIconBase = /*#__PURE__*/ Vue . extend ( {
5657 name : 'BVIconBase' ,
5758 functional : true ,
5859 props : {
5960 content : {
6061 type : String
6162 } ,
63+ stacked : {
64+ type : Boolean ,
65+ default : false
66+ } ,
6267 ...commonIconProps
6368 } ,
64- render ( h , { data, props } ) {
69+ render ( h , { data, props, children } ) {
6570 const fontScale = Math . max ( toFloat ( props . fontScale ) || 1 , 0 ) || 1
6671 const scale = Math . max ( toFloat ( props . scale ) || 1 , 0 ) || 1
6772 const rotate = toFloat ( props . rotate ) || 0
6873 const shiftH = toFloat ( props . shiftH ) || 0
6974 const shiftV = toFloat ( props . shiftV ) || 0
7075 const flipH = props . flipH
7176 const flipV = props . flipV
72- // Compute the transforms. Note that order is important as
73- // SVG transforms are applied in order from left to right
74- // and we want flipping/scale to occur before rotation.
75- // Note shifting is applied separately. Assumes that the
76- // viewbox is `0 0 20 20` (`10 10` is the center)
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)
7782 const hasScale = flipH || flipV || scale !== 1
7883 const hasTransforms = hasScale || rotate
7984 const hasShift = shiftH || shiftV
@@ -84,11 +89,19 @@ const BVIconBase = {
8489 hasTransforms ? 'translate(-10 -10)' : null
8590 ] . filter ( identity )
8691
92+ // Handling stacked icons
93+ const isStacked = props . stacked
94+ const hasContent = ! isUndefinedOrNull ( props . content )
95+
8796 // We wrap the content in a `<g>` for handling the transforms (except shift)
88- let $inner = h ( 'g' , {
89- attrs : { transform : transforms . join ( ' ' ) || null } ,
90- domProps : { innerHTML : props . content || '' }
91- } )
97+ let $inner = h (
98+ 'g' ,
99+ {
100+ attrs : { transform : transforms . join ( ' ' ) || null } ,
101+ domProps : hasContent ? { innerHTML : props . content || '' } : { }
102+ } ,
103+ children
104+ )
92105
93106 // If needed, we wrap in an additional `<g>` in order to handle the shifting
94107 if ( hasShift ) {
@@ -103,28 +116,33 @@ const BVIconBase = {
103116 'svg' ,
104117 mergeData (
105118 {
119+ staticClass : 'b-icon bi' ,
106120 class : { [ `text-${ props . variant } ` ] : ! ! props . variant } ,
107121 attrs : baseAttrs ,
108- style : { fontSize : fontScale === 1 ? null : `${ fontScale * 100 } %` }
122+ style : isStacked ? { } : { fontSize : fontScale === 1 ? null : `${ fontScale * 100 } %` }
109123 } ,
110124 // Merge in user supplied data
111125 data ,
126+ // If icon is stacked, null out some attrs
127+ isStacked ? { attrs : { width : null , height : null , role : null , alt : null } } : { } ,
112128 // These cannot be overridden by users
113129 {
114- staticClass : 'b-icon bi' ,
115- attrs : { xmlns : 'http://www.w3.org/2000/svg' , fill : 'currentColor' }
130+ attrs : {
131+ xmlns : isStacked ? null : 'http://www.w3.org/2000/svg' ,
132+ fill : 'currentColor'
133+ }
116134 }
117135 ) ,
118136 [ $inner ]
119137 )
120138 }
121- }
139+ } )
122140
123141/**
124142 * Icon component generator function
125143 *
126144 * @param {string } icon name (minus the leading `BIcon`)
127- * @param {string } raw innerHTML for SVG
145+ * @param {string } raw ` innerHTML` for SVG
128146 * @return {VueComponent }
129147 */
130148export const makeIcon = ( name , content ) => {
@@ -137,7 +155,13 @@ export const makeIcon = (name, content) => {
137155 return Vue . extend ( {
138156 name : iconName ,
139157 functional : true ,
140- props : { ...commonIconProps } ,
158+ props : {
159+ ...commonIconProps ,
160+ stacked : {
161+ type : Boolean ,
162+ default : false
163+ }
164+ } ,
141165 render ( h , { data, props } ) {
142166 return h (
143167 BVIconBase ,
0 commit comments