forked from ccbikai/Sink
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
698 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<script setup> | ||
import { useMagicKeys } from '@vueuse/core' | ||
import { useFuse } from '@vueuse/integrations/useFuse' | ||
const router = useRouter() | ||
const isOpen = ref(false) | ||
const searchTerm = ref('') | ||
const selectedLink = ref(null) | ||
const links = await useAPI('/api/link/search') | ||
const { results: filteredLinks } = useFuse(searchTerm, links, { | ||
fuseOptions: { | ||
keys: ['slug', 'url', 'comment'], | ||
}, | ||
resultLimit: 20, | ||
}) | ||
const { Meta_K, Ctrl_K } = useMagicKeys({ | ||
passive: false, | ||
onEventFired(e) { | ||
if (e.key === 'k' && (e.metaKey || e.ctrlKey)) | ||
e.preventDefault() | ||
}, | ||
}) | ||
watch([Meta_K, Ctrl_K], (v) => { | ||
if (v[0] || v[1]) | ||
isOpen.value = true | ||
}) | ||
function selectLink(link) { | ||
isOpen.value = false | ||
router.push({ | ||
path: '/dashboard/link', | ||
query: { slug: link.slug }, | ||
}) | ||
} | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<Button | ||
variant="outline" | ||
size="sm" | ||
class="relative h-10 w-full justify-start bg-background text-muted-foreground sm:w-32 md:w-48" | ||
@click="isOpen = true" | ||
> | ||
<span class="hidden md:inline-flex">Search Links...</span> | ||
<span class="inline-flex md:hidden">Search</span> | ||
<kbd class="pointer-events-none absolute right-[0.3rem] top-[0.6rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex"> | ||
<span class="text-xs">⌘</span>K | ||
</kbd> | ||
</Button> | ||
<Dialog :open="isOpen" @update:open="isOpen = !isOpen"> | ||
<DialogContent class="overflow-hidden p-0 shadow-lg"> | ||
<Command v-model:searchTerm="searchTerm" v-model="selectedLink" 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"> | ||
<CommandInput placeholder="Type to search..." /> | ||
<CommandList> | ||
<CommandEmpty v-if="searchTerm"> | ||
No links found. | ||
</CommandEmpty> | ||
<CommandGroup heading="Links"> | ||
<CommandItem v-for="link in filteredLinks" :key="link.item?.id" class="cursor-pointer" :value="link.item" @select="selectLink(link.item)"> | ||
<div class="flex gap-1 w-full"> | ||
<div class="flex-1 overflow-hidden inline-flex gap-1 items-center"> | ||
<div class="text-sm font-medium"> | ||
{{ link.item?.slug }} | ||
</div> | ||
<div class="text-xs text-muted-foreground flex-1 truncate"> | ||
({{ link.item?.url }}) | ||
</div> | ||
</div> | ||
<Badge v-if="link.item?.comment" variant="secondary"> | ||
<div class="w-24 truncate"> | ||
{{ link.item?.comment }} | ||
</div> | ||
</Badge> | ||
</div> | ||
</CommandItem> | ||
</CommandGroup> | ||
</CommandList> | ||
</Command> | ||
</DialogContent> | ||
</Dialog> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<script setup lang="ts"> | ||
import type { HTMLAttributes } from 'vue' | ||
import { cn } from '@/utils' | ||
import { type BadgeVariants, badgeVariants } from '.' | ||
const props = defineProps<{ | ||
variant?: BadgeVariants['variant'] | ||
class?: HTMLAttributes['class'] | ||
}>() | ||
</script> | ||
|
||
<template> | ||
<div :class="cn(badgeVariants({ variant }), props.class)"> | ||
<slot /> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { cva, type VariantProps } from 'class-variance-authority' | ||
|
||
export { default as Badge } from './Badge.vue' | ||
|
||
export const badgeVariants = cva( | ||
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', | ||
{ | ||
variants: { | ||
variant: { | ||
default: | ||
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80', | ||
secondary: | ||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', | ||
destructive: | ||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80', | ||
outline: 'text-foreground', | ||
}, | ||
}, | ||
defaultVariants: { | ||
variant: 'default', | ||
}, | ||
}, | ||
) | ||
|
||
export type BadgeVariants = VariantProps<typeof badgeVariants> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<script setup lang="ts"> | ||
import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue' | ||
import { cn } from '@/utils' | ||
import { ComboboxRoot, useForwardPropsEmits } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
const props = withDefaults(defineProps<ComboboxRootProps & { class?: HTMLAttributes['class'] }>(), { | ||
open: true, | ||
modelValue: '', | ||
}) | ||
const emits = defineEmits<ComboboxRootEmits>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
const forwarded = useForwardPropsEmits(delegatedProps, emits) | ||
</script> | ||
|
||
<template> | ||
<ComboboxRoot | ||
v-bind="forwarded" | ||
:class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', props.class)" | ||
> | ||
<slot /> | ||
</ComboboxRoot> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<script setup lang="ts"> | ||
import type { DialogRootEmits, DialogRootProps } from 'radix-vue' | ||
import { Dialog, DialogContent } from '@/components/ui/dialog' | ||
import { useForwardPropsEmits } from 'radix-vue' | ||
import Command from './Command.vue' | ||
const props = defineProps<DialogRootProps>() | ||
const emits = defineEmits<DialogRootEmits>() | ||
const forwarded = useForwardPropsEmits(props, emits) | ||
</script> | ||
|
||
<template> | ||
<Dialog v-bind="forwarded"> | ||
<DialogContent class="overflow-hidden p-0 shadow-lg"> | ||
<Command 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 /> | ||
</Command> | ||
</DialogContent> | ||
</Dialog> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<script setup lang="ts"> | ||
import type { ComboboxEmptyProps } from 'radix-vue' | ||
import { cn } from '@/utils' | ||
import { ComboboxEmpty } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
const props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
</script> | ||
|
||
<template> | ||
<ComboboxEmpty v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)"> | ||
<slot /> | ||
</ComboboxEmpty> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<script setup lang="ts"> | ||
import type { ComboboxGroupProps } from 'radix-vue' | ||
import { cn } from '@/utils' | ||
import { ComboboxGroup, ComboboxLabel } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
const props = defineProps<ComboboxGroupProps & { | ||
class?: HTMLAttributes['class'] | ||
heading?: string | ||
}>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
</script> | ||
|
||
<template> | ||
<ComboboxGroup | ||
v-bind="delegatedProps" | ||
:class="cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)" | ||
> | ||
<ComboboxLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground"> | ||
{{ heading }} | ||
</ComboboxLabel> | ||
<slot /> | ||
</ComboboxGroup> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<script setup lang="ts"> | ||
import { cn } from '@/utils' | ||
import { Search } from 'lucide-vue-next' | ||
import { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
defineOptions({ | ||
inheritAttrs: false, | ||
}) | ||
const props = defineProps<ComboboxInputProps & { | ||
class?: HTMLAttributes['class'] | ||
}>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
const forwardedProps = useForwardProps(delegatedProps) | ||
</script> | ||
|
||
<template> | ||
<div class="flex items-center border-b px-3" cmdk-input-wrapper> | ||
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" /> | ||
<ComboboxInput | ||
v-bind="{ ...forwardedProps, ...$attrs }" | ||
auto-focus | ||
:class="cn('flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50', props.class)" | ||
/> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<script setup lang="ts"> | ||
import type { ComboboxItemEmits, ComboboxItemProps } from 'radix-vue' | ||
import { cn } from '@/utils' | ||
import { ComboboxItem, useForwardPropsEmits } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>() | ||
const emits = defineEmits<ComboboxItemEmits>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
const forwarded = useForwardPropsEmits(delegatedProps, emits) | ||
</script> | ||
|
||
<template> | ||
<ComboboxItem | ||
v-bind="forwarded" | ||
:class="cn('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', props.class)" | ||
> | ||
<slot /> | ||
</ComboboxItem> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<script setup lang="ts"> | ||
import type { ComboboxContentEmits, ComboboxContentProps } from 'radix-vue' | ||
import { cn } from '@/utils' | ||
import { ComboboxContent, useForwardPropsEmits } from 'radix-vue' | ||
import { computed, type HTMLAttributes } from 'vue' | ||
const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), { | ||
dismissable: false, | ||
}) | ||
const emits = defineEmits<ComboboxContentEmits>() | ||
const delegatedProps = computed(() => { | ||
const { class: _, ...delegated } = props | ||
return delegated | ||
}) | ||
const forwarded = useForwardPropsEmits(delegatedProps, emits) | ||
</script> | ||
|
||
<template> | ||
<ComboboxContent v-bind="forwarded" :class="cn('max-h-[300px] overflow-y-auto overflow-x-hidden', props.class)"> | ||
<div role="presentation"> | ||
<slot /> | ||
</div> | ||
</ComboboxContent> | ||
</template> |
Oops, something went wrong.