docs-please 0.2.0-beta.0 → 0.2.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/app.config.ts +9 -1
- package/app/assets/css/main.css +2 -2
- package/app/components/app/AppHeader.vue +92 -37
- package/app/components/app/AppHeaderCenter.vue +3 -0
- package/app/components/app/AppHeaderLogo.vue +43 -0
- package/app/components/app/AppHeaderSearch.vue +3 -0
- package/app/components/app/AppSearch.vue +189 -0
- package/app/components/app/AppSearchButton.vue +51 -0
- package/app/components/content/Accordion.vue +117 -0
- package/app/components/content/AccordionItem.vue +27 -0
- package/app/components/content/Badge.vue +42 -0
- package/app/components/content/Collapsible.vue +56 -0
- package/app/components/content/ProseKbd.vue +9 -0
- package/app/components/content/ProseTable.vue +2 -2
- package/app/components/content/ProseTh.vue +1 -1
- package/app/components/content/ProseTr.vue +1 -1
- package/app/components/ui/command/Command.vue +86 -0
- package/app/components/ui/command/CommandDialog.vue +21 -0
- package/app/components/ui/command/CommandEmpty.vue +23 -0
- package/app/components/ui/command/CommandGroup.vue +44 -0
- package/app/components/ui/command/CommandInput.vue +35 -0
- package/app/components/ui/command/CommandItem.vue +75 -0
- package/app/components/ui/command/CommandList.vue +21 -0
- package/app/components/ui/command/CommandSeparator.vue +20 -0
- package/app/components/ui/command/CommandShortcut.vue +14 -0
- package/app/components/ui/command/index.ts +25 -0
- package/app/components/ui/dialog/Dialog.vue +19 -0
- package/app/components/ui/dialog/DialogClose.vue +15 -0
- package/app/components/ui/dialog/DialogContent.vue +53 -0
- package/app/components/ui/dialog/DialogDescription.vue +23 -0
- package/app/components/ui/dialog/DialogFooter.vue +15 -0
- package/app/components/ui/dialog/DialogHeader.vue +17 -0
- package/app/components/ui/dialog/DialogOverlay.vue +21 -0
- package/app/components/ui/dialog/DialogScrollContent.vue +59 -0
- package/app/components/ui/dialog/DialogTitle.vue +23 -0
- package/app/components/ui/dialog/DialogTrigger.vue +15 -0
- package/app/components/ui/dialog/index.ts +10 -0
- package/app/components/ui/kbd/Kbd.vue +21 -0
- package/app/components/ui/kbd/KbdGroup.vue +17 -0
- package/app/components/ui/kbd/index.ts +2 -0
- package/app/composables/useContentSearch.ts +52 -0
- package/app/layouts/default.vue +1 -0
- package/app/layouts/docs.vue +1 -0
- package/app/utils/navigation.ts +7 -0
- package/app/utils/prerender.ts +12 -0
- package/nuxt.config.ts +4 -0
- package/nuxt.schema.ts +44 -0
- package/package.json +7 -2
- package/server/routes/raw/[...slug].md.get.ts +45 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes, VNode } from 'vue'
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
import { ChevronDown } from 'lucide-vue-next'
|
|
5
|
+
import { cn } from '~/lib/utils'
|
|
6
|
+
import {
|
|
7
|
+
Collapsible as UICollapsible,
|
|
8
|
+
CollapsibleContent as UICollapsibleContent,
|
|
9
|
+
CollapsibleTrigger as UICollapsibleTrigger,
|
|
10
|
+
} from '~/components/ui/collapsible'
|
|
11
|
+
|
|
12
|
+
export interface CollapsibleProps {
|
|
13
|
+
/**
|
|
14
|
+
* The trigger label text.
|
|
15
|
+
* @default 'Show props'
|
|
16
|
+
*/
|
|
17
|
+
label?: string
|
|
18
|
+
/**
|
|
19
|
+
* Whether the collapsible is open by default.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
defaultOpen?: boolean
|
|
23
|
+
class?: HTMLAttributes['class']
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const props = withDefaults(defineProps<CollapsibleProps>(), {
|
|
27
|
+
label: 'Show props',
|
|
28
|
+
defaultOpen: false,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
defineSlots<{
|
|
32
|
+
default(): VNode[]
|
|
33
|
+
}>()
|
|
34
|
+
|
|
35
|
+
const isOpen = ref(props.defaultOpen)
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<UICollapsible
|
|
40
|
+
v-model:open="isOpen"
|
|
41
|
+
:class="cn('mt-4', props.class)"
|
|
42
|
+
>
|
|
43
|
+
<UICollapsibleTrigger
|
|
44
|
+
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors cursor-pointer"
|
|
45
|
+
>
|
|
46
|
+
<ChevronDown
|
|
47
|
+
class="size-4 transition-transform duration-200"
|
|
48
|
+
:class="{ 'rotate-180': isOpen }"
|
|
49
|
+
/>
|
|
50
|
+
<span>{{ label }}</span>
|
|
51
|
+
</UICollapsibleTrigger>
|
|
52
|
+
<UICollapsibleContent class="mt-2 text-left [&_[data-slot=prose-table]]:my-0 [&_[data-slot=prose-table]]:border-0 [&_[data-slot=prose-table]]:rounded-none">
|
|
53
|
+
<slot />
|
|
54
|
+
</UICollapsibleContent>
|
|
55
|
+
</UICollapsible>
|
|
56
|
+
</template>
|
|
@@ -12,10 +12,10 @@ const props = defineProps<{
|
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<template>
|
|
15
|
-
<div class="no-scrollbar my-6 w-full overflow-
|
|
15
|
+
<div data-slot="prose-table" class="no-scrollbar my-6 w-full overflow-hidden rounded-lg border">
|
|
16
16
|
<table
|
|
17
17
|
:class="cn(
|
|
18
|
-
'
|
|
18
|
+
'w-full border-collapse text-sm',
|
|
19
19
|
props.class,
|
|
20
20
|
)"
|
|
21
21
|
v-bind="$attrs"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
</script>
|
|
3
3
|
|
|
4
4
|
<template>
|
|
5
|
-
<th class="px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right">
|
|
5
|
+
<th class="border-b px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right">
|
|
6
6
|
<slot />
|
|
7
7
|
</th>
|
|
8
8
|
</template>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListboxRootEmits, ListboxRootProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { ListboxRoot, useFilter, useForwardPropsEmits } from "reka-ui"
|
|
6
|
+
import { reactive, ref, watch } from "vue"
|
|
7
|
+
import { cn } from '~/lib/utils'
|
|
8
|
+
import { provideCommandContext } from "."
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<ListboxRootProps & { class?: HTMLAttributes["class"] }>(), {
|
|
11
|
+
modelValue: "",
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const emits = defineEmits<ListboxRootEmits>()
|
|
15
|
+
|
|
16
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
17
|
+
|
|
18
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
19
|
+
|
|
20
|
+
const allItems = ref<Map<string, string>>(new Map())
|
|
21
|
+
const allGroups = ref<Map<string, Set<string>>>(new Map())
|
|
22
|
+
|
|
23
|
+
const { contains } = useFilter({ sensitivity: "base" })
|
|
24
|
+
const filterState = reactive({
|
|
25
|
+
search: "",
|
|
26
|
+
filtered: {
|
|
27
|
+
/** The count of all visible items. */
|
|
28
|
+
count: 0,
|
|
29
|
+
/** Map from visible item id to its search score. */
|
|
30
|
+
items: new Map() as Map<string, number>,
|
|
31
|
+
/** Set of groups with at least one visible item. */
|
|
32
|
+
groups: new Set() as Set<string>,
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
function filterItems() {
|
|
37
|
+
if (!filterState.search) {
|
|
38
|
+
filterState.filtered.count = allItems.value.size
|
|
39
|
+
// Do nothing, each item will know to show itself because search is empty
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Reset the groups
|
|
44
|
+
filterState.filtered.groups = new Set()
|
|
45
|
+
let itemCount = 0
|
|
46
|
+
|
|
47
|
+
// Check which items should be included
|
|
48
|
+
for (const [id, value] of allItems.value) {
|
|
49
|
+
const score = contains(value, filterState.search)
|
|
50
|
+
filterState.filtered.items.set(id, score ? 1 : 0)
|
|
51
|
+
if (score)
|
|
52
|
+
itemCount++
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check which groups have at least 1 item shown
|
|
56
|
+
for (const [groupId, group] of allGroups.value) {
|
|
57
|
+
for (const itemId of group) {
|
|
58
|
+
if (filterState.filtered.items.get(itemId)! > 0) {
|
|
59
|
+
filterState.filtered.groups.add(groupId)
|
|
60
|
+
break
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
filterState.filtered.count = itemCount
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
watch(() => filterState.search, () => {
|
|
69
|
+
filterItems()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
provideCommandContext({
|
|
73
|
+
allItems,
|
|
74
|
+
allGroups,
|
|
75
|
+
filterState,
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<ListboxRoot
|
|
81
|
+
v-bind="forwarded"
|
|
82
|
+
:class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', props.class)"
|
|
83
|
+
>
|
|
84
|
+
<slot />
|
|
85
|
+
</ListboxRoot>
|
|
86
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogRootEmits, DialogRootProps } from "reka-ui"
|
|
3
|
+
import { useForwardPropsEmits } from "reka-ui"
|
|
4
|
+
import { Dialog, DialogContent } from '~/components/ui/dialog'
|
|
5
|
+
import Command from "./Command.vue"
|
|
6
|
+
|
|
7
|
+
const props = defineProps<DialogRootProps>()
|
|
8
|
+
const emits = defineEmits<DialogRootEmits>()
|
|
9
|
+
|
|
10
|
+
const forwarded = useForwardPropsEmits(props, emits)
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<Dialog v-bind="forwarded">
|
|
15
|
+
<DialogContent class="overflow-hidden p-0 shadow-lg">
|
|
16
|
+
<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">
|
|
17
|
+
<slot />
|
|
18
|
+
</Command>
|
|
19
|
+
</DialogContent>
|
|
20
|
+
</Dialog>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PrimitiveProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { Primitive } from "reka-ui"
|
|
6
|
+
import { computed } from "vue"
|
|
7
|
+
import { cn } from '~/lib/utils'
|
|
8
|
+
import { useCommand } from "."
|
|
9
|
+
|
|
10
|
+
const props = defineProps<PrimitiveProps & { class?: HTMLAttributes["class"] }>()
|
|
11
|
+
|
|
12
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
13
|
+
|
|
14
|
+
const { filterState } = useCommand()
|
|
15
|
+
const isRender = computed(() => !!filterState.search && filterState.filtered.count === 0,
|
|
16
|
+
)
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<Primitive v-if="isRender" v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)">
|
|
21
|
+
<slot />
|
|
22
|
+
</Primitive>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListboxGroupProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { ListboxGroup, ListboxGroupLabel, useId } from "reka-ui"
|
|
6
|
+
import { computed, onMounted, onUnmounted } from "vue"
|
|
7
|
+
import { cn } from '~/lib/utils'
|
|
8
|
+
import { provideCommandGroupContext, useCommand } from "."
|
|
9
|
+
|
|
10
|
+
const props = defineProps<ListboxGroupProps & {
|
|
11
|
+
class?: HTMLAttributes["class"]
|
|
12
|
+
heading?: string
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
16
|
+
|
|
17
|
+
const { allGroups, filterState } = useCommand()
|
|
18
|
+
const id = useId()
|
|
19
|
+
|
|
20
|
+
const isRender = computed(() => !filterState.search ? true : filterState.filtered.groups.has(id))
|
|
21
|
+
|
|
22
|
+
provideCommandGroupContext({ id })
|
|
23
|
+
onMounted(() => {
|
|
24
|
+
if (!allGroups.value.has(id))
|
|
25
|
+
allGroups.value.set(id, new Set())
|
|
26
|
+
})
|
|
27
|
+
onUnmounted(() => {
|
|
28
|
+
allGroups.value.delete(id)
|
|
29
|
+
})
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<ListboxGroup
|
|
34
|
+
v-bind="delegatedProps"
|
|
35
|
+
:id="id"
|
|
36
|
+
: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)"
|
|
37
|
+
:hidden="isRender ? undefined : true"
|
|
38
|
+
>
|
|
39
|
+
<ListboxGroupLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
|
|
40
|
+
{{ heading }}
|
|
41
|
+
</ListboxGroupLabel>
|
|
42
|
+
<slot />
|
|
43
|
+
</ListboxGroup>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListboxFilterProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { Search } from "lucide-vue-next"
|
|
6
|
+
import { ListboxFilter, useForwardProps } from "reka-ui"
|
|
7
|
+
import { cn } from '~/lib/utils'
|
|
8
|
+
import { useCommand } from "."
|
|
9
|
+
|
|
10
|
+
defineOptions({
|
|
11
|
+
inheritAttrs: false,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const props = defineProps<ListboxFilterProps & {
|
|
15
|
+
class?: HTMLAttributes["class"]
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
19
|
+
|
|
20
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
21
|
+
|
|
22
|
+
const { filterState } = useCommand()
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<div class="flex items-center border-b px-3" cmdk-input-wrapper>
|
|
27
|
+
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
28
|
+
<ListboxFilter
|
|
29
|
+
v-bind="{ ...forwardedProps, ...$attrs }"
|
|
30
|
+
v-model="filterState.search"
|
|
31
|
+
auto-focus
|
|
32
|
+
:class="cn('flex h-10 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)"
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListboxItemEmits, ListboxItemProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit, useCurrentElement } from "@vueuse/core"
|
|
5
|
+
import { ListboxItem, useForwardPropsEmits, useId } from "reka-ui"
|
|
6
|
+
import { computed, onMounted, onUnmounted, ref } from "vue"
|
|
7
|
+
import { cn } from '~/lib/utils'
|
|
8
|
+
import { useCommand, useCommandGroup } from "."
|
|
9
|
+
|
|
10
|
+
const props = defineProps<ListboxItemProps & { class?: HTMLAttributes["class"] }>()
|
|
11
|
+
const emits = defineEmits<ListboxItemEmits>()
|
|
12
|
+
|
|
13
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
14
|
+
|
|
15
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
16
|
+
|
|
17
|
+
const id = useId()
|
|
18
|
+
const { filterState, allItems, allGroups } = useCommand()
|
|
19
|
+
const groupContext = useCommandGroup()
|
|
20
|
+
|
|
21
|
+
const isRender = computed(() => {
|
|
22
|
+
if (!filterState.search) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const filteredCurrentItem = filterState.filtered.items.get(id)
|
|
27
|
+
// If the filtered items is undefined means not in the all times map yet
|
|
28
|
+
// Do the first render to add into the map
|
|
29
|
+
if (filteredCurrentItem === undefined) {
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check with filter
|
|
34
|
+
return filteredCurrentItem > 0
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const itemRef = ref()
|
|
39
|
+
const currentElement = useCurrentElement(itemRef)
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
if (!(currentElement.value instanceof HTMLElement))
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
// textValue to perform filter
|
|
45
|
+
allItems.value.set(id, currentElement.value.textContent ?? props?.value!.toString())
|
|
46
|
+
|
|
47
|
+
const groupId = groupContext?.id
|
|
48
|
+
if (groupId) {
|
|
49
|
+
if (!allGroups.value.has(groupId)) {
|
|
50
|
+
allGroups.value.set(groupId, new Set([id]))
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
allGroups.value.get(groupId)?.add(id)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
onUnmounted(() => {
|
|
58
|
+
allItems.value.delete(id)
|
|
59
|
+
})
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<template>
|
|
63
|
+
<ListboxItem
|
|
64
|
+
v-if="isRender"
|
|
65
|
+
v-bind="forwarded"
|
|
66
|
+
:id="id"
|
|
67
|
+
ref="itemRef"
|
|
68
|
+
:class="cn('relative flex cursor-default gap-2 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 [&_svg]:size-4 [&_svg]:shrink-0', props.class)"
|
|
69
|
+
@select="() => {
|
|
70
|
+
filterState.search = ''
|
|
71
|
+
}"
|
|
72
|
+
>
|
|
73
|
+
<slot />
|
|
74
|
+
</ListboxItem>
|
|
75
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListboxContentProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { ListboxContent, useForwardProps } from "reka-ui"
|
|
6
|
+
import { cn } from '~/lib/utils'
|
|
7
|
+
|
|
8
|
+
const props = defineProps<ListboxContentProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
|
|
12
|
+
const forwarded = useForwardProps(delegatedProps)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<ListboxContent v-bind="forwarded" :class="cn('max-h-[300px] overflow-y-auto overflow-x-hidden', props.class)">
|
|
17
|
+
<div role="presentation">
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
20
|
+
</ListboxContent>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { SeparatorProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { Separator } from "reka-ui"
|
|
6
|
+
import { cn } from '~/lib/utils'
|
|
7
|
+
|
|
8
|
+
const props = defineProps<SeparatorProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<Separator
|
|
15
|
+
v-bind="delegatedProps"
|
|
16
|
+
:class="cn('-mx-1 h-px bg-border', props.class)"
|
|
17
|
+
>
|
|
18
|
+
<slot />
|
|
19
|
+
</Separator>
|
|
20
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { cn } from '~/lib/utils'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
class?: HTMLAttributes["class"]
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', props.class)">
|
|
12
|
+
<slot />
|
|
13
|
+
</span>
|
|
14
|
+
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Ref } from "vue"
|
|
2
|
+
import { createContext } from "reka-ui"
|
|
3
|
+
|
|
4
|
+
export { default as Command } from "./Command.vue"
|
|
5
|
+
export { default as CommandDialog } from "./CommandDialog.vue"
|
|
6
|
+
export { default as CommandEmpty } from "./CommandEmpty.vue"
|
|
7
|
+
export { default as CommandGroup } from "./CommandGroup.vue"
|
|
8
|
+
export { default as CommandInput } from "./CommandInput.vue"
|
|
9
|
+
export { default as CommandItem } from "./CommandItem.vue"
|
|
10
|
+
export { default as CommandList } from "./CommandList.vue"
|
|
11
|
+
export { default as CommandSeparator } from "./CommandSeparator.vue"
|
|
12
|
+
export { default as CommandShortcut } from "./CommandShortcut.vue"
|
|
13
|
+
|
|
14
|
+
export const [useCommand, provideCommandContext] = createContext<{
|
|
15
|
+
allItems: Ref<Map<string, string>>
|
|
16
|
+
allGroups: Ref<Map<string, Set<string>>>
|
|
17
|
+
filterState: {
|
|
18
|
+
search: string
|
|
19
|
+
filtered: { count: number, items: Map<string, number>, groups: Set<string> }
|
|
20
|
+
}
|
|
21
|
+
}>("Command")
|
|
22
|
+
|
|
23
|
+
export const [useCommandGroup, provideCommandGroupContext] = createContext<{
|
|
24
|
+
id?: string
|
|
25
|
+
}>("CommandGroup")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogRootEmits, DialogRootProps } from "reka-ui"
|
|
3
|
+
import { DialogRoot, useForwardPropsEmits } from "reka-ui"
|
|
4
|
+
|
|
5
|
+
const props = defineProps<DialogRootProps>()
|
|
6
|
+
const emits = defineEmits<DialogRootEmits>()
|
|
7
|
+
|
|
8
|
+
const forwarded = useForwardPropsEmits(props, emits)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<DialogRoot
|
|
13
|
+
v-slot="slotProps"
|
|
14
|
+
data-slot="dialog"
|
|
15
|
+
v-bind="forwarded"
|
|
16
|
+
>
|
|
17
|
+
<slot v-bind="slotProps" />
|
|
18
|
+
</DialogRoot>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogCloseProps } from "reka-ui"
|
|
3
|
+
import { DialogClose } from "reka-ui"
|
|
4
|
+
|
|
5
|
+
const props = defineProps<DialogCloseProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<DialogClose
|
|
10
|
+
data-slot="dialog-close"
|
|
11
|
+
v-bind="props"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</DialogClose>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogContentEmits, DialogContentProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { X } from "lucide-vue-next"
|
|
6
|
+
import {
|
|
7
|
+
DialogClose,
|
|
8
|
+
DialogContent,
|
|
9
|
+
DialogPortal,
|
|
10
|
+
useForwardPropsEmits,
|
|
11
|
+
} from "reka-ui"
|
|
12
|
+
import { cn } from '~/lib/utils'
|
|
13
|
+
import DialogOverlay from "./DialogOverlay.vue"
|
|
14
|
+
|
|
15
|
+
defineOptions({
|
|
16
|
+
inheritAttrs: false,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const props = withDefaults(defineProps<DialogContentProps & { class?: HTMLAttributes["class"], showCloseButton?: boolean }>(), {
|
|
20
|
+
showCloseButton: true,
|
|
21
|
+
})
|
|
22
|
+
const emits = defineEmits<DialogContentEmits>()
|
|
23
|
+
|
|
24
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
25
|
+
|
|
26
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<DialogPortal>
|
|
31
|
+
<DialogOverlay />
|
|
32
|
+
<DialogContent
|
|
33
|
+
data-slot="dialog-content"
|
|
34
|
+
v-bind="{ ...$attrs, ...forwarded }"
|
|
35
|
+
:class="
|
|
36
|
+
cn(
|
|
37
|
+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
|
|
38
|
+
props.class,
|
|
39
|
+
)"
|
|
40
|
+
>
|
|
41
|
+
<slot />
|
|
42
|
+
|
|
43
|
+
<DialogClose
|
|
44
|
+
v-if="showCloseButton"
|
|
45
|
+
data-slot="dialog-close"
|
|
46
|
+
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
47
|
+
>
|
|
48
|
+
<X />
|
|
49
|
+
<span class="sr-only">Close</span>
|
|
50
|
+
</DialogClose>
|
|
51
|
+
</DialogContent>
|
|
52
|
+
</DialogPortal>
|
|
53
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogDescriptionProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { DialogDescription, useForwardProps } from "reka-ui"
|
|
6
|
+
import { cn } from '~/lib/utils'
|
|
7
|
+
|
|
8
|
+
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
|
|
12
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<DialogDescription
|
|
17
|
+
data-slot="dialog-description"
|
|
18
|
+
v-bind="forwardedProps"
|
|
19
|
+
:class="cn('text-muted-foreground text-sm', props.class)"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</DialogDescription>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { cn } from '~/lib/utils'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div
|
|
10
|
+
data-slot="dialog-footer"
|
|
11
|
+
:class="cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', props.class)"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { cn } from '~/lib/utils'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
class?: HTMLAttributes["class"]
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div
|
|
12
|
+
data-slot="dialog-header"
|
|
13
|
+
:class="cn('flex flex-col gap-2 text-center sm:text-left', props.class)"
|
|
14
|
+
>
|
|
15
|
+
<slot />
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogOverlayProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { DialogOverlay } from "reka-ui"
|
|
6
|
+
import { cn } from '~/lib/utils'
|
|
7
|
+
|
|
8
|
+
const props = defineProps<DialogOverlayProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<DialogOverlay
|
|
15
|
+
data-slot="dialog-overlay"
|
|
16
|
+
v-bind="delegatedProps"
|
|
17
|
+
:class="cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80', props.class)"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</DialogOverlay>
|
|
21
|
+
</template>
|