feat: command palette (#200)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
07622e9606
commit
59802f0896
22 changed files with 911 additions and 101 deletions
|
@ -1,13 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
const { options } = defineProps<{
|
||||
options: string[] | { name: string; display: string }[]
|
||||
const { options, command } = defineProps<{
|
||||
options: string[] | {
|
||||
name: string
|
||||
icon?: string
|
||||
display: string
|
||||
}[]
|
||||
command?: boolean
|
||||
}>()
|
||||
|
||||
const { modelValue } = defineModel<{
|
||||
modelValue: string
|
||||
}>()
|
||||
|
||||
const tabs = computed(() => {
|
||||
const tabs = $computed(() => {
|
||||
return options.map((option) => {
|
||||
if (typeof option === 'string')
|
||||
return { name: option, display: option }
|
||||
|
@ -19,6 +24,17 @@ const tabs = computed(() => {
|
|||
function toValidName(otpion: string) {
|
||||
return otpion.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-')
|
||||
}
|
||||
|
||||
useCommands(() => command
|
||||
? tabs.map(tab => ({
|
||||
scope: 'Tabs',
|
||||
|
||||
name: tab.display,
|
||||
icon: tab.icon ?? 'i-ri:file-list-2-line',
|
||||
|
||||
onActivate: () => modelValue.value = tab.name,
|
||||
}))
|
||||
: [])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,31 +1,58 @@
|
|||
<script setup lang="ts">
|
||||
import { dropdownContextKey } from './ctx'
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
text?: string
|
||||
description?: string
|
||||
icon?: string
|
||||
checked?: boolean
|
||||
command?: boolean
|
||||
}>()
|
||||
const emit = defineEmits(['click'])
|
||||
|
||||
const { hide } = inject(dropdownContextKey, undefined) || {}
|
||||
|
||||
const el = ref<HTMLDivElement>()
|
||||
|
||||
const handleClick = (evt: MouseEvent) => {
|
||||
hide?.()
|
||||
emit('click', evt)
|
||||
}
|
||||
|
||||
useCommand({
|
||||
scope: 'Actions',
|
||||
|
||||
order: -1,
|
||||
visible: () => props.command && props.text,
|
||||
|
||||
name: () => props.text!,
|
||||
icon: () => props.icon ?? 'i-ri:question-line',
|
||||
description: () => props.description,
|
||||
|
||||
onActivate() {
|
||||
const clickEvent = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
el.value?.dispatchEvent(clickEvent)
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
flex gap-3 items-center cursor-pointer px4 py3 hover-bg-active
|
||||
v-bind="$attrs"
|
||||
v-bind="$attrs" ref="el"
|
||||
flex gap-3 items-center cursor-pointer px4 py3
|
||||
hover-bg-active
|
||||
@click="handleClick"
|
||||
>
|
||||
<div v-if="icon" :class="icon" />
|
||||
<div flex="~ col">
|
||||
<div text-15px>
|
||||
<slot />
|
||||
<slot>
|
||||
{{ text }}
|
||||
</slot>
|
||||
</div>
|
||||
<div text-3 text-secondary>
|
||||
<slot name="description">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue