element-plus
Version:
A Component Library for Vue 3
1 lines • 10.8 kB
Source Map (JSON)
{"version":3,"file":"use-input-tag.mjs","names":[],"sources":["../../../../../../../packages/components/input-tag/src/composables/use-input-tag.ts"],"sourcesContent":["import { computed, ref, shallowRef, watch } from 'vue'\nimport {\n CHANGE_EVENT,\n EVENT_CODE,\n INPUT_EVENT,\n UPDATE_MODEL_EVENT,\n} from '@element-plus/constants'\nimport {\n NOOP,\n ensureArray,\n getEventCode,\n isAndroid,\n isUndefined,\n} from '@element-plus/utils'\nimport { useComposition, useFocusController } from '@element-plus/hooks'\nimport { useFormDisabled, useFormSize } from '@element-plus/components/form'\n\nimport type { TooltipInstance } from '@element-plus/components/tooltip'\nimport type { EmitFn } from '@element-plus/utils'\nimport type { FormItemContext } from '@element-plus/components/form'\nimport type { InputTagEmits, InputTagProps } from '../input-tag'\n\ninterface UseInputTagOptions {\n props: InputTagProps\n emit: EmitFn<InputTagEmits>\n formItem?: FormItemContext\n}\n\nexport function useInputTag({ props, emit, formItem }: UseInputTagOptions) {\n const disabled = useFormDisabled()\n const size = useFormSize()\n\n const inputRef = shallowRef<HTMLInputElement>()\n const inputValue = ref<string>()\n const tagTooltipRef = ref<TooltipInstance>()\n\n const tagSize = computed(() => {\n return ['small'].includes(size.value) ? 'small' : 'default'\n })\n const placeholder = computed(() => {\n return props.modelValue?.length ? undefined : props.placeholder\n })\n const closable = computed(() => !(props.readonly || disabled.value))\n const inputLimit = computed(() => {\n return isUndefined(props.max)\n ? false\n : (props.modelValue?.length ?? 0) >= props.max\n })\n const showTagList = computed(() => {\n return props.collapseTags\n ? props.modelValue?.slice(0, props.maxCollapseTags)\n : props.modelValue\n })\n const collapseTagList = computed(() => {\n return props.collapseTags\n ? props.modelValue?.slice(props.maxCollapseTags)\n : []\n })\n\n const addTagsEmit = (value: string | string[]) => {\n const list = [...(props.modelValue ?? []), ...ensureArray(value)]\n\n emit(UPDATE_MODEL_EVENT, list)\n emit(CHANGE_EVENT, list)\n emit('add-tag', value)\n inputValue.value = undefined\n }\n\n const getDelimitedTags = (input: string) => {\n const parts = input.split(props.delimiter!)\n const tags =\n parts.length > 1 ? parts.map((val) => val.trim()).filter(Boolean) : []\n if (props.max) {\n const maxInsert = props.max - (props.modelValue?.length ?? 0)\n tags.splice(maxInsert)\n }\n return tags.length === 1 ? tags[0] : tags\n }\n\n const handlePaste = (event: ClipboardEvent) => {\n const pasted = event.clipboardData?.getData('text')\n if (props.readonly || inputLimit.value || !props.delimiter || !pasted) {\n return\n }\n const {\n selectionStart = 0,\n selectionEnd = 0,\n value,\n } = event.target as HTMLInputElement\n const nextValue =\n value.slice(0, selectionStart!) + pasted + value.slice(selectionEnd!)\n const tags = getDelimitedTags(nextValue)\n if (tags.length) {\n addTagsEmit(tags)\n emit(INPUT_EVENT, nextValue)\n event.preventDefault()\n }\n }\n\n const handleInput = (event: Event) => {\n if (inputLimit.value) {\n inputValue.value = undefined\n return\n }\n\n if (isComposing.value) return\n if (props.delimiter && inputValue.value) {\n const tags = getDelimitedTags(inputValue.value)\n if (tags.length) {\n addTagsEmit(tags)\n }\n }\n emit(INPUT_EVENT, (event.target as HTMLInputElement).value)\n }\n\n const handleKeydown = (event: KeyboardEvent) => {\n if (isComposing.value) return\n const code = getEventCode(event)\n\n switch (code) {\n case props.trigger:\n event.preventDefault()\n event.stopPropagation()\n handleAddTag()\n break\n case EVENT_CODE.numpadEnter:\n if (props.trigger === EVENT_CODE.enter) {\n event.preventDefault()\n event.stopPropagation()\n handleAddTag()\n }\n break\n case EVENT_CODE.backspace:\n if (!inputValue.value && props.modelValue?.length) {\n event.preventDefault()\n event.stopPropagation()\n handleRemoveTag(props.modelValue.length - 1)\n }\n break\n }\n }\n\n const handleKeyup = (event: KeyboardEvent) => {\n if (isComposing.value || !isAndroid()) return\n const code = getEventCode(event)\n\n switch (code) {\n case EVENT_CODE.space:\n if (props.trigger === EVENT_CODE.space) {\n event.preventDefault()\n event.stopPropagation()\n handleAddTag()\n }\n break\n }\n }\n\n const handleAddTag = () => {\n const value = inputValue.value?.trim()\n if (!value || inputLimit.value) return\n addTagsEmit(value)\n }\n\n const handleRemoveTag = (index: number) => {\n const value = (props.modelValue ?? []).slice()\n const [item] = value.splice(index, 1)\n\n emit(UPDATE_MODEL_EVENT, value)\n emit(CHANGE_EVENT, value)\n emit('remove-tag', item, index)\n }\n\n const handleClear = () => {\n inputValue.value = undefined\n emit(UPDATE_MODEL_EVENT, undefined)\n emit(CHANGE_EVENT, undefined)\n emit('clear')\n }\n\n const handleDragged = (\n draggingIndex: number,\n dropIndex: number,\n type: 'before' | 'after'\n ) => {\n const value = (props.modelValue ?? []).slice()\n const [draggedItem] = value.splice(draggingIndex, 1)\n const step =\n dropIndex > draggingIndex && type === 'before'\n ? -1\n : dropIndex < draggingIndex && type === 'after'\n ? 1\n : 0\n\n value.splice(dropIndex + step, 0, draggedItem)\n emit(UPDATE_MODEL_EVENT, value)\n emit(CHANGE_EVENT, value)\n emit('drag-tag', draggingIndex, dropIndex + step, draggedItem)\n }\n\n const focus = () => {\n inputRef.value?.focus()\n }\n\n const blur = () => {\n inputRef.value?.blur()\n }\n\n const { wrapperRef, isFocused } = useFocusController(inputRef, {\n disabled,\n beforeBlur(event) {\n return tagTooltipRef.value?.isFocusInsideContent(event)\n },\n afterBlur() {\n if (props.saveOnBlur) {\n handleAddTag()\n } else {\n inputValue.value = undefined\n }\n\n if (props.validateEvent) {\n formItem?.validate?.('blur').catch(NOOP)\n }\n },\n })\n\n const {\n isComposing,\n handleCompositionStart,\n handleCompositionUpdate,\n handleCompositionEnd,\n } = useComposition({ afterComposition: handleInput })\n\n watch(\n () => props.modelValue,\n () => {\n if (props.validateEvent) {\n formItem?.validate?.(CHANGE_EVENT).catch(NOOP)\n }\n }\n )\n\n return {\n inputRef,\n wrapperRef,\n tagTooltipRef,\n isFocused,\n isComposing,\n inputValue,\n size,\n tagSize,\n placeholder,\n closable,\n disabled,\n inputLimit,\n showTagList,\n collapseTagList,\n handleDragged,\n handlePaste,\n handleInput,\n handleKeydown,\n handleKeyup,\n handleAddTag,\n handleRemoveTag,\n handleClear,\n handleCompositionStart,\n handleCompositionUpdate,\n handleCompositionEnd,\n focus,\n blur,\n }\n}\n"],"mappings":"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"}