Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ const schema = z.object({
checkboxGroup: z.any().refine(values => !!values?.find((option: any) => option === 'option-2'), {
message: 'Include Option 2'
}),
listbox: z.any().refine(option => option?.value === 'option-2', {
message: 'Select Option 2'
}),
listboxMultiple: z.any().refine(values => !!values?.find((option: any) => option.value === 'option-2'), {
message: 'Include Option 2'
}),
slider: z.number().max(20, { message: 'Must be less than 20' }),
pin: z.string().regex(/^\d$/).array().length(5),
file: z.file().min(1).max(1024 * 1024).mime('image/png')
Expand Down Expand Up @@ -120,6 +126,14 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UCheckboxGroup v-model="state.checkboxGroup" legend="Checkbox group" :items="items" />
</UFormField>
</div>
<UFormField name="listbox" label="Listbox">
<UListbox v-model="state.listbox" :items="items" class="w-full" />
</UFormField>

<UFormField name="listboxMultiple" label="Listbox (Multiple)">
<UListbox v-model="state.listboxMultiple" :items="items" multiple class="w-full" />
</UFormField>

<UFormField name="pin" label="Pin Input" :error-pattern="/(pin)\..*/">
<UPinInput v-model="state.pin" />
</UFormField>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = [
{ label: 'Benjamin Canac', description: 'benjamincanac', avatar: { src: 'https://github.com/benjamincanac.png' }, id: 1 },
{ label: 'Romain Hamel', description: 'romhml', avatar: { src: 'https://github.com/romhml.png' }, id: 2 },
{ label: 'SΓ©bastien Chopin', description: 'atinux', avatar: { src: 'https://github.com/atinux.png' }, id: 3 },
{ label: 'Hugo Richard', description: 'HugoRCD', avatar: { src: 'https://github.com/HugoRCD.png' }, id: 4 },
{ label: 'Sandro Circi', description: 'sandros94', avatar: { src: 'https://github.com/sandros94.png' }, id: 5 },
{ label: 'Daniel Roe', description: 'danielroe', avatar: { src: 'https://github.com/danielroe.png' }, id: 6 },
{ label: 'Jakub MichΓ‘lek', description: 'J-Michalek', avatar: { src: 'https://github.com/J-Michalek.png' }, id: 7 }
]

const value = ref<ListboxItem[]>([])
</script>

<template>
<UListbox
v-model="value"
:items="items"
multiple
by="id"
class="w-full"
/>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = [
{ label: 'France', description: 'The Hexagon', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', description: 'The Federal Republic', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', description: 'The Boot', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', description: 'The Bull Skin', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', description: 'The Low Country', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', description: 'The Heart of Europe', icon: 'i-lucide-map-pin', value: 'PL' }
]

const value = ref<ListboxItem[]>([])
</script>

<template>
<UListbox
v-model="value"
:items="items"
multiple
class="w-full"
/>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'listbox-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
email: user.email,
value: String(user.id)
}))
},
immediate: false
})

onMounted(() => {
execute()
})
</script>

<template>
<UListbox
:items="users || []"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
filter
class="w-full"
>
<template #item-label="{ item }">
{{ item.label }}

<span class="text-muted">
{{ item.email }}
</span>
</template>
</UListbox>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'

const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'listbox-users-search',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id)
}))
},
immediate: false
})

onMounted(() => {
execute()
})
</script>

<template>
<UListbox
v-model:search-term="searchTerm"
:items="users || []"
:filter="{
icon: 'i-lucide-search',
loading: status === 'pending'
}"
ignore-filter
class="w-full"
/>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
]

const value = ref<ListboxItem>(items[2]!)
</script>

<template>
<div class="w-full flex flex-col gap-4">
<UListbox
v-model="value"
:items="items"
class="w-full"
/>

<p class="text-sm text-muted">
Selected: {{ value?.label || 'None' }}
</p>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
]

const value = ref<ListboxItem[]>([items[2]!, items[4]!])
</script>

<template>
<div class="w-full flex flex-col gap-4">
<UListbox
v-model="value"
:items="items"
multiple
class="w-full"
/>

<p class="text-sm text-muted">
Selected: {{ value.map(i => i.label).join(', ') || 'None' }}
</p>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
const searchTerm = ref('F')
const items = ref([
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
])
const value = ref()
</script>

<template>
<UListbox v-model="value" v-model:search-term="searchTerm" filter :items="items" class="w-full" />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup lang="ts">
const items = ref([
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' }
])
const value = ref('FR')
</script>

<template>
<UListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const allItems: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' },
{ label: 'Belgium', icon: 'i-lucide-map-pin', value: 'BE' },
{ label: 'Portugal', icon: 'i-lucide-map-pin', value: 'PT' }
]

const targetItems = ref<ListboxItem[]>([])
const sourceSelection = ref<ListboxItem[]>([])
const targetSelection = ref<ListboxItem[]>([])

const sourceItems = computed(() => allItems.filter(item => !targetItems.value.some(t => t.value === item.value)))

function transferSelected() {
targetItems.value = [...targetItems.value, ...sourceSelection.value]
sourceSelection.value = []
}

function removeSelected() {
targetItems.value = targetItems.value.filter(item => !targetSelection.value.some(t => t.value === item.value))
targetSelection.value = []
}
</script>

<template>
<div class="flex items-stretch gap-4 w-full">
<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Available</span>

<UListbox
v-model="sourceSelection"
:items="sourceItems"
multiple
filter
class="w-full"
/>
</div>

<div class="flex flex-col items-center justify-center gap-1">
<UButton
icon="i-lucide-chevron-right"
color="neutral"
variant="outline"
:disabled="!sourceSelection.length"
@click="transferSelected"
/>
<UButton
icon="i-lucide-chevron-left"
color="neutral"
variant="outline"
:disabled="!targetSelection.length"
@click="removeSelected"
/>
</div>

<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Selected</span>

<UListbox
v-model="targetSelection"
:items="targetItems"
multiple
filter
class="w-full"
/>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = Array.from({ length: 1000 }, (_, i) => ({
label: `Item ${i + 1}`,
icon: 'i-lucide-file',
value: i + 1
}))

const value = ref<ListboxItem[]>([])
</script>

<template>
<UListbox
v-model="value"
:items="items"
multiple
virtualize
class="w-full"
/>
</template>
Loading
Loading