feat(command-dialog-fuse): add new Demo component for custom filter-search with useFuse
This commit is contained in:
parent
a906ca1883
commit
070a51647e
|
|
@ -31,6 +31,7 @@
|
|||
"embla-carousel": "8.0.0-rc19",
|
||||
"embla-carousel-autoplay": "8.0.0-rc19",
|
||||
"embla-carousel-vue": "8.0.0-rc19",
|
||||
"fuse.js": "^7.0.0",
|
||||
"lucide-vue-next": "^0.276.0",
|
||||
"radix-vue": "^1.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
|
|
|
|||
|
|
@ -137,7 +137,106 @@ watch(CmdJ, (v) => {
|
|||
</div>
|
||||
</template>
|
||||
```
|
||||
### Dialog with custom filter (Fuse.js)
|
||||
|
||||
<ComponentPreview name="CommandDialogUseFuseDemo" />
|
||||
|
||||
For this Demo we will use the [useFuse](https://vueuse.org/integrations/useFuse/) integration. Don't forget to install `fuse.js` and `@vueuse/integrations`:
|
||||
|
||||
```bash
|
||||
pnpm install fuse.js @vueuse/integrations
|
||||
```
|
||||
|
||||
Code Example:
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
|
||||
import { ref, watch } from 'vue'
|
||||
import { useFuse } from '@vueuse/integrations/useFuse'
|
||||
import {
|
||||
CommandDialog,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from '@/lib/registry/default/ui/command'
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const { Meta_J, Ctrl_J } = useMagicKeys({
|
||||
passive: false,
|
||||
onEventFired(e) {
|
||||
if (e.key === 'j' && (e.metaKey || e.ctrlKey))
|
||||
e.preventDefault()
|
||||
},
|
||||
})
|
||||
|
||||
watch([Meta_J, Ctrl_J], (v) => {
|
||||
if (v[0] || v[1])
|
||||
handleOpenChange()
|
||||
})
|
||||
|
||||
function handleOpenChange() {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
function customFiltering(val: string[], term: string) {
|
||||
const { results } = useFuse(term, val, {
|
||||
matchAllWhenSearchEmpty: true,
|
||||
fuseOptions: {
|
||||
shouldSort: false,
|
||||
},
|
||||
})
|
||||
|
||||
return results.value?.map(v => v.item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Press
|
||||
<kbd
|
||||
class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"
|
||||
>
|
||||
<span class="text-xs">⌘</span>J
|
||||
</kbd>
|
||||
</p>
|
||||
<CommandDialog v-model:open="open" :filter-function="customFiltering">
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandGroup heading="Suggestions">
|
||||
<CommandItem value="calendar">
|
||||
Calendar
|
||||
</CommandItem>
|
||||
<CommandItem value="search-emoji">
|
||||
Search Emoji
|
||||
</CommandItem>
|
||||
<CommandItem value="calculator">
|
||||
Calculator
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
<CommandSeparator />
|
||||
<CommandGroup heading="Settings">
|
||||
<CommandItem value="profile">
|
||||
Profile
|
||||
</CommandItem>
|
||||
<CommandItem value="billing">
|
||||
Billing
|
||||
</CommandItem>
|
||||
<CommandItem value="settings">
|
||||
Settings
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
### Combobox
|
||||
|
||||
You can use the `<Command />` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.
|
||||
You can use the `<Command />` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
<script setup lang="ts">
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
|
||||
import { ref, watch } from 'vue'
|
||||
import { useFuse } from '@vueuse/integrations/useFuse'
|
||||
import {
|
||||
CommandDialog,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from '@/lib/registry/default/ui/command'
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const { Meta_M, Ctrl_M } = useMagicKeys({
|
||||
passive: false,
|
||||
onEventFired(e) {
|
||||
if (e.key === 'm' && (e.metaKey || e.ctrlKey))
|
||||
e.preventDefault()
|
||||
},
|
||||
})
|
||||
|
||||
watch([Meta_M, Ctrl_M], (v) => {
|
||||
if (v[0] || v[1])
|
||||
handleOpenChange()
|
||||
})
|
||||
|
||||
function handleOpenChange() {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
function customFiltering(val: string[], term: string) {
|
||||
const { results } = useFuse(term, val, {
|
||||
matchAllWhenSearchEmpty: true,
|
||||
fuseOptions: {
|
||||
shouldSort: false,
|
||||
},
|
||||
})
|
||||
|
||||
return results.value?.map(v => v.item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Press
|
||||
<kbd
|
||||
class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"
|
||||
>
|
||||
<span class="text-xs">⌘</span>M
|
||||
</kbd>
|
||||
</p>
|
||||
<CommandDialog v-model:open="open" :filter-function="customFiltering">
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandGroup heading="Suggestions">
|
||||
<CommandItem value="calendar">
|
||||
Calendar
|
||||
</CommandItem>
|
||||
<CommandItem value="search-emoji">
|
||||
Search Emoji
|
||||
</CommandItem>
|
||||
<CommandItem value="calculator">
|
||||
Calculator
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
<CommandSeparator />
|
||||
<CommandGroup heading="Settings">
|
||||
<CommandItem value="profile">
|
||||
Profile
|
||||
</CommandItem>
|
||||
<CommandItem value="billing">
|
||||
Billing
|
||||
</CommandItem>
|
||||
<CommandItem value="settings">
|
||||
Settings
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts" generic="T">
|
||||
import { reactiveOmit } from '@vueuse/core'
|
||||
import { useEmitAsProps } from 'radix-vue'
|
||||
import type { DialogRootEmits, DialogRootProps } from 'radix-vue'
|
||||
import Command from './Command.vue'
|
||||
|
|
@ -16,7 +17,7 @@ const emitsAsProps = useEmitAsProps(emits)
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-bind="{ ...props, ...emitsAsProps }">
|
||||
<Dialog v-bind="{ ...reactiveOmit(props, 'filterFunction'), ...emitsAsProps }">
|
||||
<DialogContent class="p-0 overflow-hidden shadow-lg">
|
||||
<Command :filter-function="props.filterFunction" class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
<script setup lang="ts">
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
|
||||
import { ref, watch } from 'vue'
|
||||
import { useFuse } from '@vueuse/integrations/useFuse'
|
||||
import {
|
||||
CommandDialog,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from '@/lib/registry/default/ui/command'
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const { Meta_M, Ctrl_M } = useMagicKeys({
|
||||
passive: false,
|
||||
onEventFired(e) {
|
||||
if (e.key === 'm' && (e.metaKey || e.ctrlKey))
|
||||
e.preventDefault()
|
||||
},
|
||||
})
|
||||
|
||||
watch([Meta_M, Ctrl_M], (v) => {
|
||||
if (v[0] || v[1])
|
||||
handleOpenChange()
|
||||
})
|
||||
|
||||
function handleOpenChange() {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
function customFiltering(val: string[], term: string) {
|
||||
const { results } = useFuse(term, val, {
|
||||
matchAllWhenSearchEmpty: true,
|
||||
fuseOptions: {
|
||||
shouldSort: false,
|
||||
},
|
||||
})
|
||||
|
||||
return results.value?.map(v => v.item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Press
|
||||
<kbd
|
||||
class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"
|
||||
>
|
||||
<span class="text-xs">⌘</span>M
|
||||
</kbd>
|
||||
</p>
|
||||
<CommandDialog v-model:open="open" :filter-function="customFiltering">
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandGroup heading="Suggestions">
|
||||
<CommandItem value="calendar">
|
||||
Calendar
|
||||
</CommandItem>
|
||||
<CommandItem value="search-emoji">
|
||||
Search Emoji
|
||||
</CommandItem>
|
||||
<CommandItem value="calculator">
|
||||
Calculator
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
<CommandSeparator />
|
||||
<CommandGroup heading="Settings">
|
||||
<CommandItem value="profile">
|
||||
Profile
|
||||
</CommandItem>
|
||||
<CommandItem value="billing">
|
||||
Billing
|
||||
</CommandItem>
|
||||
<CommandItem value="settings">
|
||||
Settings
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -92,6 +92,9 @@ importers:
|
|||
embla-carousel-vue:
|
||||
specifier: 8.0.0-rc19
|
||||
version: 8.0.0-rc19(vue@3.4.8)
|
||||
fuse.js:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0
|
||||
lucide-vue-next:
|
||||
specifier: ^0.276.0
|
||||
version: 0.276.0(vue@3.4.8)
|
||||
|
|
@ -182,7 +185,7 @@ importers:
|
|||
version: 4.5.0(@types/node@20.8.10)
|
||||
vitepress:
|
||||
specifier: ^1.0.0-rc.24
|
||||
version: 1.0.0-rc.24(@algolia/client-search@4.22.0)(@types/node@20.8.10)(postcss@8.4.33)(search-insights@2.13.0)(typescript@5.2.2)
|
||||
version: 1.0.0-rc.24(@algolia/client-search@4.22.0)(@types/node@20.8.10)(fuse.js@7.0.0)(postcss@8.4.33)(search-insights@2.13.0)(typescript@5.2.2)
|
||||
vue-tsc:
|
||||
specifier: ^1.8.27
|
||||
version: 1.8.27(typescript@5.2.2)
|
||||
|
|
@ -5193,7 +5196,7 @@ packages:
|
|||
- '@vue/composition-api'
|
||||
- vue
|
||||
|
||||
/@vueuse/integrations@10.5.0(focus-trap@7.5.4)(vue@3.4.8):
|
||||
/@vueuse/integrations@10.5.0(focus-trap@7.5.4)(fuse.js@7.0.0)(vue@3.4.8):
|
||||
resolution: {integrity: sha512-fm5sXLCK0Ww3rRnzqnCQRmfjDURaI4xMsx+T+cec0ngQqHx/JgUtm8G0vRjwtonIeTBsH1Q8L3SucE+7K7upJQ==}
|
||||
peerDependencies:
|
||||
async-validator: '*'
|
||||
|
|
@ -5237,6 +5240,7 @@ packages:
|
|||
'@vueuse/core': 10.5.0(vue@3.4.8)
|
||||
'@vueuse/shared': 10.5.0(vue@3.4.8)
|
||||
focus-trap: 7.5.4
|
||||
fuse.js: 7.0.0
|
||||
vue-demi: 0.14.6(vue@3.4.8)
|
||||
transitivePeerDependencies:
|
||||
- '@vue/composition-api'
|
||||
|
|
@ -8423,6 +8427,10 @@ packages:
|
|||
/function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
/fuse.js@7.0.0:
|
||||
resolution: {integrity: sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/gauge@3.0.2:
|
||||
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -14301,7 +14309,7 @@ packages:
|
|||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vitepress@1.0.0-rc.24(@algolia/client-search@4.22.0)(@types/node@20.8.10)(postcss@8.4.33)(search-insights@2.13.0)(typescript@5.2.2):
|
||||
/vitepress@1.0.0-rc.24(@algolia/client-search@4.22.0)(@types/node@20.8.10)(fuse.js@7.0.0)(postcss@8.4.33)(search-insights@2.13.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-RpnL8cnOGwiRlBbrYQUm9sYkJbtyOt/wYXk2diTcokY4yvks/5lq9LuSt+MURWB6ZqwpSNHvTmxgaSfLoG0/OA==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -14319,7 +14327,7 @@ packages:
|
|||
'@vitejs/plugin-vue': 4.3.1(vite@4.5.0)(vue@3.4.8)
|
||||
'@vue/devtools-api': 6.5.1
|
||||
'@vueuse/core': 10.5.0(vue@3.4.8)
|
||||
'@vueuse/integrations': 10.5.0(focus-trap@7.5.4)(vue@3.4.8)
|
||||
'@vueuse/integrations': 10.5.0(focus-trap@7.5.4)(fuse.js@7.0.0)(vue@3.4.8)
|
||||
focus-trap: 7.5.4
|
||||
mark.js: 8.11.1
|
||||
minisearch: 6.1.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user