@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 12.1 kB
Source Map (JSON)
{"version":3,"file":"textarea.vue2.mjs","sources":["../../../components/textarea/textarea.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { Icon } from '@/components/icon'\nimport { useFieldStore } from '@/components/form'\n\nimport { computed, ref, toRef, watch } from 'vue'\n\nimport {\n createIconProp,\n createStateProp,\n emitEvent,\n useIcons,\n useLocale,\n useNameHelper,\n useProps\n} from '@vexip-ui/config'\nimport { debounce, isNull, throttle, toNumber } from '@vexip-ui/utils'\nimport { textareaProps } from './props'\n\ndefineOptions({ name: 'Textarea' })\n\nconst { idFor, state, labelId, disabled, loading, validateField, getFieldValue, setFieldValue } =\n useFieldStore<string>(() => textarea.value?.focus())\n\nconst _props = defineProps(textareaProps)\nconst props = useProps('textarea', _props, {\n state: createStateProp(state),\n locale: null,\n value: {\n default: () => getFieldValue(),\n static: true\n },\n placeholder: null,\n rows: 2,\n noResize: false,\n autofocus: false,\n spellcheck: false,\n autocomplete: false,\n readonly: false,\n disabled: () => disabled.value,\n debounce: false,\n delay: null,\n maxLength: 0,\n loading: () => loading.value,\n loadingIcon: createIconProp(),\n loadingLock: false,\n loadingEffect: null,\n sync: false,\n controlClass: null,\n controlAttrs: null,\n name: {\n default: '',\n static: true\n }\n})\n\nconst emit = defineEmits(['update:value'])\n\nconst nh = useNameHelper('textarea')\nconst locale = useLocale('input', toRef(props, 'locale'))\nconst icons = useIcons()\n\nconst focused = ref(false)\nconst currentValue = ref(props.value)\nconst currentLength = ref(props.value ? props.value.length : 0)\nconst composing = ref(false)\n\nconst textarea = ref<HTMLTextAreaElement>()\n\nlet lastValue = props.value\n\nconst isReadonly = computed(() => {\n return (props.loading && props.loadingLock) || props.readonly\n})\nconst className = computed(() => {\n return {\n [nh.b()]: true,\n [nh.ns('input-vars')]: true,\n [nh.bs('vars')]: true,\n [nh.bm('inherit')]: props.inherit,\n [nh.bm('focused')]: focused.value,\n [nh.bm('disabled')]: props.disabled,\n [nh.bm('readonly')]: isReadonly.value,\n [nh.bm('loading')]: props.loading,\n [nh.bm('no-resize')]: props.noResize,\n [nh.bm(props.state)]: props.state !== 'default'\n }\n})\nconst autoComplete = computed(() => {\n return typeof props.autocomplete === 'boolean'\n ? props.autocomplete\n ? 'on'\n : 'off'\n : props.autocomplete\n})\n\nwatch(\n () => props.value,\n value => {\n currentValue.value = value\n lastValue = value\n limitValueLength()\n }\n)\n\ndefineExpose({\n idFor,\n currentValue,\n currentLength,\n composing,\n isReadonly,\n textarea,\n copyValue,\n focus: (options?: FocusOptions) => textarea.value?.focus(options),\n blur: () => textarea.value?.blur()\n})\n\nfunction handleFocus(event: FocusEvent) {\n focused.value = true\n emitEvent(props.onFocus, event)\n}\n\nfunction handleBlur(event: FocusEvent) {\n focused.value = false\n emitEvent(props.onBlur, event)\n}\n\nfunction handleChange(event: Event) {\n const type = event.type as 'change' | 'input'\n\n if (composing.value) {\n if (type === 'input') return\n\n composing.value = false\n }\n\n currentValue.value = (event.target as HTMLTextAreaElement).value\n limitValueLength()\n\n if (type === 'change') {\n if (lastValue === currentValue.value) return\n\n lastValue = currentValue.value\n\n if (!props.sync) {\n emit('update:value', currentValue.value)\n setFieldValue(currentValue.value)\n }\n\n emitEvent(props.onChange, currentValue.value)\n\n if (!props.sync) {\n validateField()\n }\n } else {\n if (props.sync) {\n emit('update:value', currentValue.value)\n setFieldValue(currentValue.value)\n }\n\n emitEvent(props.onInput, currentValue.value)\n\n if (props.sync) {\n validateField()\n }\n }\n}\n\nfunction handleEnter() {\n emitEvent(props.onEnter)\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n emitEvent(props.onKeyDown, event)\n}\n\nfunction handleKeyPress(event: KeyboardEvent) {\n emitEvent(props.onKeyPress, event)\n}\n\nfunction handleKeyUp(event: KeyboardEvent) {\n emitEvent(props.onKeyUp, event)\n}\n\nfunction limitValueLength() {\n let value = currentValue.value\n\n if (isNull(value)) {\n currentLength.value = 0\n\n return\n }\n\n const maxLength = props.maxLength\n\n if (maxLength && value.length > maxLength) {\n value = value.slice(0, maxLength)\n }\n\n currentLength.value = value.length\n currentValue.value = value\n}\n\nfunction copyValue() {\n const textarea = document.createElement('textarea')\n\n textarea.style.height = '0'\n textarea.setAttribute('readonly', 'readonly')\n textarea.value = currentValue.value\n document.body.appendChild(textarea)\n textarea.select()\n\n const isSuccess = document.execCommand('copy')\n\n document.body.removeChild(textarea)\n\n return isSuccess\n}\n\nconst delay = toNumber(props.delay)\nconst handleInput = props.debounce\n ? debounce(handleChange, delay || 100)\n : throttle(handleChange, delay || 16)\n\nfunction handleCompositionStart(event: CompositionEvent) {\n composing.value = true\n emitEvent(props.onCompositionStart, event)\n}\n\nfunction handleCompositionEnd(event: CompositionEvent) {\n if (composing.value) {\n composing.value = false\n\n if (textarea.value) {\n textarea.value.dispatchEvent(new Event('input'))\n }\n }\n\n emitEvent(props.onCompositionStart, event)\n}\n</script>\n\n<template>\n <div :id=\"idFor\" :class=\"className\" @click=\"textarea?.focus()\">\n <textarea\n v-bind=\"props.controlAttrs\"\n ref=\"textarea\"\n :class=\"[nh.be('control'), props.controlAttrs?.class, props.controlClass]\"\n :value=\"currentValue\"\n :rows=\"props.rows\"\n :autofocus=\"props.autofocus\"\n :autocomplete=\"autoComplete\"\n :spellcheck=\"props.spellcheck\"\n :disabled=\"props.disabled\"\n :readonly=\"isReadonly\"\n :placeholder=\"props.placeholder ?? locale.placeholder\"\n :maxlength=\"props.maxLength > 0 ? props.maxLength : undefined\"\n :name=\"props.name || props.controlAttrs?.name\"\n :aria-labelledby=\"labelId\"\n @blur=\"handleBlur\"\n @focus=\"handleFocus\"\n @keyup.enter=\"handleEnter\"\n @keyup=\"handleKeyUp\"\n @keypress=\"handleKeyPress\"\n @keydown=\"handleKeyDown\"\n @input=\"handleInput\"\n @change=\"handleChange\"\n @compositionstart=\"handleCompositionStart\"\n @compositionend=\"handleCompositionEnd\"\n ></textarea>\n <div :class=\"nh.be('extra')\">\n <Transition :name=\"nh.ns('fade')\" appear>\n <div v-if=\"props.loading\" :class=\"nh.be('loading')\">\n <Icon\n v-bind=\"icons.loading\"\n :effect=\"props.loadingEffect || icons.loading.effect\"\n :icon=\"props.loadingIcon || icons.loading.icon\"\n label=\"loading\"\n ></Icon>\n </div>\n </Transition>\n <div v-if=\"props.maxLength > 0\" :class=\"nh.be('count')\">\n <slot name=\"count\" :value=\"currentValue\">\n {{ props.maxLength === Infinity ? currentLength : `${currentLength}/${props.maxLength}` }}\n </slot>\n </div>\n </div>\n </div>\n</template>\n"],"names":["idFor","state","labelId","disabled","loading","validateField","getFieldValue","setFieldValue","useFieldStore","_a","textarea","props","useProps","__props","createStateProp","createIconProp","emit","__emit","nh","useNameHelper","locale","useLocale","toRef","icons","useIcons","focused","ref","currentValue","currentLength","composing","lastValue","isReadonly","computed","className","autoComplete","watch","value","limitValueLength","__expose","copyValue","options","handleFocus","event","emitEvent","handleBlur","handleChange","type","handleEnter","handleKeyDown","handleKeyPress","handleKeyUp","isNull","maxLength","isSuccess","delay","toNumber","handleInput","debounce","throttle","handleCompositionStart","handleCompositionEnd"],"mappings":"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"}