feat(ui): add StringListInput component

Reusable multi-row text input with Add/Remove buttons. Used in the
upcoming refactor of Custom Domains and self-signed Domains / IP
Addresses editors so all three share a single editor pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
0xJacky
2026-05-23 23:19:14 +08:00
parent 7c8b2dae4d
commit 75250e23cc
2 changed files with 60 additions and 0 deletions
@@ -0,0 +1,57 @@
<script setup lang="ts">
defineProps<{
placeholder?: string
addButtonText?: string
}>()
const items = defineModel<string[]>({ required: true })
function addItem() {
items.value = [...items.value, '']
}
function removeItem(index: number) {
if (items.value.length <= 1)
return
const next = [...items.value]
next.splice(index, 1)
items.value = next
}
function updateItem(index: number, value: string) {
const next = [...items.value]
next[index] = value
items.value = next
}
</script>
<template>
<div class="space-y-2">
<div
v-for="(item, index) in items"
:key="index"
class="flex items-center gap-2"
>
<AInput
:value="item"
:placeholder="placeholder"
class="flex-1"
@update:value="(value: string) => updateItem(index, value)"
/>
<AButton
v-if="items.length > 1"
type="link"
danger
@click="removeItem(index)"
>
{{ $gettext('Remove') }}
</AButton>
</div>
<AButton
block
@click="addItem"
>
{{ addButtonText ?? $gettext('Add Item') }}
</AButton>
</div>
</template>
@@ -0,0 +1,3 @@
import StringListInput from './StringListInput.vue'
export default StringListInput