import { makeAutocompleteProps, useAutocomplete, useAutofocus } from "./chunk-IZQZFEAL.js"; import { VCounter, VField, makeVFieldProps } from "./chunk-J7Q2NMV7.js"; import { VInput, makeVInputProps, useFocus } from "./chunk-4VABFUPG.js"; import { forwardRefs } from "./chunk-GUNW7S2L.js"; import { intersect_default } from "./chunk-5ONGSJQ2.js"; import { useDisplay } from "./chunk-N4LJHDYD.js"; import { useProxiedModel } from "./chunk-KA77II4V.js"; import { callEvent, clamp, convertToUnit, filterInputAttrs, genericComponent, propsFactory, useRender } from "./chunk-LZ5T2ERG.js"; import { Fragment, computed, createBaseVNode, createVNode, mergeProps, nextTick, normalizeClass, onBeforeUnmount, onMounted, ref, shallowRef, vModelText, watch, watchEffect, withDirectives } from "./chunk-2MKFL3BX.js"; // node_modules/vuetify/lib/components/VTextarea/VTextarea.js import "/home/david/Documents/vscode/personal_development/ServerManagerWebApp/frontend/node_modules/vuetify/lib/components/VTextarea/VTextarea.css"; import "/home/david/Documents/vscode/personal_development/ServerManagerWebApp/frontend/node_modules/vuetify/lib/components/VTextField/VTextField.css"; var makeVTextareaProps = propsFactory({ autoGrow: Boolean, autofocus: Boolean, counter: [Boolean, Number, String], counterValue: Function, prefix: String, placeholder: String, persistentPlaceholder: Boolean, persistentCounter: Boolean, noResize: Boolean, rows: { type: [Number, String], default: 5, validator: (v) => !isNaN(parseFloat(v)) }, maxHeight: { type: [Number, String], validator: (v) => !isNaN(parseFloat(v)) }, maxRows: { type: [Number, String], validator: (v) => !isNaN(parseFloat(v)) }, suffix: String, modelModifiers: Object, ...makeAutocompleteProps(), ...makeVInputProps(), ...makeVFieldProps() }, "VTextarea"); var VTextarea = genericComponent()({ name: "VTextarea", directives: { vIntersect: intersect_default }, inheritAttrs: false, props: makeVTextareaProps(), emits: { "click:control": (e) => true, "mousedown:control": (e) => true, "update:focused": (focused) => true, "update:modelValue": (val) => true, "update:rows": (rows) => true }, setup(props, _ref) { let { attrs, emit, slots } = _ref; const model = useProxiedModel(props, "modelValue"); const { isFocused, focus, blur } = useFocus(props); const { onIntersect } = useAutofocus(props); const counterValue = computed(() => { return typeof props.counterValue === "function" ? props.counterValue(model.value) : (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 void 0; return props.counter; }); const vInputRef = ref(); const vFieldRef = ref(); const controlHeight = shallowRef(""); const textareaRef = ref(); const scrollbarWidth = ref(0); const { platform } = useDisplay(); const autocomplete = useAutocomplete(props); const isActive = computed(() => props.persistentPlaceholder || isFocused.value || props.active); function onFocus() { if (autocomplete.isSuppressing.value) { autocomplete.update(); } if (textareaRef.value !== document.activeElement) { textareaRef.value?.focus(); } if (!isFocused.value) focus(); } function onControlClick(e) { onFocus(); emit("click:control", e); } function onControlMousedown(e) { emit("mousedown:control", e); } function onClear(e) { e.stopPropagation(); onFocus(); nextTick(() => { model.value = ""; callEvent(props["onClick:clear"], e); }); } function onInput(e) { const el = e.target; if (!props.modelModifiers?.trim) { model.value = el.value; return; } const value = el.value; const start = el.selectionStart; const end = el.selectionEnd; model.value = value; nextTick(() => { let offset = 0; if (value.trimStart().length === el.value.length) { offset = value.length - el.value.length; } if (start != null) el.selectionStart = start - offset; if (end != null) el.selectionEnd = end - offset; }); } const sizerRef = ref(); const rows = ref(Number(props.rows)); const isPlainOrUnderlined = computed(() => ["plain", "underlined"].includes(props.variant)); watchEffect(() => { if (!props.autoGrow) rows.value = Number(props.rows); }); function calculateInputHeight() { nextTick(() => { if (!textareaRef.value) return; if (platform.value.firefox) { scrollbarWidth.value = 12; return; } const { offsetWidth, clientWidth } = textareaRef.value; scrollbarWidth.value = Math.max(0, offsetWidth - clientWidth); }); if (!props.autoGrow) return; nextTick(() => { if (!sizerRef.value || !vFieldRef.value) return; const style = getComputedStyle(sizerRef.value); const fieldStyle = getComputedStyle(vFieldRef.value.$el); const padding = parseFloat(style.getPropertyValue("--v-field-padding-top")) + parseFloat(style.getPropertyValue("--v-input-padding-top")) + parseFloat(style.getPropertyValue("--v-field-padding-bottom")); const height = sizerRef.value.scrollHeight; const lineHeight = parseFloat(style.lineHeight); const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue("--v-input-control-height"))); const maxHeight = props.maxHeight ? parseFloat(props.maxHeight) : parseFloat(props.maxRows) * lineHeight + padding || Infinity; const newHeight = clamp(height ?? 0, minHeight, maxHeight); rows.value = Math.floor((newHeight - padding) / lineHeight); controlHeight.value = convertToUnit(newHeight); }); } onMounted(calculateInputHeight); watch(model, calculateInputHeight); watch(() => props.rows, calculateInputHeight); watch(() => props.maxHeight, calculateInputHeight); watch(() => props.maxRows, calculateInputHeight); watch(() => props.density, calculateInputHeight); watch(rows, (val) => { emit("update:rows", val); }); let observer; watch(sizerRef, (val) => { if (val) { observer = new ResizeObserver(calculateInputHeight); observer.observe(sizerRef.value); } else { observer?.disconnect(); } }); onBeforeUnmount(() => { observer?.disconnect(); }); useRender(() => { const hasCounter = !!(slots.counter || props.counter || props.counterValue); const hasDetails = !!(hasCounter || slots.details); const [rootAttrs, inputAttrs] = filterInputAttrs(attrs); const { modelValue: _, ...inputProps } = VInput.filterProps(props); const fieldProps = { ...VField.filterProps(props), "onClick:clear": onClear }; return createVNode(VInput, mergeProps({ "ref": vInputRef, "modelValue": model.value, "onUpdate:modelValue": ($event) => model.value = $event, "class": ["v-textarea v-text-field", { "v-textarea--prefixed": props.prefix, "v-textarea--suffixed": props.suffix, "v-text-field--prefixed": props.prefix, "v-text-field--suffixed": props.suffix, "v-textarea--auto-grow": props.autoGrow, "v-textarea--no-resize": props.noResize || props.autoGrow, "v-input--plain-underlined": isPlainOrUnderlined.value }, props.class], "style": [{ "--v-textarea-max-height": props.maxHeight ? convertToUnit(props.maxHeight) : void 0, "--v-textarea-scroll-bar-width": convertToUnit(scrollbarWidth.value) }, props.style] }, rootAttrs, inputProps, { "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value, "focused": isFocused.value }), { ...slots, default: (_ref2) => { let { id, isDisabled, isDirty, isReadonly, isValid, hasDetails: hasDetails2 } = _ref2; return createVNode(VField, mergeProps({ "ref": vFieldRef, "style": { "--v-textarea-control-height": controlHeight.value }, "onClick": onControlClick, "onMousedown": onControlMousedown, "onClick:prependInner": props["onClick:prependInner"], "onClick:appendInner": props["onClick:appendInner"] }, fieldProps, { "id": id.value, "active": isActive.value || isDirty.value, "labelId": `${id.value}-label`, "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value, "dirty": isDirty.value || props.dirty, "disabled": isDisabled.value, "focused": isFocused.value, "details": hasDetails2.value, "error": isValid.value === false }), { ...slots, default: (_ref3) => { let { props: { class: fieldClass, ...slotProps }, controlRef } = _ref3; return createBaseVNode(Fragment, null, [props.prefix && createBaseVNode("span", { "class": "v-text-field__prefix" }, [props.prefix]), withDirectives(createBaseVNode("textarea", mergeProps({ "ref": (val) => textareaRef.value = controlRef.value = val, "class": fieldClass, "value": model.value, "onInput": onInput, "autofocus": props.autofocus, "readonly": isReadonly.value, "disabled": isDisabled.value, "placeholder": props.placeholder, "rows": props.rows, "name": autocomplete.fieldName.value, "autocomplete": autocomplete.fieldAutocomplete.value, "onFocus": onFocus, "onBlur": blur, "aria-labelledby": `${id.value}-label` }, slotProps, inputAttrs), null), [[intersect_default, { handler: onIntersect }, null, { once: true }]]), props.autoGrow && withDirectives(createBaseVNode("textarea", { "class": normalizeClass([fieldClass, "v-textarea__sizer"]), "id": `${slotProps.id}-sizer`, "onUpdate:modelValue": ($event) => model.value = $event, "ref": sizerRef, "readonly": true, "aria-hidden": "true" }, null), [[vModelText, model.value]]), props.suffix && createBaseVNode("span", { "class": "v-text-field__suffix" }, [props.suffix])]); } }); }, details: hasDetails ? (slotProps) => createBaseVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createBaseVNode(Fragment, null, [createBaseVNode("span", null, null), createVNode(VCounter, { "active": props.persistentCounter || isFocused.value, "value": counterValue.value, "max": max.value, "disabled": props.disabled }, slots.counter)])]) : void 0 }); }); return forwardRefs({}, vInputRef, vFieldRef, textareaRef); } }); export { VTextarea }; //# sourceMappingURL=chunk-I4SZJCEY.js.map