UNPKG

hongluan-ui

Version:
1 lines 19.6 kB
{"version":3,"file":"input2.mjs","sources":["../../../../../../packages/components/input/src/input.vue"],"sourcesContent":["<template>\n <div\n v-bind=\"containerAttrs\"\n :class=\"[\n namespace,\n inputSize ? inputSize : '',\n `as-${nativeType}`,\n type ? type : '',\n nativeType === 'hidden' ? 'display-none' : '',\n {\n 'is-disabled': inputDisabled,\n 'is-exceed': inputExceed,\n 'is-focus': isFocused,\n 'has-password-visible': getPwdVisible(),\n 'has-suffix': getSuffixVisible(),\n 'round': round,\n 'fill': inputFill,\n 'block': block,\n 'thin' : thin\n },\n $attrs.class\n ]\"\n :style=\"$attrs.style\"\n :role=\"containerRole\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <template v-if=\"nativeType !== 'textarea'\">\n <div ref=\"wrapperRef\" class=\"input-wrapper\">\n <slot name=\"tags\"></slot>\n <input\n v-if=\"nativeType !== 'textarea'\"\n :id=\"inputId\"\n ref=\"input\"\n v-bind=\"attrs\"\n :minlength=\"minlength\"\n :maxlength=\"maxlength\"\n :type=\"showPassword ? (passwordVisible ? 'text': 'password') : nativeType\"\n :disabled=\"inputDisabled\"\n :readonly=\"readonly\"\n :autocomplete=\"autocomplete\"\n :tabindex=\"tabindex\"\n :aria-label=\"label || ariaLabel\"\n :placeholder=\"placeholder\"\n :style=\"inputStyle\"\n :form=\"form\"\n class=\"input-inner\"\n :autofocus=\"autofocus\"\n @compositionstart=\"handleCompositionStart\"\n @compositionupdate=\"handleCompositionUpdate\"\n @compositionend=\"handleCompositionEnd\"\n @input=\"handleInput\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n @change=\"handleChange\"\n @keydown=\"handleKeydown\"\n >\n <span v-if=\"$slots.prefix\" class=\"input-affixe prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n\n <span v-if=\"getSuffixVisible()\" class=\"input-affixe suffix\">\n <template v-if=\"!showClear\">\n <slot name=\"suffix\"></slot>\n </template>\n <hl-icon v-if=\"showClear\" class=\"input-close\" @mousedown.prevent @click=\"clear\">\n <system-close />\n </hl-icon>\n </span>\n <span v-if=\"getPwdVisible()\" class=\"input-affixe password-visible\">\n <hl-icon v-if=\"showPwdVisible\" @click=\"handlePasswordVisible\">\n <system-hidden v-if=\"passwordVisible\" />\n <system-show v-if=\"!passwordVisible\" />\n </hl-icon>\n </span>\n <span v-if=\"isWordLimitVisible\" :style=\"countStyle\" class=\"input-count\">\n {{ textLength }} / {{ maxlength }}\n </span>\n </div>\n </template>\n <textarea\n v-else\n :id=\"inputId\"\n ref=\"textarea\"\n :class=\"[`input-inner`, type, isFocused ? 'is-focus' : '']\"\n v-bind=\"attrs\"\n :minlength=\"minlength\"\n :maxlength=\"maxlength\"\n :tabindex=\"tabindex\"\n :disabled=\"inputDisabled\"\n :readonly=\"readonly\"\n :autocomplete=\"autocomplete\"\n :style=\"textareaStyle\"\n :aria-label=\"label || ariaLabel\"\n :placeholder=\"placeholder\"\n :form=\"form\"\n :rows=\"rows\"\n :autofocus=\"autofocus\"\n @compositionstart=\"handleCompositionStart\"\n @compositionupdate=\"handleCompositionUpdate\"\n @compositionend=\"handleCompositionEnd\"\n @input=\"handleInput\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n @change=\"handleChange\"\n @keydown=\"handleKeydown\"\n >\n </textarea>\n <span\n v-if=\"isWordLimitVisible && nativeType === 'textarea'\"\n :style=\"countStyle\"\n class=\"input-count\"\n >\n {{ textLength }} / {{ maxlength }}\n </span>\n </div>\n</template>\n\n<script lang='ts'>\nimport {\n defineComponent,\n inject,\n computed,\n watch,\n nextTick,\n ref,\n shallowRef,\n onMounted,\n} from 'vue'\nimport { isNil } from 'lodash-unified'\nimport { useAttrs, useComposition, useConsistentProp, useCursor, useNamespace, useFormItemInputId, useFocusController } from '@hongluan-ui/hooks'\nimport { UPDATE_MODEL_EVENT } from '@hongluan-ui/constants'\nimport { isClient, isObject, debugWarn } from '@hongluan-ui/utils'\nimport { useResizeObserver } from '@vueuse/core'\nimport { formContextKey, formItemContextKey, FormItemEvents } from '@hongluan-ui/tokens'\nimport HlIcon from '@hongluan-ui/components/icon'\nimport { SystemClose, SystemShow, SystemHidden } from '@hongluan-ui/components/system-icon'\nimport { calcTextareaHeight } from './utils'\nimport { inputProps } from './input'\n\nimport type { FormContext, FormItemContext } from '@hongluan-ui/tokens'\nimport type { StyleValue } from '@hongluan-ui/utils'\n\ntype TargetElement = HTMLInputElement | HTMLTextAreaElement\n\nexport default defineComponent({\n name: 'Input',\n components: {\n HlIcon,\n SystemClose,\n SystemShow,\n SystemHidden,\n\n },\n inheritAttrs: false,\n props: inputProps,\n emits: [\n UPDATE_MODEL_EVENT, 'input', 'change', 'focus', 'blur', 'clear',\n 'mouseleave', 'mouseenter', 'keydown', 'compositionstart', 'compositionupdate', 'compositionend',\n ],\n setup(props, { emit, slots, attrs: rawAttrs }) {\n const { namespace } = useNamespace('input')\n const containerAttrs = computed<Record<string, unknown>>(() => {\n const comboBoxAttrs: Record<string, any> = {}\n if (props.containerRole === 'combobox') {\n comboBoxAttrs['aria-haspopup'] = rawAttrs['aria-haspopup']\n comboBoxAttrs['aria-owns'] = rawAttrs['aria-owns']\n comboBoxAttrs['aria-expanded'] = rawAttrs['aria-expanded']\n }\n return comboBoxAttrs\n })\n\n const attrs = useAttrs({\n excludeKeys: computed<string[]>(() => {\n return Object.keys(containerAttrs.value)\n }),\n })\n\n const form = inject(formContextKey, {} as FormContext)\n const formItem = inject(formItemContextKey, {} as FormItemContext)\n\n const input = ref<HTMLInputElement>()\n const textarea = ref<HTMLTextAreaElement>()\n const countStyle = ref<StyleValue>()\n // const focused = ref(false)\n const hovering = ref(false)\n const passwordVisible = ref(false)\n const _textareaCalcStyle = shallowRef(props.inputStyle)\n\n const inputOrTextarea = computed(() => input.value || textarea.value)\n const { wrapperRef, isFocused, handleFocus, handleBlur } = useFocusController(\n inputOrTextarea,\n {\n afterBlur() {\n if (props.validateEvent) {\n formItem?.validate?.('blur').catch(err => debugWarn(err))\n }\n },\n },\n )\n\n const { size: inputSize, disabled: inputDisabled, fill: inputFill } = useConsistentProp()\n const needStatusIcon = computed(() => form.statusIcon)\n const validateState = computed(() => formItem.validateState || '')\n const textareaStyle = computed<StyleValue>(() => [\n props.inputStyle,\n _textareaCalcStyle.value,\n { resize: props.resize },\n ])\n const nativeInputValue = computed(() => isNil(props.modelValue) ? '' : String(props.modelValue))\n const showClear = computed(() => {\n return props.clearable &&\n !inputDisabled.value &&\n !props.readonly &&\n !!nativeInputValue.value &&\n (isFocused.value || hovering.value)\n })\n const showPwdVisible = computed(() => {\n return props.showPassword &&\n !inputDisabled.value &&\n !props.readonly &&\n !!nativeInputValue.value &&\n (!!nativeInputValue.value || isFocused.value)\n })\n\n const isWordLimitVisible = computed(() => {\n return props.showWordLimit &&\n !!props.maxlength &&\n (props.nativeType === 'text' || props.nativeType === 'textarea') &&\n !inputDisabled.value &&\n !props.readonly &&\n !props.showPassword\n })\n const textLength = computed(() => nativeInputValue.value.length)\n const inputExceed = computed(() => {\n // show exceed style if length of initial value greater then maxlength\n return isWordLimitVisible.value && textLength.value > Number(props.maxlength)\n })\n\n const [recordCursor, setCursor] = useCursor(input)\n const { inputId } = useFormItemInputId(props, {\n formItemContext: formItem,\n })\n\n useResizeObserver(textarea, entries => {\n onceInitSizeTextarea()\n if (!isWordLimitVisible.value || props.resize !== 'both') return\n const entry = entries[0]\n const { width } = entry.contentRect\n countStyle.value = {\n /** right: 100% - width + padding(15) + right(6) */\n right: `calc(100% - ${width + 15 + 6}px)`,\n }\n })\n\n const resizeTextarea = () => {\n const { nativeType, autosize } = props\n\n if (!isClient || nativeType !== 'textarea' || !textarea.value) return\n\n if (autosize) {\n const minRows = isObject(autosize) ? autosize.minRows : void 0\n const maxRows = isObject(autosize) ? autosize.maxRows : void 0\n const textareaStyle = calcTextareaHeight(textarea.value, minRows, maxRows)\n\n // If the scrollbar is displayed, the height of the textarea needs more space than the calculated height.\n // If set textarea height in this case, the scrollbar will not hide.\n // So we need to hide scrollbar first, and reset it in next tick.\n // see https://github.com/element-plus/element-plus/issues/8825\n\n _textareaCalcStyle.value = {\n overflowY: 'hidden',\n ...textareaStyle,\n }\n\n nextTick(() => {\n // NOTE: Force repaint to make sure the style set above is applied.\n textarea.value!.offsetHeight\n _textareaCalcStyle.value = textareaStyle\n })\n } else {\n _textareaCalcStyle.value = {\n minHeight: calcTextareaHeight(textarea.value).minHeight,\n }\n }\n }\n\n const createOnceInitResize = (resizeTextarea: () => void) => {\n let isInit = false\n return () => {\n if (isInit || !props.autosize) return\n const isElHidden = textarea.value?.offsetParent === null\n if (!isElHidden) {\n resizeTextarea()\n isInit = true\n }\n }\n }\n // fix: https://github.com/element-plus/element-plus/issues/12074\n const onceInitSizeTextarea = createOnceInitResize(resizeTextarea)\n\n const setNativeInputValue = () => {\n const input = inputOrTextarea.value\n const formatterValue = props.formatter\n ? props.formatter(nativeInputValue.value)\n : nativeInputValue.value\n if (!input || input.value === formatterValue) return\n input.value = formatterValue\n }\n\n const handleInput = (event: Event) => {\n recordCursor()\n\n let { value } = event.target as TargetElement\n\n if (props.formatter) {\n value = props.parser ? props.parser(value) : value\n }\n\n // should not emit input during composition\n // see: https://github.com/ElemeFE/element/issues/10516\n if (isComposing.value) return\n\n // hack for https://github.com/ElemeFE/element/issues/8548\n // should remove the following line when we don't support IE\n if (value === nativeInputValue.value) {\n setNativeInputValue()\n return\n }\n\n emit(UPDATE_MODEL_EVENT, value)\n emit('input', value, event)\n\n // ensure native input value is controlled\n // see: https://github.com/ElemeFE/element/issues/12850\n nextTick(setNativeInputValue)\n setCursor()\n }\n\n const handleChange = (event: Event) => {\n emit('change', (event.target as TargetElement).value)\n }\n\n const focus = () => {\n // see: https://github.com/ElemeFE/element/issues/18573\n nextTick(() => {\n inputOrTextarea.value?.focus()\n })\n }\n\n const blur = () => {\n inputOrTextarea.value?.blur()\n }\n\n // const handleFocus = (event: FocusEvent) => {\n // focused.value = true\n // emit('focus', event)\n // }\n\n // const handleBlur = (event: FocusEvent) => {\n // focused.value = false\n // emit('blur', event)\n // if (props.validateEvent) {\n // formItem.validate?.(FormItemEvents.blur).catch(err => debugWarn(err))\n // }\n // }\n\n const select = () => {\n inputOrTextarea.value?.select()\n }\n\n const {\n isComposing,\n handleCompositionStart,\n handleCompositionUpdate,\n handleCompositionEnd,\n } = useComposition({ emit, afterComposition: handleInput })\n\n const clear = () => {\n emit(UPDATE_MODEL_EVENT, '')\n emit('change', '')\n emit('clear')\n emit('input', '')\n }\n\n const handlePasswordVisible = () => {\n passwordVisible.value = !passwordVisible.value\n focus()\n }\n\n const getSuffixVisible = () => {\n return slots.suffix ||\n props.clearable ||\n // showClear.value ||\n // showPwdVisible.value ||\n (validateState.value && needStatusIcon.value)\n }\n\n const getPwdVisible = () => {\n return props.showPassword ||\n // showClear.value ||\n // showPwdVisible.value ||\n (validateState.value && needStatusIcon.value)\n }\n\n watch(() => props.modelValue, () => {\n nextTick(() => resizeTextarea())\n if (props.validateEvent) {\n formItem.validate?.(FormItemEvents.change).catch(err => debugWarn(err))\n }\n })\n\n // native input value is set explicitly\n // do not use v-model / :value in template\n // see: https://github.com/ElemeFE/element/issues/14521\n watch(nativeInputValue, () => {\n setNativeInputValue()\n })\n\n // when change between <input> and <textarea>,\n // update DOM dependent value and styles\n // https://github.com/ElemeFE/element/issues/14857\n watch(() => props.nativeType, () => {\n nextTick(() => {\n setNativeInputValue()\n resizeTextarea()\n })\n })\n\n onMounted(() => {\n if (!props.formatter && props.parser) {\n debugWarn(\n 'Input',\n 'If you set the parser, you also need to set the formatter.',\n )\n }\n setNativeInputValue()\n nextTick(resizeTextarea)\n })\n\n const handleMouseLeave = (e: MouseEvent) => {\n hovering.value = false\n emit('mouseleave', e)\n }\n\n const handleMouseEnter = (e: MouseEvent) => {\n hovering.value = true\n emit('mouseenter', e)\n }\n\n const handleKeydown = (e: KeyboardEvent) => {\n emit('keydown', e)\n }\n\n return {\n namespace,\n isComposing,\n input,\n inputId,\n textarea,\n attrs,\n containerAttrs,\n inputSize,\n validateState,\n textareaStyle,\n countStyle,\n resizeTextarea,\n inputDisabled,\n inputFill,\n showClear,\n showPwdVisible,\n isWordLimitVisible,\n textLength,\n hovering,\n inputExceed,\n passwordVisible,\n inputOrTextarea,\n wrapperRef,\n handleInput,\n handleChange,\n handleFocus,\n handleBlur,\n handleCompositionStart,\n handleCompositionUpdate,\n handleCompositionEnd,\n handlePasswordVisible,\n clear,\n select,\n focus,\n blur,\n isFocused,\n getSuffixVisible,\n getPwdVisible,\n handleMouseLeave,\n handleMouseEnter,\n handleKeydown,\n }\n },\n})\n\n</script>\n"],"names":["_openBlock","_createCommentVNode"],"mappings":"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"}