@@ -199,7 +199,7 @@ export type CommandPaletteSlots<G extends CommandPaletteGroup<T> = CommandPalett
199199import { computed , ref , useTemplateRef , toRef } from ' vue'
200200import { ListboxRoot , ListboxFilter , ListboxContent , ListboxGroup , ListboxGroupLabel , ListboxVirtualizer , ListboxItem , ListboxItemIndicator , useForwardProps , useForwardPropsEmits } from ' reka-ui'
201201import { defu } from ' defu'
202- import { reactivePick , createReusableTemplate } from ' @vueuse/core'
202+ import { reactivePick , createReusableTemplate , refThrottled } from ' @vueuse/core'
203203import { useFuse } from ' @vueuse/integrations/useFuse'
204204import { useAppConfig } from ' #imports'
205205import { useLocale } from ' ../composables/useLocale'
@@ -290,14 +290,18 @@ const items = computed(() => groups.value?.filter((group) => {
290290
291291const { results : fuseResults } = useFuse <typeof items .value [number ]>(searchTerm , items , fuse )
292292
293- function getGroupWithItems(group : G , items : (T & { matches? : FuseResult <T >[' matches' ] })[]) {
293+ const throttledFuseResults = refThrottled (fuseResults , 16 , true )
294+
295+ function processGroupItems(group : G , items : (T & { matches? : FuseResult <T >[' matches' ] })[]) {
296+ let processedItems = items
297+
294298 if (group ?.postFilter && typeof group .postFilter === ' function' ) {
295- items = group .postFilter (searchTerm .value , items )
299+ processedItems = group .postFilter (searchTerm .value , processedItems )
296300 }
297301
298302 return {
299303 ... group ,
300- items: items .slice (0 , fuse .value .resultLimit ).map ((item ) => {
304+ items: processedItems .slice (0 , fuse .value .resultLimit ).map ((item ) => {
301305 return {
302306 ... item ,
303307 labelHtml: highlight <T >(item , searchTerm .value , props .labelKey ),
@@ -308,7 +312,9 @@ function getGroupWithItems(group: G, items: (T & { matches?: FuseResult<T>['matc
308312}
309313
310314const filteredGroups = computed (() => {
311- const groupsById = fuseResults .value .reduce ((acc , result ) => {
315+ const currentGroups = groups .value
316+
317+ const groupsById = throttledFuseResults .value .reduce ((acc , result ) => {
312318 const { item, matches } = result
313319 if (! item .group ) {
314320 return acc
@@ -321,38 +327,49 @@ const filteredGroups = computed(() => {
321327 }, {} as Record <string , (T & { matches? : FuseResult <T >[' matches' ] })[]>)
322328
323329 if (props .preserveGroupOrder ) {
324- const processedGroups: Array <ReturnType <typeof getGroupWithItems >> = []
330+ const processedGroups: Array <ReturnType <typeof processGroupItems >> = []
325331
326- for (const group of groups . value || []) {
332+ for (const group of currentGroups || []) {
327333 if (! group .items ?.length ) {
328334 continue
329335 }
330336
331- const items = group .ignoreFilter
332- ? group .items
333- : groupsById [group .id ]
337+ const items = group .ignoreFilter ? group .items : groupsById [group .id ]
338+ if (! items ?.length ) {
339+ continue
340+ }
341+
342+ const processedGroup = processGroupItems (group , items )
334343
335- if (items ?.length ) {
336- processedGroups .push (getGroupWithItems (group , items ))
344+ // Filter out groups that become empty after postFilter
345+ if (processedGroup .items ?.length ) {
346+ processedGroups .push (processedGroup )
337347 }
338348 }
339349
340350 return processedGroups
341351 }
342352
343353 const fuseGroups = Object .entries (groupsById ).map (([id , items ]) => {
344- const group = groups . value ?.find (group => group .id === id )
354+ const group = currentGroups ?.find (group => group .id === id )
345355 if (! group ) {
346356 return
347357 }
348358
349- return getGroupWithItems (group , items )
359+ const processedGroup = processGroupItems (group , items )
360+ // Filter out groups without items after postFilter
361+ return processedGroup .items ?.length ? processedGroup : undefined
350362 }).filter (group => !! group )
351363
352- const nonFuseGroups = groups . value
364+ const nonFuseGroups = currentGroups
353365 ?.map ((group , index ) => ({ ... group , index }))
354366 ?.filter (group => group .ignoreFilter && group .items ?.length )
355- ?.map (group => ({ ... getGroupWithItems (group , group .items || []), index: group .index })) || []
367+ ?.map ((group ) => {
368+ const processedGroup = processGroupItems (group , group .items || [])
369+ return { ... processedGroup , index: group .index }
370+ })
371+ // Filter out groups without items after postFilter
372+ ?.filter (group => group .items ?.length ) || []
356373
357374 return nonFuseGroups .reduce ((acc , group ) => {
358375 acc .splice (group .index , 0 , group )
@@ -442,9 +459,11 @@ function onSelect(e: Event, item: T) {
442459 <slot :name =" ((item.slot ? `${item.slot}-label` : group?.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>)" :item =" (item as any)" :index =" index" :ui =" ui" >
443460 <span v-if =" item.prefix" :class =" ui.itemLabelPrefix({ class: [props.ui?.itemLabelPrefix, item.ui?.itemLabelPrefix] })" >{{ item.prefix }}</span >
444461
445- <span :class =" ui.itemLabelBase({ class: [props.ui?.itemLabelBase, item.ui?.itemLabelBase], active: active || item.active })" v-html =" item.labelHtml || get(item, props.labelKey as string)" />
462+ <span v-if =" item.labelHtml" :class =" ui.itemLabelBase({ class: [props.ui?.itemLabelBase, item.ui?.itemLabelBase], active: active || item.active })" v-html =" item.labelHtml" />
463+ <span v-else :class =" ui.itemLabelBase({ class: [props.ui?.itemLabelBase, item.ui?.itemLabelBase], active: active || item.active })" >{{ get(item, props.labelKey as string) }}</span >
446464
447- <span :class =" ui.itemLabelSuffix({ class: [props.ui?.itemLabelSuffix, item.ui?.itemLabelSuffix], active: active || item.active })" v-html =" item.suffixHtml || item.suffix" />
465+ <span v-if =" item.suffixHtml" :class =" ui.itemLabelSuffix({ class: [props.ui?.itemLabelSuffix, item.ui?.itemLabelSuffix], active: active || item.active })" v-html =" item.suffixHtml" />
466+ <span v-else-if =" item.suffix" :class =" ui.itemLabelSuffix({ class: [props.ui?.itemLabelSuffix, item.ui?.itemLabelSuffix], active: active || item.active })" >{{ item.suffix }}</span >
448467 </slot >
449468 </span >
450469
0 commit comments