mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
fix(channels): preserve model tags during IME composition
This commit is contained in:
@@ -23,9 +23,9 @@
|
||||
type="text"
|
||||
class="flex-1 min-w-[120px] border-none bg-transparent text-sm outline-none placeholder:text-gray-400 dark:text-white"
|
||||
:placeholder="models.length === 0 ? placeholder : ''"
|
||||
@keydown.enter.prevent="addModel"
|
||||
@keydown.enter="handleEnter"
|
||||
@keydown.tab="handleTab"
|
||||
@keydown.delete="handleBackspace"
|
||||
@keydown.backspace="handleBackspace"
|
||||
@paste="handlePaste"
|
||||
@blur="addModel"
|
||||
/>
|
||||
@@ -66,8 +66,14 @@ function addModel() {
|
||||
inputValue.value = ''
|
||||
}
|
||||
|
||||
function handleEnter(event: KeyboardEvent) {
|
||||
if (event.isComposing) return
|
||||
event.preventDefault()
|
||||
addModel()
|
||||
}
|
||||
|
||||
function handleTab(event: KeyboardEvent) {
|
||||
if (!inputValue.value.trim()) return
|
||||
if (event.isComposing || !inputValue.value.trim()) return
|
||||
event.preventDefault()
|
||||
addModel()
|
||||
}
|
||||
@@ -78,7 +84,8 @@ function removeModel(idx: number) {
|
||||
emit('update:models', newModels)
|
||||
}
|
||||
|
||||
function handleBackspace() {
|
||||
function handleBackspace(event: KeyboardEvent) {
|
||||
if (event.isComposing) return
|
||||
if (inputValue.value === '' && props.models.length > 0) {
|
||||
removeModel(props.models.length - 1)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,33 @@ function pressTab(input: Element, shiftKey = false) {
|
||||
}
|
||||
|
||||
describe('model tag keyboard navigation', () => {
|
||||
it.each(['Enter', 'Tab', 'Backspace'])('leaves composing %s to the input method', async (key) => {
|
||||
const wrapper = mount(ModelTagInput, { props: { models: ['existing'] } })
|
||||
const input = wrapper.get('input')
|
||||
if (key !== 'Backspace') await input.setValue('prefix')
|
||||
const event = new KeyboardEvent('keydown', { key, isComposing: true, bubbles: true, cancelable: true })
|
||||
input.element.dispatchEvent(event)
|
||||
expect(event.defaultPrevented).toBe(false)
|
||||
expect(wrapper.emitted('update:models')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('keeps tags on Delete and removes the last tag only on Backspace', async () => {
|
||||
const wrapper = mount(ModelTagInput, { props: { models: ['existing'] } })
|
||||
await wrapper.get('input').trigger('keydown', { key: 'Delete' })
|
||||
expect(wrapper.emitted('update:models')).toBeUndefined()
|
||||
await wrapper.get('input').trigger('keydown', { key: 'Backspace' })
|
||||
expect(wrapper.emitted('update:models')).toEqual([[[]]])
|
||||
})
|
||||
|
||||
it('commits ordinary Enter input and prevents form submission', async () => {
|
||||
const wrapper = mount(ModelTagInput, { props: { models: [] } })
|
||||
const input = wrapper.get('input'); await input.setValue('new-model')
|
||||
const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true })
|
||||
input.element.dispatchEvent(event)
|
||||
expect(event.defaultPrevented).toBe(true)
|
||||
expect(wrapper.emitted('update:models')).toEqual([[['new-model']]])
|
||||
})
|
||||
|
||||
it.each([false, true])('allows leaving an empty input with Tab (shift: %s)', (shift) => {
|
||||
const wrapper = mount(ModelTagInput, { props: { models: ['gpt-4o'] } })
|
||||
expect(pressTab(wrapper.get('input').element, shift).defaultPrevented).toBe(false)
|
||||
|
||||
Reference in New Issue
Block a user