import { Fragment as _Fragment, withDirectives as _withDirectives, createVNode as _createVNode, mergeProps as _mergeProps, resolveDirective as _resolveDirective } from "vue"; // Styles import "./VTextField.css"; // Components import { VCounter } from "../VCounter/VCounter.mjs"; import { filterFieldProps, makeVFieldProps, VField } from "../VField/VField.mjs"; import { makeVInputProps, VInput } from "../VInput/VInput.mjs"; // Composables import { useFocus } from "../../composables/focus.mjs"; import { forwardRefs } from "../../composables/forwardRefs.mjs"; import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Directives import Intersect from "../../directives/intersect/index.mjs"; // Utilities import { cloneVNode, computed, nextTick, ref } from 'vue'; import { callEvent, filterInputAttrs, genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month']; export const makeVTextFieldProps = propsFactory({ autofocus: Boolean, counter: [Boolean, Number, String], counterValue: [Number, Function], prefix: String, placeholder: String, persistentPlaceholder: Boolean, persistentCounter: Boolean, suffix: String, role: String, type: { type: String, default: 'text' }, modelModifiers: Object, ...makeVInputProps(), ...makeVFieldProps() }, 'VTextField'); export const VTextField = genericComponent()({ name: 'VTextField', directives: { Intersect }, inheritAttrs: false, props: makeVTextFieldProps(), emits: { 'click:control': e => true, 'mousedown:control': e => true, 'update:focused': focused => true, 'update:modelValue': val => true }, setup(props, _ref) { let { attrs, emit, slots } = _ref; const model = useProxiedModel(props, 'modelValue'); const { isFocused, focus, blur } = useFocus(props); const counterValue = computed(() => { return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : (model.value ?? '').toString().length; }); const max = computed(() => { if (attrs.maxlength) return attrs.maxlength; if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined; return props.counter; }); const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant)); function onIntersect(isIntersecting, entries) { if (!props.autofocus || !isIntersecting) return; entries[0].target?.focus?.(); } const vInputRef = ref(); const vFieldRef = ref(); const inputRef = ref(); const isActive = computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active); function onFocus() { if (inputRef.value !== document.activeElement) { inputRef.value?.focus(); } if (!isFocused.value) focus(); } function onControlMousedown(e) { emit('mousedown:control', e); if (e.target === inputRef.value) return; onFocus(); e.preventDefault(); } function onControlClick(e) { onFocus(); emit('click:control', e); } function onClear(e) { e.stopPropagation(); onFocus(); nextTick(() => { model.value = null; callEvent(props['onClick:clear'], e); }); } function onInput(e) { const el = e.target; model.value = el.value; if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) { const caretPosition = [el.selectionStart, el.selectionEnd]; nextTick(() => { el.selectionStart = caretPosition[0]; el.selectionEnd = caretPosition[1]; }); } } useRender(() => { const hasCounter = !!(slots.counter || props.counter !== false && props.counter != null); const hasDetails = !!(hasCounter || slots.details); const [rootAttrs, inputAttrs] = filterInputAttrs(attrs); const { modelValue: _, ...inputProps } = VInput.filterProps(props); const fieldProps = filterFieldProps(props); return _createVNode(VInput, _mergeProps({ "ref": vInputRef, "modelValue": model.value, "onUpdate:modelValue": $event => model.value = $event, "class": ['v-text-field', { 'v-text-field--prefixed': props.prefix, 'v-text-field--suffixed': props.suffix, 'v-input--plain-underlined': isPlainOrUnderlined.value }, props.class], "style": props.style }, rootAttrs, inputProps, { "centerAffix": !isPlainOrUnderlined.value, "focused": isFocused.value }), { ...slots, default: _ref2 => { let { id, isDisabled, isDirty, isReadonly, isValid } = _ref2; return _createVNode(VField, _mergeProps({ "ref": vFieldRef, "onMousedown": onControlMousedown, "onClick": onControlClick, "onClick:clear": onClear, "onClick:prependInner": props['onClick:prependInner'], "onClick:appendInner": props['onClick:appendInner'], "role": props.role }, fieldProps, { "id": id.value, "active": isActive.value || isDirty.value, "dirty": isDirty.value || props.dirty, "disabled": isDisabled.value, "focused": isFocused.value, "error": isValid.value === false }), { ...slots, default: _ref3 => { let { props: { class: fieldClass, ...slotProps } } = _ref3; const inputNode = _withDirectives(_createVNode("input", _mergeProps({ "ref": inputRef, "value": model.value, "onInput": onInput, "autofocus": props.autofocus, "readonly": isReadonly.value, "disabled": isDisabled.value, "name": props.name, "placeholder": props.placeholder, "size": 1, "type": props.type, "onFocus": onFocus, "onBlur": blur }, slotProps, inputAttrs), null), [[_resolveDirective("intersect"), { handler: onIntersect }, null, { once: true }]]); return _createVNode(_Fragment, null, [props.prefix && _createVNode("span", { "class": "v-text-field__prefix" }, [_createVNode("span", { "class": "v-text-field__prefix__text" }, [props.prefix])]), slots.default ? _createVNode("div", { "class": fieldClass, "data-no-activator": "" }, [slots.default(), inputNode]) : cloneVNode(inputNode, { class: fieldClass }), props.suffix && _createVNode("span", { "class": "v-text-field__suffix" }, [_createVNode("span", { "class": "v-text-field__suffix__text" }, [props.suffix])])]); } }); }, details: hasDetails ? slotProps => _createVNode(_Fragment, null, [slots.details?.(slotProps), hasCounter && _createVNode(_Fragment, null, [_createVNode("span", null, null), _createVNode(VCounter, { "active": props.persistentCounter || isFocused.value, "value": counterValue.value, "max": max.value }, slots.counter)])]) : undefined }); }); return forwardRefs({}, vInputRef, vFieldRef, inputRef); } }); //# sourceMappingURL=VTextField.mjs.map