mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-27 18:30:35 +01:00
feat(CommandPalette): add custom slots
This commit is contained in:
@@ -31,6 +31,11 @@ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
||||
*/
|
||||
placeholder?: string
|
||||
children?: CommandPaletteItem[]
|
||||
/**
|
||||
* Custom interface slot to display instead of children items.
|
||||
* When defined, clicking this item will show the custom interface.
|
||||
*/
|
||||
interface?: string
|
||||
onSelect?(e?: Event): void
|
||||
class?: any
|
||||
ui?: Pick<CommandPalette['slots'], 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemLabelPrefix' | 'itemLabelBase' | 'itemLabelSuffix' | 'itemTrailing' | 'itemTrailingKbds' | 'itemTrailingKbdsSize' | 'itemTrailingHighlightedIcon' | 'itemTrailingIcon'>
|
||||
@@ -149,6 +154,7 @@ export type CommandPaletteSlots<G extends CommandPaletteGroup<T> = CommandPalett
|
||||
'empty'(props: { searchTerm?: string }): any
|
||||
'back'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
'close'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
'interface'(props: { interfaceName?: string, current: any, searchTerm: string, navigateBack: () => void }): any
|
||||
'item': SlotProps<T>
|
||||
'item-leading': SlotProps<T>
|
||||
'item-label': SlotProps<T>
|
||||
@@ -208,12 +214,17 @@ const fuse = computed(() => defu({}, props.fuse, {
|
||||
matchAllWhenSearchEmpty: true
|
||||
}))
|
||||
|
||||
const history = ref<(CommandPaletteGroup & { placeholder?: string })[]>([])
|
||||
const history = ref<(CommandPaletteGroup & { placeholder?: string, interface?: string })[]>([])
|
||||
|
||||
const placeholder = computed(() => history.value[history.value.length - 1]?.placeholder || props.placeholder || t('commandPalette.placeholder'))
|
||||
|
||||
const groups = computed(() => history.value?.length ? [history.value[history.value.length - 1] as G] : props.groups)
|
||||
|
||||
const _currentInterface = computed(() => {
|
||||
const current = history.value[history.value.length - 1]
|
||||
return current?.interface ? current : null
|
||||
})
|
||||
|
||||
const items = computed(() => groups.value?.filter((group) => {
|
||||
if (!group.id) {
|
||||
console.warn(`[@nuxt/ui] CommandPalette group is missing an \`id\` property`)
|
||||
@@ -280,7 +291,7 @@ const filteredGroups = computed(() => {
|
||||
const listboxRootRef = useTemplateRef('listboxRootRef')
|
||||
|
||||
function navigate(item: T) {
|
||||
if (!item.children?.length) {
|
||||
if (!item.children?.length && !item.interface) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -289,7 +300,8 @@ function navigate(item: T) {
|
||||
label: item.label,
|
||||
slot: item.slot,
|
||||
placeholder: item.placeholder,
|
||||
items: item.children
|
||||
interface: item.interface,
|
||||
items: item.children || []
|
||||
} as any)
|
||||
|
||||
searchTerm.value = ''
|
||||
@@ -316,7 +328,7 @@ function onBackspace() {
|
||||
}
|
||||
|
||||
function onSelect(e: Event, item: T) {
|
||||
if (item.children?.length) {
|
||||
if (item.children?.length || item.interface) {
|
||||
e.preventDefault()
|
||||
|
||||
navigate(item)
|
||||
@@ -371,7 +383,17 @@ function onSelect(e: Event, item: T) {
|
||||
</ListboxFilter>
|
||||
|
||||
<ListboxContent :class="ui.content({ class: props.ui?.content })">
|
||||
<div v-if="filteredGroups?.length" role="presentation" :class="ui.viewport({ class: props.ui?.viewport })">
|
||||
<div v-if="_currentInterface" :class="ui.viewport({ class: props.ui?.viewport })">
|
||||
<slot
|
||||
name="interface"
|
||||
:interface-name="_currentInterface.interface"
|
||||
:current="_currentInterface"
|
||||
:search-term="searchTerm"
|
||||
:navigate-back="navigateBack"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else-if="filteredGroups?.length" role="presentation" :class="ui.viewport({ class: props.ui?.viewport })">
|
||||
<ListboxGroup v-for="group in filteredGroups" :key="`group-${group.id}`" :class="ui.group({ class: props.ui?.group })">
|
||||
<ListboxGroupLabel v-if="get(group, props.labelKey as string)" :class="ui.label({ class: props.ui?.label })">
|
||||
{{ get(group, props.labelKey as string) }}
|
||||
@@ -415,7 +437,7 @@ function onSelect(e: Event, item: T) {
|
||||
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, item.ui?.itemTrailing] })">
|
||||
<slot :name="((item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
||||
<UIcon
|
||||
v-if="item.children && item.children.length > 0"
|
||||
v-if="(item.children && item.children.length > 0) || item.interface"
|
||||
:name="trailingIcon || appConfig.ui.icons.chevronRight"
|
||||
:class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user