83 lines
3.2 KiB
Vue
83 lines
3.2 KiB
Vue
<script setup lang="ts">
|
|
const inputRef = ref<HTMLTextAreaElement | null>(null);
|
|
const inputValue = ref('');
|
|
const isFocused = ref(false);
|
|
const emit = defineEmits<{
|
|
submit: [value: string];
|
|
}>();
|
|
|
|
const props = defineProps({
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const handleSubmit = () => {
|
|
if (inputValue.value.trim()) {
|
|
emit('submit', inputValue.value);
|
|
inputValue.value = '';
|
|
}
|
|
};
|
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
if (event.key === 'Enter') {
|
|
if (event.shiftKey) return;
|
|
if (event.ctrlKey || event.metaKey) {
|
|
if (inputRef.value === null) return;
|
|
|
|
// inset new line
|
|
let cursorPosition = inputRef.value.selectionStart;
|
|
if (cursorPosition === undefined) return;
|
|
if (cursorPosition !== inputRef.value.selectionEnd) return;
|
|
|
|
inputValue.value = inputValue.value.slice(0, cursorPosition) + "\n" + inputValue.value.slice(cursorPosition);
|
|
// inputRef.value.selectionStart = cursorPosition + 1;
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
handleSubmit();
|
|
}
|
|
};
|
|
|
|
let hasCommandKey = false;
|
|
if (import.meta.server) {
|
|
let headers = useRequestHeaders();
|
|
hasCommandKey = headers['user-agent']?.includes('Mac OS') ?? false;
|
|
} else {
|
|
hasCommandKey = navigator.userAgent.includes('Mac OS');
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="w-full max-w-full mx-auto">
|
|
<div class="relative flex flex-col gap-3 p-3 rounded-2xl border transition-border ease-in-out duration-300 bg-[var(--color-input)]
|
|
border-[var(--color-highlight)] focus-within:border-[var(--color-highlight-high)]">
|
|
<!-- Text Input -->
|
|
<div class="flex-1 min-w-0">
|
|
<textarea v-model="inputValue" ref="inputRef"
|
|
:placeholder="`Start something great. Press ${hasCommandKey ? '⌘ + Enter' : 'ctrl + Enter'} to insert a new line.`"
|
|
@focus="isFocused = true" @blur="isFocused = false" @keydown="handleKeyDown"
|
|
class="w-full bg-transparent text-[var(--color-text)] placeholder-white/50 resize-none outline-none text-[15px] leading-6 min-h-[24px] max-h-32 overflow-y-auto scrollbar-thin scrollbar-thumb-white/20 scrollbar-track-transparent"
|
|
rows="2"></textarea>
|
|
</div>
|
|
|
|
<!-- Toolbar -->
|
|
<div class="flex">
|
|
<div class="flex-1"></div>
|
|
<!-- Send Button -->
|
|
<button aria-label="Send message" @click="handleSubmit" :disabled="!inputValue.trim() || loading"
|
|
:class="[
|
|
'p-2 rounded-xl transition-all duration-200 flex items-center justify-center',
|
|
inputValue.trim()
|
|
? 'bg-[var(--color-accent)] text-[var(--color-accent-text)] hover:bg-[var(--color-accent-hover)]'
|
|
: 'bg-[var(--color-highlight)] text-[var(--color-highlight-high)] cursor-not-allowed'
|
|
]">
|
|
<Icon v-if="loading" name="svg-spinners:ring-resize" class="w-4 h-4" />
|
|
<Icon v-else name="mynaui:send-solid" class="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|