fix: select input
							parent
							
								
									6e2c5a6a83
								
							
						
					
					
						commit
						82f28ce3d0
					
				|  | @ -1,6 +1,8 @@ | |||
| import type { PropType } from 'vue'; | ||||
| import { defineComponent, shallowRef, ref, watch } from 'vue'; | ||||
| import { computed, defineComponent, shallowRef, ref, watch } from 'vue'; | ||||
| import PropTypes from './vue-types'; | ||||
| import type { BaseInputInnerExpose } from './BaseInputInner'; | ||||
| import BaseInputInner from './BaseInputInner'; | ||||
| 
 | ||||
| export interface BaseInputExpose { | ||||
|   focus: () => void; | ||||
|  | @ -30,6 +32,8 @@ const BaseInput = defineComponent({ | |||
|       default: 'input', | ||||
|     }, | ||||
|     size: PropTypes.string, | ||||
|     style: PropTypes.style, | ||||
|     class: PropTypes.string, | ||||
|   }, | ||||
|   emits: [ | ||||
|     'change', | ||||
|  | @ -40,9 +44,11 @@ const BaseInput = defineComponent({ | |||
|     'compositionstart', | ||||
|     'compositionend', | ||||
|     'keyup', | ||||
|     'paste', | ||||
|     'mousedown', | ||||
|   ], | ||||
|   setup(props, { emit, attrs, expose }) { | ||||
|     const inputRef = shallowRef(null); | ||||
|     const inputRef = shallowRef<BaseInputInnerExpose>(null); | ||||
|     const renderValue = ref(); | ||||
|     const isComposing = ref(false); | ||||
|     watch( | ||||
|  | @ -115,19 +121,26 @@ const BaseInput = defineComponent({ | |||
|     expose({ | ||||
|       focus, | ||||
|       blur, | ||||
|       input: inputRef, | ||||
|       input: computed(() => inputRef.value?.input), | ||||
|       setSelectionRange, | ||||
|       select, | ||||
|       getSelectionStart: () => inputRef.value?.selectionStart, | ||||
|       getSelectionEnd: () => inputRef.value?.selectionEnd, | ||||
|       getScrollTop: () => inputRef.value?.scrollTop, | ||||
|       getSelectionStart: () => inputRef.value?.getSelectionStart(), | ||||
|       getSelectionEnd: () => inputRef.value?.getSelectionEnd(), | ||||
|       getScrollTop: () => inputRef.value?.getScrollTop(), | ||||
|     }); | ||||
|     const handleMousedown = (e: MouseEvent) => { | ||||
|       emit('mousedown', e); | ||||
|     }; | ||||
|     const handlePaste = (e: ClipboardEvent) => { | ||||
|       emit('paste', e); | ||||
|     }; | ||||
|     return () => { | ||||
|       const { tag: Tag, ...restProps } = props; | ||||
|       const { tag: Tag, style, ...restProps } = props; | ||||
|       return ( | ||||
|         <Tag | ||||
|         <BaseInputInner | ||||
|           {...restProps} | ||||
|           {...attrs} | ||||
|           style={JSON.stringify(style)} | ||||
|           onInput={handleInput} | ||||
|           onChange={handleChange} | ||||
|           onBlur={handleBlur} | ||||
|  | @ -138,6 +151,8 @@ const BaseInput = defineComponent({ | |||
|           onCompositionend={onCompositionend} | ||||
|           onKeyup={handleKeyUp} | ||||
|           onKeydown={handleKeyDown} | ||||
|           onPaste={handlePaste} | ||||
|           onMousedown={handleMousedown} | ||||
|         /> | ||||
|       ); | ||||
|     }; | ||||
|  |  | |||
|  | @ -0,0 +1,96 @@ | |||
| import type { PropType } from 'vue'; | ||||
| import { defineComponent, shallowRef } from 'vue'; | ||||
| import PropTypes from './vue-types'; | ||||
| 
 | ||||
| export interface BaseInputInnerExpose { | ||||
|   focus: () => void; | ||||
|   blur: () => void; | ||||
|   input: HTMLInputElement | HTMLTextAreaElement | null; | ||||
|   setSelectionRange: ( | ||||
|     start: number, | ||||
|     end: number, | ||||
|     direction?: 'forward' | 'backward' | 'none', | ||||
|   ) => void; | ||||
|   select: () => void; | ||||
|   getSelectionStart: () => number | null; | ||||
|   getSelectionEnd: () => number | null; | ||||
|   getScrollTop: () => number | null; | ||||
|   setScrollTop: (scrollTop: number) => void; | ||||
| } | ||||
| const BaseInputInner = defineComponent({ | ||||
|   compatConfig: { MODE: 3 }, | ||||
|   // inheritAttrs: false, | ||||
|   props: { | ||||
|     disabled: PropTypes.looseBool, | ||||
|     type: PropTypes.string, | ||||
|     value: PropTypes.any, | ||||
|     tag: { | ||||
|       type: String as PropType<'input' | 'textarea'>, | ||||
|       default: 'input', | ||||
|     }, | ||||
|     size: PropTypes.string, | ||||
|     onChange: Function as PropType<(e: Event) => void>, | ||||
|     onInput: Function as PropType<(e: Event) => void>, | ||||
|     onBlur: Function as PropType<(e: Event) => void>, | ||||
|     onFocus: Function as PropType<(e: Event) => void>, | ||||
|     onKeydown: Function as PropType<(e: Event) => void>, | ||||
|     onCompositionstart: Function as PropType<(e: Event) => void>, | ||||
|     onCompositionend: Function as PropType<(e: Event) => void>, | ||||
|     onKeyup: Function as PropType<(e: Event) => void>, | ||||
|     onPaste: Function as PropType<(e: Event) => void>, | ||||
|     onMousedown: Function as PropType<(e: Event) => void>, | ||||
|   }, | ||||
|   emits: [ | ||||
|     'change', | ||||
|     'input', | ||||
|     'blur', | ||||
|     'keydown', | ||||
|     'focus', | ||||
|     'compositionstart', | ||||
|     'compositionend', | ||||
|     'keyup', | ||||
|     'paste', | ||||
|     'mousedown', | ||||
|   ], | ||||
|   setup(props, { expose }) { | ||||
|     const inputRef = shallowRef(null); | ||||
| 
 | ||||
|     const focus = () => { | ||||
|       if (inputRef.value) { | ||||
|         inputRef.value.focus(); | ||||
|       } | ||||
|     }; | ||||
|     const blur = () => { | ||||
|       if (inputRef.value) { | ||||
|         inputRef.value.blur(); | ||||
|       } | ||||
|     }; | ||||
|     const setSelectionRange = ( | ||||
|       start: number, | ||||
|       end: number, | ||||
|       direction?: 'forward' | 'backward' | 'none', | ||||
|     ) => { | ||||
|       inputRef.value?.setSelectionRange(start, end, direction); | ||||
|     }; | ||||
| 
 | ||||
|     const select = () => { | ||||
|       inputRef.value?.select(); | ||||
|     }; | ||||
|     expose({ | ||||
|       focus, | ||||
|       blur, | ||||
|       input: inputRef, | ||||
|       setSelectionRange, | ||||
|       select, | ||||
|       getSelectionStart: () => inputRef.value?.selectionStart, | ||||
|       getSelectionEnd: () => inputRef.value?.selectionEnd, | ||||
|       getScrollTop: () => inputRef.value?.scrollTop, | ||||
|     }); | ||||
|     return () => { | ||||
|       const { tag: Tag, value, ...restProps } = props; | ||||
|       return <Tag {...restProps} ref={inputRef} value={value} />; | ||||
|     }; | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| export default BaseInputInner; | ||||
|  | @ -48,7 +48,6 @@ const Input = defineComponent({ | |||
|   setup(props) { | ||||
|     let blurTimeout = null; | ||||
|     const VCSelectContainerEvent = inject('VCSelectContainerEvent') as any; | ||||
| 
 | ||||
|     return () => { | ||||
|       const { | ||||
|         prefixCls, | ||||
|  | @ -97,6 +96,7 @@ const Input = defineComponent({ | |||
|             ref: inputRef, | ||||
|             disabled, | ||||
|             tabindex, | ||||
|             lazy: false, | ||||
|             autocomplete: autocomplete || 'off', | ||||
|             autofocus, | ||||
|             class: classNames(`${prefixCls}-selection-search-input`, inputNode?.props?.class), | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import TransBtn from '../TransBtn'; | |||
| import type { InnerSelectorProps } from './interface'; | ||||
| import Input from './Input'; | ||||
| import type { Ref, PropType } from 'vue'; | ||||
| import { computed, defineComponent, onMounted, shallowRef, watch } from 'vue'; | ||||
| import { ref, watchEffect, computed, defineComponent, onMounted, shallowRef, watch } from 'vue'; | ||||
| import classNames from '../../_util/classNames'; | ||||
| import pickAttrs from '../../_util/pickAttrs'; | ||||
| import PropTypes from '../../_util/vue-types'; | ||||
|  | @ -24,6 +24,8 @@ type SelectorProps = InnerSelectorProps & { | |||
|   tagRender?: (props: CustomTagProps) => VueNode; | ||||
|   onToggleOpen: any; | ||||
| 
 | ||||
|   compositionStatus: boolean; | ||||
| 
 | ||||
|   // Motion | ||||
|   choiceTransitionName?: string; | ||||
| 
 | ||||
|  | @ -46,7 +48,7 @@ const props = { | |||
|   autocomplete: String, | ||||
|   activeDescendantId: String, | ||||
|   tabindex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), | ||||
| 
 | ||||
|   compositionStatus: Boolean, | ||||
|   removeIcon: PropTypes.any, | ||||
|   choiceTransitionName: String, | ||||
| 
 | ||||
|  | @ -91,11 +93,14 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
|       () => | ||||
|         props.mode === 'tags' || ((props.showSearch && (props.open || focused.value)) as boolean), | ||||
|     ); | ||||
| 
 | ||||
|     const targetValue = ref(''); | ||||
|     watchEffect(() => { | ||||
|       targetValue.value = inputValue.value; | ||||
|     }); | ||||
|     // We measure width and set to the input immediately | ||||
|     onMounted(() => { | ||||
|       watch( | ||||
|         inputValue, | ||||
|         targetValue, | ||||
|         () => { | ||||
|           inputWidth.value = measureRef.value.scrollWidth; | ||||
|         }, | ||||
|  | @ -202,6 +207,14 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
|       return defaultRenderSelector(content, content, false); | ||||
|     } | ||||
| 
 | ||||
|     const handleInput = (e: Event) => { | ||||
|       const composing = (e.target as any).composing; | ||||
|       targetValue.value = (e.target as any).value; | ||||
|       if (!composing) { | ||||
|         props.onInputChange(e); | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     return () => { | ||||
|       const { | ||||
|         id, | ||||
|  | @ -215,14 +228,13 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
|         autocomplete, | ||||
|         activeDescendantId, | ||||
|         tabindex, | ||||
|         onInputChange, | ||||
|         compositionStatus, | ||||
|         onInputPaste, | ||||
|         onInputKeyDown, | ||||
|         onInputMouseDown, | ||||
|         onInputCompositionStart, | ||||
|         onInputCompositionEnd, | ||||
|       } = props; | ||||
| 
 | ||||
|       // >>> Input Node | ||||
|       const inputNode = ( | ||||
|         <div | ||||
|  | @ -241,10 +253,10 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
|             autocomplete={autocomplete} | ||||
|             editable={inputEditable.value} | ||||
|             activeDescendantId={activeDescendantId} | ||||
|             value={inputValue.value} | ||||
|             value={targetValue.value} | ||||
|             onKeydown={onInputKeyDown} | ||||
|             onMousedown={onInputMouseDown} | ||||
|             onChange={onInputChange} | ||||
|             onChange={handleInput} | ||||
|             onPaste={onInputPaste} | ||||
|             onCompositionstart={onInputCompositionStart} | ||||
|             onCompositionend={onInputCompositionEnd} | ||||
|  | @ -256,7 +268,7 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
| 
 | ||||
|           {/* Measure Node */} | ||||
|           <span ref={measureRef} class={`${selectionPrefixCls.value}-search-mirror`} aria-hidden> | ||||
|             {inputValue.value}  | ||||
|             {targetValue.value}  | ||||
|           </span> | ||||
|         </div> | ||||
|       ); | ||||
|  | @ -277,7 +289,7 @@ const SelectSelector = defineComponent<SelectorProps>({ | |||
|       return ( | ||||
|         <> | ||||
|           {selectionNode} | ||||
|           {!values.length && !inputValue.value && ( | ||||
|           {!values.length && !inputValue.value && !compositionStatus && ( | ||||
|             <span class={`${selectionPrefixCls.value}-placeholder`}>{placeholder}</span> | ||||
|           )} | ||||
|         </> | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import pickAttrs from '../../_util/pickAttrs'; | ||||
| import Input from './Input'; | ||||
| import type { InnerSelectorProps } from './interface'; | ||||
| import { Fragment, Ref, computed, defineComponent, shallowRef, watch } from 'vue'; | ||||
| import { Fragment, computed, defineComponent, shallowRef, watch } from 'vue'; | ||||
| import PropTypes from '../../_util/vue-types'; | ||||
| import type { VueNode } from '../../_util/type'; | ||||
| import useInjectLegacySelectContext from '../../vc-tree-select/LegacyContext'; | ||||
|  | @ -10,8 +10,6 @@ interface SelectorProps extends InnerSelectorProps { | |||
|   inputElement: VueNode; | ||||
|   activeValue: string; | ||||
|   optionLabelRender: Function; | ||||
| 
 | ||||
|   // placeholder | ||||
|   compositionStatus: boolean; | ||||
| } | ||||
| const props = { | ||||
|  | @ -92,6 +90,13 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|         </span> | ||||
|       ); | ||||
|     }; | ||||
|     const handleInput = (e: Event) => { | ||||
|       const composing = (e.target as any).composing; | ||||
|       if (!composing) { | ||||
|         inputChanged.value = true; | ||||
|         props.onInputChange(e); | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     return () => { | ||||
|       const { | ||||
|  | @ -109,7 +114,6 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|         optionLabelRender, | ||||
|         onInputKeyDown, | ||||
|         onInputMouseDown, | ||||
|         onInputChange, | ||||
|         onInputPaste, | ||||
|         onInputCompositionStart, | ||||
|         onInputCompositionEnd, | ||||
|  | @ -153,10 +157,7 @@ const SingleSelector = defineComponent<SelectorProps>({ | |||
|               value={inputValue.value} | ||||
|               onKeydown={onInputKeyDown} | ||||
|               onMousedown={onInputMouseDown} | ||||
|               onChange={e => { | ||||
|                 inputChanged.value = true; | ||||
|                 onInputChange(e as any); | ||||
|               }} | ||||
|               onChange={handleInput} | ||||
|               onPaste={onInputPaste} | ||||
|               onCompositionstart={onInputCompositionStart} | ||||
|               onCompositionend={onInputCompositionEnd} | ||||
|  |  | |||
|  | @ -124,7 +124,7 @@ const Selector = defineComponent<SelectorProps>({ | |||
|   } as any, | ||||
|   setup(props, { expose }) { | ||||
|     const inputRef = createRef(); | ||||
|     let compositionStatus = ref(false); | ||||
|     const compositionStatus = ref(false); | ||||
| 
 | ||||
|     // ====================== Input ====================== | ||||
|     const [getInputMouseDown, setInputMouseDown] = useLock(0); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou