feat: mentions
							parent
							
								
									0910df5a95
								
							
						
					
					
						commit
						a53768fa9a
					
				|  | @ -35,3 +35,7 @@ v-model -> v-model:visible | |||
| v-model -> v-model:visible | ||||
| 
 | ||||
| okButtonProps、cancelButtonProps 扁平化处理 | ||||
| 
 | ||||
| ## Mentions | ||||
| 
 | ||||
| v-model -> v-model:value | ||||
|  |  | |||
|  | @ -1,19 +1,16 @@ | |||
| import { inject } from 'vue'; | ||||
| import PropTypes from '../_util/vue-types'; | ||||
| import Empty from '../empty'; | ||||
| import { ConfigConsumerProps } from './'; | ||||
| 
 | ||||
| const RenderEmpty = { | ||||
|   functional: true, | ||||
|   inject: { | ||||
|     configProvider: { default: () => ConfigConsumerProps }, | ||||
|   }, | ||||
|   props: { | ||||
|     componentName: PropTypes.string, | ||||
|   }, | ||||
|   render(createElement, context) { | ||||
|     const { props, injections } = context; | ||||
|   setup(props) { | ||||
|     const configProvider = inject('configProvider', ConfigConsumerProps); | ||||
|     function renderHtml(componentName) { | ||||
|       const getPrefixCls = injections.configProvider.getPrefixCls; | ||||
|       const getPrefixCls = configProvider.getPrefixCls; | ||||
|       const prefix = getPrefixCls('empty'); | ||||
|       switch (componentName) { | ||||
|         case 'Table': | ||||
|  | @ -31,11 +28,11 @@ const RenderEmpty = { | |||
|           return <Empty />; | ||||
|       } | ||||
|     } | ||||
|     return renderHtml(props.componentName); | ||||
|     return () => renderHtml(props.componentName); | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| function renderEmpty(h, componentName) { | ||||
| function renderEmpty(componentName) { | ||||
|   return <RenderEmpty componentName={componentName} />; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| import { inject, nextTick } from 'vue'; | ||||
| import classNames from 'classnames'; | ||||
| import omit from 'omit.js'; | ||||
| import PropTypes from '../_util/vue-types'; | ||||
|  | @ -7,12 +8,7 @@ import Base from '../base'; | |||
| import Spin from '../spin'; | ||||
| import BaseMixin from '../_util/BaseMixin'; | ||||
| import { ConfigConsumerProps } from '../config-provider'; | ||||
| import { | ||||
|   getOptionProps, | ||||
|   getComponentFromProp, | ||||
|   getListeners, | ||||
|   filterEmpty, | ||||
| } from '../_util/props-util'; | ||||
| import { getOptionProps, getComponent, filterEmpty } from '../_util/props-util'; | ||||
| 
 | ||||
| const { Option } = VcMentions; | ||||
| 
 | ||||
|  | @ -53,18 +49,16 @@ const Mentions = { | |||
|   name: 'AMentions', | ||||
|   mixins: [BaseMixin], | ||||
|   inheritAttrs: false, | ||||
|   model: { | ||||
|     prop: 'value', | ||||
|     event: 'change', | ||||
|   }, | ||||
|   Option: { ...Option, name: 'AMentionsOption' }, | ||||
|   getMentions, | ||||
|   props: { | ||||
|     ...mentionsProps, | ||||
|     loading: PropTypes.bool, | ||||
|   }, | ||||
|   inject: { | ||||
|     configProvider: { default: () => ConfigConsumerProps }, | ||||
|   setup() { | ||||
|     return { | ||||
|       configProvider: inject('configProvider', ConfigConsumerProps), | ||||
|     }; | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|  | @ -72,7 +66,7 @@ const Mentions = { | |||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|     nextTick(() => { | ||||
|       if (this.autoFocus) { | ||||
|         this.focus(); | ||||
|       } | ||||
|  | @ -99,19 +93,19 @@ const Mentions = { | |||
|     }, | ||||
|     onChange(val) { | ||||
|       this.$emit('change', val); | ||||
|       this.$emit('update:value', val); | ||||
|     }, | ||||
|     getNotFoundContent(renderEmpty) { | ||||
|       const h = this.$createElement; | ||||
|       const notFoundContent = getComponentFromProp(this, 'notFoundContent'); | ||||
|       const notFoundContent = getComponent(this, 'notFoundContent'); | ||||
|       if (notFoundContent !== undefined) { | ||||
|         return notFoundContent; | ||||
|       } | ||||
| 
 | ||||
|       return renderEmpty(h, 'Select'); | ||||
|       return renderEmpty('Select'); | ||||
|     }, | ||||
|     getOptions() { | ||||
|       const { loading } = this.$props; | ||||
|       const children = filterEmpty(this.$slots.default || []); | ||||
|       const children = filterEmpty(this.$slots.default?.() || []); | ||||
| 
 | ||||
|       if (loading) { | ||||
|         return ( | ||||
|  | @ -154,24 +148,20 @@ const Mentions = { | |||
|     }); | ||||
| 
 | ||||
|     const mentionsProps = { | ||||
|       props: { | ||||
|         prefixCls, | ||||
|         notFoundContent: this.getNotFoundContent(renderEmpty), | ||||
|         ...otherProps, | ||||
|         disabled, | ||||
|         filterOption: this.getFilterOption(), | ||||
|         getPopupContainer, | ||||
|         children: this.getOptions(), | ||||
|       }, | ||||
|       prefixCls, | ||||
|       notFoundContent: this.getNotFoundContent(renderEmpty), | ||||
|       ...otherProps, | ||||
|       disabled, | ||||
|       filterOption: this.getFilterOption(), | ||||
|       getPopupContainer, | ||||
|       children: this.getOptions(), | ||||
|       class: mergedClassName, | ||||
|       attrs: { rows: 1, ...this.$attrs }, | ||||
|       on: { | ||||
|         ...getListeners(this), | ||||
|         change: this.onChange, | ||||
|         select: this.onSelect, | ||||
|         focus: this.onFocus, | ||||
|         blur: this.onBlur, | ||||
|       }, | ||||
|       rows: 1, | ||||
|       ...this.$attrs, | ||||
|       onChange: this.onChange, | ||||
|       onSelect: this.onSelect, | ||||
|       onFocus: this.onFocus, | ||||
|       onBlur: this.onBlur, | ||||
|       ref: 'vcMentions', | ||||
|     }; | ||||
| 
 | ||||
|  | @ -180,10 +170,10 @@ const Mentions = { | |||
| }; | ||||
| 
 | ||||
| /* istanbul ignore next */ | ||||
| Mentions.install = function(Vue) { | ||||
|   Vue.use(Base); | ||||
|   Vue.component(Mentions.name, Mentions); | ||||
|   Vue.component(Mentions.Option.name, Mentions.Option); | ||||
| Mentions.install = function(app) { | ||||
|   app.use(Base); | ||||
|   app.component(Mentions.name, Mentions); | ||||
|   app.component(Mentions.Option.name, Mentions.Option); | ||||
| }; | ||||
| 
 | ||||
| export default Mentions; | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| import { nextTick } from 'vue'; | ||||
| import PropTypes from '../_util/vue-types'; | ||||
| import { alignElement, alignPoint } from 'dom-align'; | ||||
| import addEventListener from '../vc-util/Dom/addEventListener'; | ||||
|  | @ -30,7 +31,7 @@ export default { | |||
|     return {}; | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|     nextTick(() => { | ||||
|       this.prevProps = { ...this.$props }; | ||||
|       const props = this.$props; | ||||
|       // if parent ref not attached .... use document.getElementById | ||||
|  | @ -41,7 +42,7 @@ export default { | |||
|     }); | ||||
|   }, | ||||
|   updated() { | ||||
|     this.$nextTick(() => { | ||||
|     nextTick(() => { | ||||
|       const prevProps = this.prevProps; | ||||
|       const props = this.$props; | ||||
|       let reAlign = false; | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| import Menu, { MenuItem } from '../../vc-menu'; | ||||
| import PropTypes from '../../_util/vue-types'; | ||||
| import { OptionProps } from './Option'; | ||||
| import { inject } from 'vue'; | ||||
| 
 | ||||
| function noop() {} | ||||
| export default { | ||||
|  | @ -9,10 +10,11 @@ export default { | |||
|     prefixCls: PropTypes.string, | ||||
|     options: PropTypes.arrayOf(OptionProps), | ||||
|   }, | ||||
|   inject: { | ||||
|     mentionsContext: { default: {} }, | ||||
|   setup() { | ||||
|     return { | ||||
|       mentionsContext: inject('mentionsContext'), | ||||
|     }; | ||||
|   }, | ||||
| 
 | ||||
|   render() { | ||||
|     const { | ||||
|       notFoundContent, | ||||
|  | @ -27,37 +29,36 @@ export default { | |||
| 
 | ||||
|     return ( | ||||
|       <Menu | ||||
|         {...{ | ||||
|           props: { | ||||
|             prefixCls: `${prefixCls}-menu`, | ||||
|             activeKey: activeOption.value, | ||||
|           }, | ||||
|           on: { | ||||
|             select: ({ key }) => { | ||||
|               const option = options.find(({ value }) => value === key); | ||||
|               selectOption(option); | ||||
|             }, | ||||
|             focus: onFocus, | ||||
|             blur: onBlur, | ||||
|           }, | ||||
|         prefixCls={`${prefixCls}-menu`} | ||||
|         activeKey={activeOption.value} | ||||
|         onSelect={({ key }) => { | ||||
|           const option = options.find(({ value }) => value === key); | ||||
|           selectOption(option); | ||||
|         }} | ||||
|       > | ||||
|         {options.map((option, index) => { | ||||
|           const { value, disabled, children } = option; | ||||
|           return ( | ||||
|             <MenuItem | ||||
|               key={value} | ||||
|               disabled={disabled} | ||||
|               onMouseenter={() => { | ||||
|                 setActiveIndex(index); | ||||
|               }} | ||||
|             > | ||||
|               {children} | ||||
|         onBlur={onBlur} | ||||
|         onFocus={onFocus} | ||||
|         children={[ | ||||
|           ...options.map((option, index) => { | ||||
|             const { value, disabled, children } = option; | ||||
|             return ( | ||||
|               <MenuItem | ||||
|                 key={value} | ||||
|                 disabled={disabled} | ||||
|                 onMouseenter={() => { | ||||
|                   setActiveIndex(index); | ||||
|                 }} | ||||
|               > | ||||
|                 {children} | ||||
|               </MenuItem> | ||||
|             ); | ||||
|           }), | ||||
|           !options.length && ( | ||||
|             <MenuItem key="notFoundContent" disabled> | ||||
|               {notFoundContent} | ||||
|             </MenuItem> | ||||
|           ); | ||||
|         })} | ||||
|         {!options.length && <MenuItem disabled>{notFoundContent}</MenuItem>} | ||||
|       </Menu> | ||||
|           ), | ||||
|         ].filter(Boolean)} | ||||
|       /> | ||||
|     ); | ||||
|   }, | ||||
| }; | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ export default { | |||
| 
 | ||||
|     const { $slots } = this; | ||||
| 
 | ||||
|     const children = $slots.default; | ||||
|     const children = $slots.default?.(); | ||||
| 
 | ||||
|     const popupElement = this.getDropdownElement(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,13 +1,8 @@ | |||
| import { provide, nextTick } from 'vue'; | ||||
| import omit from 'omit.js'; | ||||
| import KeyCode from '../../_util/KeyCode'; | ||||
| import BaseMixin from '../../_util/BaseMixin'; | ||||
| import { | ||||
|   getSlots, | ||||
|   hasProp, | ||||
|   getOptionProps, | ||||
|   getListeners, | ||||
|   initDefaultProps, | ||||
| } from '../../_util/props-util'; | ||||
| import { hasProp, getOptionProps, initDefaultProps } from '../../_util/props-util'; | ||||
| import warning from 'warning'; | ||||
| import { | ||||
|   getBeforeSelectionText, | ||||
|  | @ -24,15 +19,9 @@ const Mentions = { | |||
|   name: 'Mentions', | ||||
|   mixins: [BaseMixin], | ||||
|   inheritAttrs: false, | ||||
|   model: { | ||||
|     prop: 'value', | ||||
|     event: 'change', | ||||
|   }, | ||||
|   props: initDefaultProps(vcMentionsProps, defaultProps), | ||||
|   provide() { | ||||
|     return { | ||||
|       mentionsContext: this, | ||||
|     }; | ||||
|   created() { | ||||
|     this.mentionsContext = provide('mentionsContext', this); | ||||
|   }, | ||||
|   data() { | ||||
|     const { value = '', defaultValue = '' } = this.$props; | ||||
|  | @ -53,7 +42,7 @@ const Mentions = { | |||
|     }, | ||||
|   }, | ||||
|   updated() { | ||||
|     this.$nextTick(() => { | ||||
|     nextTick(() => { | ||||
|       const { measuring } = this.$data; | ||||
| 
 | ||||
|       // Sync measure div top with textarea for rc-trigger usage | ||||
|  | @ -215,8 +204,7 @@ const Mentions = { | |||
|       const { filterOption, children = [] } = this.$props; | ||||
|       const list = (Array.isArray(children) ? children : [children]) | ||||
|         .map(item => { | ||||
|           const children = getSlots(item).default; | ||||
|           return { ...getOptionProps(item), children }; | ||||
|           return { ...getOptionProps(item), children: item.children.default?.() || item.children }; | ||||
|         }) | ||||
|         .filter(option => { | ||||
|           /** Return all result if `filterOption` is false. */ | ||||
|  | @ -283,21 +271,17 @@ const Mentions = { | |||
|         <textarea | ||||
|           ref="textarea" | ||||
|           {...{ | ||||
|             directives: [{ name: 'ant-input' }], | ||||
|             attrs: { ...inputProps, ...this.$attrs }, | ||||
|             domProps: { | ||||
|               value, | ||||
|             }, | ||||
|             on: { | ||||
|               ...getListeners(this), | ||||
|               select: noop, | ||||
|               change: noop, | ||||
|               input: this.onChange, | ||||
|               keydown: this.onKeyDown, | ||||
|               keyup: this.onKeyUp, | ||||
|               blur: this.onInputBlur, | ||||
|             }, | ||||
|             ...inputProps, | ||||
|             ...this.$attrs, | ||||
|             onChange: noop, | ||||
|             onSelect: noop, | ||||
|           }} | ||||
|           value={value} | ||||
|           onInput={this.onChange} | ||||
|           onBlur={this.onInputBlur} | ||||
|           onKeyDown={this.onKeyDown} | ||||
|           onKeyUp={this.onKeyUp} | ||||
|           onFocus={this.onInputFocus} | ||||
|         /> | ||||
|         {measuring && ( | ||||
|           <div ref="measure" class={`${prefixCls}-measure`}> | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ const Menu = { | |||
|     selectable: PropTypes.bool.def(true), | ||||
|   }, | ||||
|   mixins: [BaseMixin], | ||||
| 
 | ||||
|   data() { | ||||
|     const props = getOptionProps(this); | ||||
|     let selectedKeys = props.defaultSelectedKeys; | ||||
|  |  | |||
|  | @ -281,7 +281,7 @@ export default { | |||
|             align={align} | ||||
|             onAlign={this.onAlign} | ||||
|           > | ||||
|             <PopupInner {...popupInnerProps}>{$slots.default && $slots.default()}</PopupInner> | ||||
|             <PopupInner {...popupInnerProps}>{$slots.default?.()}</PopupInner> | ||||
|           </Align> | ||||
|         </Transition> | ||||
|       ); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Amour1688
						Amour1688