chore: refactor tag
							parent
							
								
									be8faa5190
								
							
						
					
					
						commit
						09eb71d5fb
					
				|  | @ -1,4 +1,6 @@ | ||||||
| import { tuple } from './type'; | import { ElementOf, tuple } from './type'; | ||||||
|  | 
 | ||||||
|  | export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning'); | ||||||
| 
 | 
 | ||||||
| export const PresetColorTypes = tuple( | export const PresetColorTypes = tuple( | ||||||
|   'pink', |   'pink', | ||||||
|  | @ -15,3 +17,6 @@ export const PresetColorTypes = tuple( | ||||||
|   'gold', |   'gold', | ||||||
|   'lime', |   'lime', | ||||||
| ); | ); | ||||||
|  | 
 | ||||||
|  | export type PresetColorType = ElementOf<typeof PresetColorTypes>; | ||||||
|  | export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,22 @@ | ||||||
|  | export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||||||
| // https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
 | // https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
 | ||||||
| export const tuple = <T extends string[]>(...args: T) => args; | export const tuple = <T extends string[]>(...args: T) => args; | ||||||
| 
 | 
 | ||||||
| export const tupleNum = (...args) => args; | export const tupleNum = <T extends number[]>(...args: T) => args; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * https://stackoverflow.com/a/59187769
 | ||||||
|  |  * Extract the type of an element of an array/tuple without performing indexing | ||||||
|  |  */ | ||||||
|  | export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer E)[] ? E : never; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * https://github.com/Microsoft/TypeScript/issues/29729
 | ||||||
|  |  */ | ||||||
|  | export type LiteralUnion<T extends U, U> = T | (U & {}); | ||||||
|  | 
 | ||||||
|  | export type StringKeyOf<T> = Extract<keyof T, string>; | ||||||
|  | 
 | ||||||
