mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 20:19:34 +01:00
feat(CommandPalette): improve theme and performance
This commit is contained in:
@@ -102,7 +102,6 @@ defineShortcuts({
|
||||
:groups="groups"
|
||||
:fuse="{
|
||||
fuseOptions: {
|
||||
threshold: 0.1,
|
||||
includeMatches: true
|
||||
}
|
||||
}"
|
||||
|
||||
@@ -99,6 +99,7 @@ const ui = computed(() => tv({ extend: commandPalette, slots: props.ui })())
|
||||
const fuse = computed(() => defu({}, props.fuse, {
|
||||
fuseOptions: {
|
||||
ignoreLocation: true,
|
||||
threshold: 0.1,
|
||||
keys: ['label', 'suffix']
|
||||
},
|
||||
resultLimit: 12,
|
||||
@@ -112,13 +113,7 @@ const items = computed(() => props.groups?.filter((group) => {
|
||||
}
|
||||
|
||||
return true
|
||||
}).flatMap((group) => {
|
||||
let items = group.items || []
|
||||
if (group.filter) {
|
||||
items = group.filter(searchTerm.value, items)
|
||||
}
|
||||
return items?.map(item => ({ ...item, group: group.id })) || []
|
||||
}) || [])
|
||||
}).flatMap(group => group.items?.map(item => ({ ...item, group: group.id })) || []) || [])
|
||||
|
||||
const { results: fuseResults } = useFuse<T>(searchTerm, items, fuse)
|
||||
|
||||
@@ -127,7 +122,7 @@ const groups = computed(() => {
|
||||
return []
|
||||
}
|
||||
|
||||
const groups: Record<string, (T & { matches: FuseResult<T>['matches'] })[]> = fuseResults.value.reduce((acc, result) => {
|
||||
const groupsById: Record<string, (T & { matches?: FuseResult<T>['matches'] })[]> = fuseResults.value.reduce((acc, result) => {
|
||||
const { item, matches } = result
|
||||
if (!item.group) {
|
||||
return acc
|
||||
@@ -139,12 +134,22 @@ const groups = computed(() => {
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
return Object.entries(groups).map(([id, items]) => {
|
||||
return Object.entries(groupsById).map(([id, items]) => {
|
||||
const group = props.groups?.find(group => group.id === id)
|
||||
|
||||
if (group?.filter && typeof group.filter === 'function') {
|
||||
items = group.filter(searchTerm.value, items)
|
||||
}
|
||||
|
||||
return {
|
||||
...group,
|
||||
items: items.slice(0, fuse.value.resultLimit)
|
||||
items: items.slice(0, fuse.value.resultLimit).map((item) => {
|
||||
return {
|
||||
...item,
|
||||
labelHtml: highlight<T>(item, searchTerm.value, 'label'),
|
||||
suffixHtml: highlight<T>(item, searchTerm.value, undefined, ['label'])
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -180,7 +185,7 @@ const groups = computed(() => {
|
||||
</UInput>
|
||||
</ComboboxInput>
|
||||
|
||||
<ComboboxPortal :disabled="true">
|
||||
<ComboboxPortal disabled>
|
||||
<ComboboxContent :class="ui.content()" :dismissable="false">
|
||||
<ComboboxEmpty :class="ui.empty()">
|
||||
<slot name="empty" :search-term="searchTerm">
|
||||
@@ -197,7 +202,7 @@ const groups = computed(() => {
|
||||
<ComboboxItem
|
||||
v-for="(item, index) in group.items"
|
||||
:key="`group-${groupIndex}-${index}`"
|
||||
:value="omit(item, ['matches' as any, 'group' as any, 'select'])"
|
||||
:value="omit(item, ['matches' as any, 'group' as any, 'select', 'labelHtml', 'suffixHtml'])"
|
||||
:disabled="item.disabled"
|
||||
:class="ui.item()"
|
||||
@select="item.select"
|
||||
@@ -220,9 +225,9 @@ const groups = computed(() => {
|
||||
<slot :name="item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`" :item="item" :index="index">
|
||||
<span v-if="item.prefix" :class="ui.itemLabelPrefix()">{{ item.prefix }}</span>
|
||||
|
||||
<span :class="ui.itemLabelBase()" v-html="highlight<T>(item, searchTerm, 'label') || item.label" />
|
||||
<span :class="ui.itemLabelBase()" v-html="item.labelHtml || item.label" />
|
||||
|
||||
<span :class="ui.itemLabelSuffix()" v-html="highlight<T>(item, searchTerm, undefined, ['label']) || item.suffix" />
|
||||
<span :class="ui.itemLabelSuffix()" v-html="item.suffixHtml || item.suffix" />
|
||||
</slot>
|
||||
</span>
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ export function highlight<T>(item: T & { matches?: FuseResult<T>['matches'] }, s
|
||||
|
||||
content += value.substring(nextUnhighlightedRegionStartingIndex)
|
||||
|
||||
const endIndex = content.indexOf('</mark>')
|
||||
if (endIndex > 50) {
|
||||
content = truncateHTMLFromStart(content, 45)
|
||||
const markIndex = content.indexOf('<mark>')
|
||||
if (markIndex !== -1) {
|
||||
content = truncateHTMLFromStart(content, content.length - markIndex)
|
||||
}
|
||||
|
||||
return content
|
||||
|
||||
@@ -19,8 +19,8 @@ export default (options: Required<ModuleOptions>) => ({
|
||||
itemTrailingHighlightedIcon: 'shrink-0 size-5 text-gray-400 dark:text-gray-500 hidden group-data-highlighted:inline-flex',
|
||||
itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
|
||||
itemLabel: 'truncate space-x-1',
|
||||
itemLabelBase: '[&>mark]:text-[initial] [&>mark]:bg-[initial]',
|
||||
itemLabelPrefix: 'text-gray-400 dark:text-gray-500',
|
||||
itemLabelBase: 'text-gray-900 dark:text-white [&>mark]:bg-primary-500 dark:[&>mark]:bg-primary-400 [&>mark]:text-white dark:[&>mark]:text-gray-900',
|
||||
itemLabelPrefix: 'text-gray-700 dark:text-gray-200',
|
||||
itemLabelSuffix: 'text-gray-400 dark:text-gray-500 [&>mark]:bg-primary-500 dark:[&>mark]:bg-primary-400 [&>mark]:text-white dark:[&>mark]:text-gray-900'
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user