|  | export type EventHandlers<E> = { | ||||||
|  |   [K in StringKeyOf<E>]?: E[K] extends Function ? E[K] : (payload: E[K]) => void; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | @ -1,18 +1,18 @@ | ||||||
| import { nextTick, inject } from 'vue'; | import { nextTick, inject, defineComponent } from 'vue'; | ||||||
| import TransitionEvents from './css-animation/Event'; | import TransitionEvents from './css-animation/Event'; | ||||||
| import raf from './raf'; | import raf from './raf'; | ||||||
| import { ConfigConsumerProps } from '../config-provider'; | import { ConfigConsumerProps } from '../config-provider'; | ||||||
| import { findDOMNode } from './props-util'; | import { findDOMNode } from './props-util'; | ||||||
| let styleForPesudo; | let styleForPesudo: HTMLStyleElement | null; | ||||||
| 
 | 
 | ||||||
| // Where el is the DOM element you'd like to test for visibility
 | // Where el is the DOM element you'd like to test for visibility
 | ||||||
| function isHidden(element) { | function isHidden(element: HTMLElement) { | ||||||
|   if (process.env.NODE_ENV === 'test') { |   if (process.env.NODE_ENV === 'test') { | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   return !element || element.offsetParent === null; |   return !element || element.offsetParent === null; | ||||||
| } | } | ||||||
| function isNotGrey(color) { | function isNotGrey(color: string) { | ||||||
|   // eslint-disable-next-line no-useless-escape
 |   // eslint-disable-next-line no-useless-escape
 | ||||||
|   const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/); |   const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/); | ||||||
|   if (match && match[1] && match[2] && match[3]) { |   if (match && match[1] && match[2] && match[3]) { | ||||||
|  | @ -20,7 +20,7 @@ function isNotGrey(color) { | ||||||
|   } |   } | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| export default { | export default defineComponent({ | ||||||
|   name: 'Wave', |   name: 'Wave', | ||||||
|   props: ['insertExtraNode'], |   props: ['insertExtraNode'], | ||||||
|   mounted() { |   mounted() { | ||||||
|  | @ -47,7 +47,7 @@ export default { | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     onClick(node, waveColor) { |     onClick(node: HTMLElement, waveColor: string) { | ||||||
|       if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) { |       if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  | @ -87,7 +87,7 @@ export default { | ||||||
|       TransitionEvents.addStartEventListener(node, this.onTransitionStart); |       TransitionEvents.addStartEventListener(node, this.onTransitionStart); | ||||||
|       TransitionEvents.addEndEventListener(node, this.onTransitionEnd); |       TransitionEvents.addEndEventListener(node, this.onTransitionEnd); | ||||||
|     }, |     }, | ||||||
|     onTransitionStart(e) { |     onTransitionStart(e: AnimationEvent) { | ||||||
|       if (this._.isUnmounted) return; |       if (this._.isUnmounted) return; | ||||||
| 
 | 
 | ||||||
|       const node = findDOMNode(this); |       const node = findDOMNode(this); | ||||||
|  | @ -99,7 +99,7 @@ export default { | ||||||
|         this.resetEffect(node); |         this.resetEffect(node); | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     onTransitionEnd(e) { |     onTransitionEnd(e: AnimationEvent) { | ||||||
|       if (!e || e.animationName !== 'fadeEffect') { |       if (!e || e.animationName !== 'fadeEffect') { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  | @ -109,7 +109,7 @@ export default { | ||||||
|       const { insertExtraNode } = this.$props; |       const { insertExtraNode } = this.$props; | ||||||
|       return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'; |       return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'; | ||||||
|     }, |     }, | ||||||
|     bindAnimationEvent(node) { |     bindAnimationEvent(node: HTMLElement) { | ||||||
|       if ( |       if ( | ||||||
|         !node || |         !node || | ||||||
|         !node.getAttribute || |         !node.getAttribute || | ||||||
|  | @ -118,9 +118,9 @@ export default { | ||||||
|       ) { |       ) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|       const onClick = e => { |       const onClick = (e: MouseEvent) => { | ||||||
|         // Fix radio button click twice
 |         // Fix radio button click twice
 | ||||||
|         if (e.target.tagName === 'INPUT' || isHidden(e.target)) { |         if ((e.target as HTMLElement).tagName === 'INPUT' || isHidden(e.target as HTMLElement)) { | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|         this.resetEffect(node); |         this.resetEffect(node); | ||||||
|  | @ -146,7 +146,7 @@ export default { | ||||||
|       }; |       }; | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     resetEffect(node) { |     resetEffect(node: HTMLElement) { | ||||||
|       if (!node || node === this.extraNode || !(node instanceof Element)) { |       if (!node || node === this.extraNode || !(node instanceof Element)) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  | @ -171,4 +171,4 @@ export default { | ||||||
|     } |     } | ||||||
|     return this.$slots.default && this.$slots.default()[0]; |     return this.$slots.default && this.$slots.default()[0]; | ||||||
|   }, |   }, | ||||||
| }; | }); | ||||||
|  |  | ||||||
|  | @ -1,45 +0,0 @@ | ||||||
| import { inject } from 'vue'; |  | ||||||
| import PropTypes from '../_util/vue-types'; |  | ||||||
| import { ConfigConsumerProps } from '../config-provider'; |  | ||||||
| 
 |  | ||||||
| export default { |  | ||||||
|   name: 'ACheckableTag', |  | ||||||
|   props: { |  | ||||||
|     prefixCls: PropTypes.string, |  | ||||||
|     checked: PropTypes.bool, |  | ||||||
|     onChange: PropTypes.func, |  | ||||||
|     'onUpdate:checked': PropTypes.func, |  | ||||||
|   }, |  | ||||||
|   setup() { |  | ||||||
|     return { |  | ||||||
|       configProvider: inject('configProvider', ConfigConsumerProps), |  | ||||||
|     }; |  | ||||||
|   }, |  | ||||||
|   computed: { |  | ||||||
|     classes() { |  | ||||||
|       const { checked, prefixCls: customizePrefixCls } = this; |  | ||||||
|       const getPrefixCls = this.configProvider.getPrefixCls; |  | ||||||
|       const prefixCls = getPrefixCls('tag', customizePrefixCls); |  | ||||||
|       return { |  | ||||||
|         [`${prefixCls}`]: true, |  | ||||||
|         [`${prefixCls}-checkable`]: true, |  | ||||||
|         [`${prefixCls}-checkable-checked`]: checked, |  | ||||||
|       }; |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     handleClick() { |  | ||||||
|       const { checked } = this; |  | ||||||
|       this.$emit('update:checked', !checked); |  | ||||||
|       this.$emit('change', !checked); |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   render() { |  | ||||||
|     const { classes, handleClick, $slots } = this; |  | ||||||
|     return ( |  | ||||||
|       <div class={classes} onClick={handleClick}> |  | ||||||
|         {$slots.default && $slots.default()} |  | ||||||
|       </div> |  | ||||||
|     ); |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
|  | @ -0,0 +1,44 @@ | ||||||
|  | import { inject, CSSProperties, SetupContext } from 'vue'; | ||||||
|  | import classNames from 'classnames'; | ||||||
|  | import { ConfigConsumerProps } from '../config-provider'; | ||||||
|  | 
 | ||||||
|  | export interface CheckableTagProps { | ||||||
|  |   prefixCls?: string; | ||||||
|  |   class?: string; | ||||||
|  |   style?: CSSProperties; | ||||||
|  |   checked: boolean; | ||||||
|  |   onChange?: (checked: boolean) => void; | ||||||
|  |   onClick?: (e: Event) => void; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const CheckableTag = (props: CheckableTagProps, { slots }: SetupContext) => { | ||||||
|  |   const { getPrefixCls } = inject('configProvider', ConfigConsumerProps); | ||||||
|  |   const handleClick = (e: Event) => { | ||||||
|  |     const { checked, onChange, onClick } = props; | ||||||
|  |     if (onChange) { | ||||||
|  |       onChange(!checked); | ||||||
|  |     } | ||||||
|  |     if (onClick) { | ||||||
|  |       onClick(e); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const { prefixCls: customizePrefixCls, class: className, checked } = props; | ||||||
|  |   const prefixCls = getPrefixCls('tag', customizePrefixCls); | ||||||
|  |   const cls = classNames( | ||||||
|  |     prefixCls, | ||||||
|  |     { | ||||||
|  |       [`${prefixCls}-checkable`]: true, | ||||||
|  |       [`${prefixCls}-checkable-checked`]: checked, | ||||||
|  |     }, | ||||||
|  |     className, | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <span class={cls} onClick={handleClick}> | ||||||
|  |       {slots.default?.()} | ||||||
|  |     </span> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default CheckableTag; | ||||||
|  | @ -1,121 +0,0 @@ | ||||||
| import { inject } from 'vue'; |  | ||||||
| import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; |  | ||||||
| import PropTypes from '../_util/vue-types'; |  | ||||||
| import Wave from '../_util/wave'; |  | ||||||
| import { hasProp, getOptionProps } from '../_util/props-util'; |  | ||||||
| import BaseMixin from '../_util/BaseMixin'; |  | ||||||
| import { ConfigConsumerProps } from '../config-provider'; |  | ||||||
| 
 |  | ||||||
| const PresetColorTypes = [ |  | ||||||
|   'pink', |  | ||||||
|   'red', |  | ||||||
|   'yellow', |  | ||||||
|   'orange', |  | ||||||
|   'cyan', |  | ||||||
|   'green', |  | ||||||
|   'blue', |  | ||||||
|   'purple', |  | ||||||
|   'geekblue', |  | ||||||
|   'magenta', |  | ||||||
|   'volcano', |  | ||||||
|   'gold', |  | ||||||
|   'lime', |  | ||||||
| ]; |  | ||||||
| const PresetColorRegex = new RegExp(`^(${PresetColorTypes.join('|')})(-inverse)?$`); |  | ||||||
| 
 |  | ||||||
| export default { |  | ||||||
|   name: 'ATag', |  | ||||||
|   mixins: [BaseMixin], |  | ||||||
|   props: { |  | ||||||
|     prefixCls: PropTypes.string, |  | ||||||
|     color: PropTypes.string, |  | ||||||
|     closable: PropTypes.bool.def(false), |  | ||||||
|     visible: PropTypes.bool, |  | ||||||
|     onClose: PropTypes.func, |  | ||||||
|     'onUpdate:visible': PropTypes.func, |  | ||||||
|   }, |  | ||||||
|   setup() { |  | ||||||
|     return { |  | ||||||
|       configProvider: inject('configProvider', ConfigConsumerProps), |  | ||||||
|     }; |  | ||||||
|   }, |  | ||||||
|   data() { |  | ||||||
|     let _visible = true; |  | ||||||
|     const props = getOptionProps(this); |  | ||||||
|     if ('visible' in props) { |  | ||||||
|       _visible = this.visible; |  | ||||||
|     } |  | ||||||
|     return { |  | ||||||
|       _visible, |  | ||||||
|     }; |  | ||||||
|   }, |  | ||||||
|   watch: { |  | ||||||
|     visible(val) { |  | ||||||
|       this.setState({ |  | ||||||
|         _visible: val, |  | ||||||
|       }); |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     setVisible(visible, e) { |  | ||||||
|       this.$emit('update:visible', false); |  | ||||||
|       this.$emit('close', e); |  | ||||||
|       if (e.defaultPrevented) { |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|       if (!hasProp(this, 'visible')) { |  | ||||||
|         this.setState({ _visible: visible }); |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     handleIconClick(e) { |  | ||||||
|       e.stopPropagation(); |  | ||||||
|       this.setVisible(false, e); |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     isPresetColor() { |  | ||||||
|       const { color } = this.$props; |  | ||||||
|       if (!color) { |  | ||||||
|         return false; |  | ||||||
|       } |  | ||||||
|       return PresetColorRegex.test(color); |  | ||||||
|     }, |  | ||||||
|     getTagStyle() { |  | ||||||
|       const { color } = this.$props; |  | ||||||
|       const isPresetColor = this.isPresetColor(); |  | ||||||
|       return { |  | ||||||
|         backgroundColor: color && !isPresetColor ? color : undefined, |  | ||||||
|       }; |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     getTagClassName(prefixCls) { |  | ||||||
|       const { color } = this.$props; |  | ||||||
|       const isPresetColor = this.isPresetColor(); |  | ||||||
|       return { |  | ||||||
|         [prefixCls]: true, |  | ||||||
|         [`${prefixCls}-${color}`]: isPresetColor, |  | ||||||
|         [`${prefixCls}-has-color`]: color && !isPresetColor, |  | ||||||
|       }; |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     renderCloseIcon() { |  | ||||||
|       const { closable } = this.$props; |  | ||||||
|       return closable ? <CloseOutlined onClick={this.handleIconClick} /> : null; |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   render() { |  | ||||||
|     const { prefixCls: customizePrefixCls } = this.$props; |  | ||||||
|     const isNeedWave = 'onClick' in this.$attrs; |  | ||||||
|     const getPrefixCls = this.configProvider.getPrefixCls; |  | ||||||
|     const prefixCls = getPrefixCls('tag', customizePrefixCls); |  | ||||||
|     const { _visible: visible } = this.$data; |  | ||||||
|     const tag = ( |  | ||||||
|       <span v-show={visible} class={this.getTagClassName(prefixCls)} style={this.getTagStyle()}> |  | ||||||
|         {this.$slots.default && this.$slots.default()} |  | ||||||
|         {this.renderCloseIcon()} |  | ||||||
|       </span> |  | ||||||
|     ); |  | ||||||
|     return isNeedWave ? <Wave>{tag}</Wave> : tag; |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| import Tag from './Tag'; |  | ||||||
| import CheckableTag from './CheckableTag'; |  | ||||||
| 
 |  | ||||||
| Tag.CheckableTag = CheckableTag; |  | ||||||
| 
 |  | ||||||
| /* istanbul ignore next */ |  | ||||||
| Tag.install = function(app) { |  | ||||||
|   app.component(Tag.name, Tag); |  | ||||||
|   app.component(Tag.CheckableTag.name, Tag.CheckableTag); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export default Tag; |  | ||||||
|  | @ -0,0 +1,143 @@ | ||||||
|  | import { | ||||||
|  |   inject, | ||||||
|  |   ref, | ||||||
|  |   HTMLAttributes, | ||||||
|  |   VNodeChild, | ||||||
|  |   Events, | ||||||
|  |   defineComponent, | ||||||
|  |   SetupContext, | ||||||
|  |   App, | ||||||
|  |   watchEffect, | ||||||
|  | } from 'vue'; | ||||||
|  | import classNames from 'classnames'; | ||||||
|  | import omit from 'omit.js'; | ||||||
|  | import CloseOutlined from '@ant-design/icons-vue/CloseOutlined'; | ||||||
|  | import Wave from '../_util/wave'; | ||||||
|  | import { | ||||||
|  |   PresetColorTypes, | ||||||
|  |   PresetStatusColorTypes, | ||||||
|  |   PresetColorType, | ||||||
|  |   PresetStatusColorType, | ||||||
|  | } from '../_util/colors'; | ||||||
|  | import { LiteralUnion, EventHandlers } from '../_util/type'; | ||||||
|  | import { ConfigConsumerProps } from '../config-provider'; | ||||||
|  | import CheckableTag from './CheckableTag'; | ||||||
|  | 
 | ||||||
|  | const PresetColorRegex = new RegExp(`^(${PresetColorTypes.join('|')})(-inverse)?$`); | ||||||
|  | const PresetStatusColorRegex = new RegExp(`^(${PresetStatusColorTypes.join('|')})$`); | ||||||
|  | 
 | ||||||
|  | export interface TagProps extends HTMLAttributes, Partial<EventHandlers<Events>> { | ||||||
|  |   prefixCls?: string; | ||||||
|  |   color?: LiteralUnion<PresetColorType | PresetStatusColorType, string>; | ||||||
|  |   closable?: boolean; | ||||||
|  |   closeIcon?: VNodeChild | JSX.Element; | ||||||
|  |   visible?: boolean; | ||||||
|  |   onClose?: Function; | ||||||
|  |   icon?: VNodeChild | JSX.Element; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const Tag = defineComponent({ | ||||||
|  |   setup(_: TagProps, { slots, attrs }: SetupContext) { | ||||||
|  |     const { getPrefixCls } = inject('configProvider', ConfigConsumerProps); | ||||||
|  | 
 | ||||||
|  |     const visible = ref(true); | ||||||
|  | 
 | ||||||
|  |     return () => { | ||||||
|  |       const { | ||||||
|  |         prefixCls: customizePrefixCls, | ||||||
|  |         style, | ||||||
|  |         icon, | ||||||
|  |         color, | ||||||
|  |         onClose, | ||||||
|  |         closeIcon, | ||||||
|  |         closable = false, | ||||||
|  |         ...props | ||||||
|  |       } = attrs as TagProps; | ||||||
|  | 
 | ||||||
|  |       watchEffect(() => { | ||||||
|  |         if ('visible' in props) { | ||||||
|  |           visible.value = props.visible!; | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       const isPresetColor = (): boolean => { | ||||||
|  |         if (!color) { | ||||||
|  |           return false; | ||||||
|  |         } | ||||||
|  |         return PresetColorRegex.test(color) || PresetStatusColorRegex.test(color); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       const presetColor = isPresetColor(); | ||||||
|  |       const prefixCls = getPrefixCls('tag', customizePrefixCls); | ||||||
|  | 
 | ||||||
|  |       const handleCloseClick = (e: MouseEvent) => { | ||||||
|  |         e.stopPropagation(); | ||||||
|  |         if (onClose) { | ||||||
|  |           onClose(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (e.defaultPrevented) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |         if (!('visible' in props)) { | ||||||
|  |           visible.value = false; | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       const renderCloseIcon = () => { | ||||||
|  |         if (closable) { | ||||||
|  |           return closeIcon ? ( | ||||||
|  |             <div class={`${prefixCls}-close-icon`} onClick={handleCloseClick}> | ||||||
|  |               {closeIcon} | ||||||
|  |             </div> | ||||||
|  |           ) : ( | ||||||
|  |             <CloseOutlined class={`${prefixCls}-close-icon`} onClick={handleCloseClick} /> | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       const tagStyle = { | ||||||
|  |         backgroundColor: color && !isPresetColor() ? color : undefined, | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       const tagClassName = classNames(prefixCls, { | ||||||
|  |         [`${prefixCls}-${color}`]: presetColor, | ||||||
|  |         [`${prefixCls}-has-color`]: color && !presetColor, | ||||||
|  |         [`${prefixCls}-hidden`]: !visible.value, | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       const tagProps = omit(props, ['visible']); | ||||||
|  |       const iconNode = icon || null; | ||||||
|  |       const children = slots.default?.(); | ||||||
|  |       const kids = iconNode ? ( | ||||||
|  |         <> | ||||||
|  |           {iconNode} | ||||||
|  |           <span>{children}</span> | ||||||
|  |         </> | ||||||
|  |       ) : ( | ||||||
|  |         children | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       const isNeedWave = 'onClick' in props; | ||||||
|  | 
 | ||||||
|  |       const tagNode = ( | ||||||
|  |         <span {...tagProps} class={tagClassName} style={tagStyle}> | ||||||
|  |           {kids} | ||||||
|  |           {renderCloseIcon()} | ||||||
|  |         </span> | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return isNeedWave ? <Wave>{tagNode}</Wave> : tagNode; | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | Tag.CheckableTag = CheckableTag; | ||||||
|  | 
 | ||||||
|  | Tag.install = (app: App) => { | ||||||
|  |   app.component(Tag.name, Tag); | ||||||
|  |   app.component(CheckableTag.name, CheckableTag); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default Tag; | ||||||
		Loading…
	
		Reference in New Issue
	
	 Amour1688
						Amour1688