@thxgg/steward 0.1.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/.env.example +7 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/app/app.vue +14 -0
- package/app/assets/css/main.css +129 -0
- package/app/components/CommandPalette.vue +182 -0
- package/app/components/ShortcutsHelp.vue +85 -0
- package/app/components/git/ChangesMinimap.vue +143 -0
- package/app/components/git/CommitList.vue +224 -0
- package/app/components/git/DiffPanel.vue +402 -0
- package/app/components/git/DiffViewer.vue +803 -0
- package/app/components/layout/RepoSelector.vue +358 -0
- package/app/components/layout/Sidebar.vue +91 -0
- package/app/components/prd/Meta.vue +69 -0
- package/app/components/prd/Viewer.vue +285 -0
- package/app/components/tasks/Board.vue +86 -0
- package/app/components/tasks/Card.vue +108 -0
- package/app/components/tasks/Column.vue +108 -0
- package/app/components/tasks/Detail.vue +291 -0
- package/app/components/ui/badge/Badge.vue +26 -0
- package/app/components/ui/badge/index.ts +26 -0
- package/app/components/ui/button/Button.vue +29 -0
- package/app/components/ui/button/index.ts +38 -0
- package/app/components/ui/card/Card.vue +22 -0
- package/app/components/ui/card/CardAction.vue +17 -0
- package/app/components/ui/card/CardContent.vue +17 -0
- package/app/components/ui/card/CardDescription.vue +17 -0
- package/app/components/ui/card/CardFooter.vue +17 -0
- package/app/components/ui/card/CardHeader.vue +17 -0
- package/app/components/ui/card/CardTitle.vue +17 -0
- package/app/components/ui/card/index.ts +7 -0
- package/app/components/ui/combobox/Combobox.vue +19 -0
- package/app/components/ui/combobox/ComboboxAnchor.vue +23 -0
- package/app/components/ui/combobox/ComboboxEmpty.vue +21 -0
- package/app/components/ui/combobox/ComboboxGroup.vue +27 -0
- package/app/components/ui/combobox/ComboboxInput.vue +42 -0
- package/app/components/ui/combobox/ComboboxItem.vue +24 -0
- package/app/components/ui/combobox/ComboboxItemIndicator.vue +23 -0
- package/app/components/ui/combobox/ComboboxList.vue +33 -0
- package/app/components/ui/combobox/ComboboxSeparator.vue +21 -0
- package/app/components/ui/combobox/ComboboxTrigger.vue +24 -0
- package/app/components/ui/combobox/ComboboxViewport.vue +23 -0
- package/app/components/ui/combobox/index.ts +13 -0
- package/app/components/ui/command/Command.vue +103 -0
- package/app/components/ui/command/CommandDialog.vue +33 -0
- package/app/components/ui/command/CommandEmpty.vue +27 -0
- package/app/components/ui/command/CommandGroup.vue +45 -0
- package/app/components/ui/command/CommandInput.vue +54 -0
- package/app/components/ui/command/CommandItem.vue +76 -0
- package/app/components/ui/command/CommandList.vue +25 -0
- package/app/components/ui/command/CommandSeparator.vue +21 -0
- package/app/components/ui/command/CommandShortcut.vue +17 -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/input/Input.vue +33 -0
- package/app/components/ui/input/index.ts +1 -0
- package/app/components/ui/scroll-area/ScrollArea.vue +33 -0
- package/app/components/ui/scroll-area/ScrollBar.vue +32 -0
- package/app/components/ui/scroll-area/index.ts +2 -0
- package/app/components/ui/separator/Separator.vue +29 -0
- package/app/components/ui/separator/index.ts +1 -0
- package/app/components/ui/sheet/Sheet.vue +19 -0
- package/app/components/ui/sheet/SheetClose.vue +15 -0
- package/app/components/ui/sheet/SheetContent.vue +62 -0
- package/app/components/ui/sheet/SheetDescription.vue +21 -0
- package/app/components/ui/sheet/SheetFooter.vue +16 -0
- package/app/components/ui/sheet/SheetHeader.vue +15 -0
- package/app/components/ui/sheet/SheetOverlay.vue +21 -0
- package/app/components/ui/sheet/SheetTitle.vue +21 -0
- package/app/components/ui/sheet/SheetTrigger.vue +15 -0
- package/app/components/ui/sheet/index.ts +8 -0
- package/app/components/ui/tabs/Tabs.vue +24 -0
- package/app/components/ui/tabs/TabsContent.vue +21 -0
- package/app/components/ui/tabs/TabsList.vue +24 -0
- package/app/components/ui/tabs/TabsTrigger.vue +26 -0
- package/app/components/ui/tabs/index.ts +4 -0
- package/app/components/ui/tooltip/Tooltip.vue +19 -0
- package/app/components/ui/tooltip/TooltipContent.vue +34 -0
- package/app/components/ui/tooltip/TooltipProvider.vue +14 -0
- package/app/components/ui/tooltip/TooltipTrigger.vue +15 -0
- package/app/components/ui/tooltip/index.ts +4 -0
- package/app/composables/useFileWatch.ts +78 -0
- package/app/composables/useGit.ts +180 -0
- package/app/composables/useKeyboard.ts +180 -0
- package/app/composables/usePrd.ts +86 -0
- package/app/composables/useRepos.ts +108 -0
- package/app/composables/useThemeMode.ts +38 -0
- package/app/composables/useToast.ts +31 -0
- package/app/layouts/default.vue +197 -0
- package/app/lib/utils.ts +7 -0
- package/app/pages/[repo]/[prd].vue +263 -0
- package/app/pages/index.vue +257 -0
- package/app/types/git.ts +81 -0
- package/app/types/index.ts +29 -0
- package/app/types/prd.ts +49 -0
- package/app/types/repo.ts +37 -0
- package/app/types/task.ts +134 -0
- package/bin/prd +21 -0
- package/components.json +21 -0
- package/dist/app/types/git.js +1 -0
- package/dist/app/types/prd.js +1 -0
- package/dist/app/types/repo.js +1 -0
- package/dist/app/types/task.js +1 -0
- package/dist/host/src/api/git.js +96 -0
- package/dist/host/src/api/index.js +4 -0
- package/dist/host/src/api/prds.js +195 -0
- package/dist/host/src/api/repos.js +47 -0
- package/dist/host/src/api/state.js +63 -0
- package/dist/host/src/executor.js +109 -0
- package/dist/host/src/index.js +95 -0
- package/dist/host/src/mcp.js +62 -0
- package/dist/host/src/ui.js +64 -0
- package/dist/server/utils/db.js +125 -0
- package/dist/server/utils/git.js +396 -0
- package/dist/server/utils/prd-state.js +229 -0
- package/dist/server/utils/repos.js +256 -0
- package/docs/MCP.md +180 -0
- package/nuxt.config.ts +34 -0
- package/package.json +88 -0
- package/public/favicon.ico +0 -0
- package/public/robots.txt +1 -0
- package/server/api/browse.get.ts +52 -0
- package/server/api/repos/[repoId]/git/commits.get.ts +103 -0
- package/server/api/repos/[repoId]/git/diff.get.ts +77 -0
- package/server/api/repos/[repoId]/git/file-content.get.ts +66 -0
- package/server/api/repos/[repoId]/git/file-diff.get.ts +109 -0
- package/server/api/repos/[repoId]/prd/[prdSlug]/progress.get.ts +36 -0
- package/server/api/repos/[repoId]/prd/[prdSlug]/tasks/[taskId]/commits.get.ts +146 -0
- package/server/api/repos/[repoId]/prd/[prdSlug]/tasks.get.ts +36 -0
- package/server/api/repos/[repoId]/prd/[prdSlug].get.ts +97 -0
- package/server/api/repos/[repoId]/prds.get.ts +85 -0
- package/server/api/repos/[repoId]/refresh-git-repos.post.ts +42 -0
- package/server/api/repos/[repoId].delete.ts +27 -0
- package/server/api/repos/index.get.ts +5 -0
- package/server/api/repos/index.post.ts +39 -0
- package/server/api/watch.get.ts +63 -0
- package/server/plugins/migrate-legacy-state.ts +19 -0
- package/server/tsconfig.json +3 -0
- package/server/utils/db.ts +169 -0
- package/server/utils/git.ts +478 -0
- package/server/utils/prd-state.ts +335 -0
- package/server/utils/repos.ts +322 -0
- package/server/utils/watcher.ts +179 -0
- package/tsconfig.json +4 -0
|
@@ -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>
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
DialogOverlay,
|
|
10
|
+
DialogPortal,
|
|
11
|
+
useForwardPropsEmits,
|
|
12
|
+
} from "reka-ui"
|
|
13
|
+
import { cn } from "@/lib/utils"
|
|
14
|
+
|
|
15
|
+
defineOptions({
|
|
16
|
+
inheritAttrs: false,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const props = defineProps<DialogContentProps & { class?: HTMLAttributes["class"] }>()
|
|
20
|
+
const emits = defineEmits<DialogContentEmits>()
|
|
21
|
+
|
|
22
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
23
|
+
|
|
24
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<DialogPortal>
|
|
29
|
+
<DialogOverlay
|
|
30
|
+
class="fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
31
|
+
>
|
|
32
|
+
<DialogContent
|
|
33
|
+
:class="
|
|
34
|
+
cn(
|
|
35
|
+
'relative z-50 grid w-full max-w-lg my-8 gap-4 border border-border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
|
|
36
|
+
props.class,
|
|
37
|
+
)
|
|
38
|
+
"
|
|
39
|
+
v-bind="{ ...$attrs, ...forwarded }"
|
|
40
|
+
@pointer-down-outside="(event) => {
|
|
41
|
+
const originalEvent = event.detail.originalEvent;
|
|
42
|
+
const target = originalEvent.target as HTMLElement;
|
|
43
|
+
if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
}
|
|
46
|
+
}"
|
|
47
|
+
>
|
|
48
|
+
<slot />
|
|
49
|
+
|
|
50
|
+
<DialogClose
|
|
51
|
+
class="absolute top-4 right-4 p-0.5 transition-colors rounded-md hover:bg-secondary"
|
|
52
|
+
>
|
|
53
|
+
<X class="w-4 h-4" />
|
|
54
|
+
<span class="sr-only">Close</span>
|
|
55
|
+
</DialogClose>
|
|
56
|
+
</DialogContent>
|
|
57
|
+
</DialogOverlay>
|
|
58
|
+
</DialogPortal>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogTitleProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { DialogTitle, useForwardProps } from "reka-ui"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
|
|
12
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<DialogTitle
|
|
17
|
+
data-slot="dialog-title"
|
|
18
|
+
v-bind="forwardedProps"
|
|
19
|
+
:class="cn('text-lg leading-none font-semibold', props.class)"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</DialogTitle>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogTriggerProps } from "reka-ui"
|
|
3
|
+
import { DialogTrigger } from "reka-ui"
|
|
4
|
+
|
|
5
|
+
const props = defineProps<DialogTriggerProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<DialogTrigger
|
|
10
|
+
data-slot="dialog-trigger"
|
|
11
|
+
v-bind="props"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</DialogTrigger>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as Dialog } from "./Dialog.vue"
|
|
2
|
+
export { default as DialogClose } from "./DialogClose.vue"
|
|
3
|
+
export { default as DialogContent } from "./DialogContent.vue"
|
|
4
|
+
export { default as DialogDescription } from "./DialogDescription.vue"
|
|
5
|
+
export { default as DialogFooter } from "./DialogFooter.vue"
|
|
6
|
+
export { default as DialogHeader } from "./DialogHeader.vue"
|
|
7
|
+
export { default as DialogOverlay } from "./DialogOverlay.vue"
|
|
8
|
+
export { default as DialogScrollContent } from "./DialogScrollContent.vue"
|
|
9
|
+
export { default as DialogTitle } from "./DialogTitle.vue"
|
|
10
|
+
export { default as DialogTrigger } from "./DialogTrigger.vue"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { useVModel } from "@vueuse/core"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
defaultValue?: string | number
|
|
8
|
+
modelValue?: string | number
|
|
9
|
+
class?: HTMLAttributes["class"]
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const emits = defineEmits<{
|
|
13
|
+
(e: "update:modelValue", payload: string | number): void
|
|
14
|
+
}>()
|
|
15
|
+
|
|
16
|
+
const modelValue = useVModel(props, "modelValue", emits, {
|
|
17
|
+
passive: true,
|
|
18
|
+
defaultValue: props.defaultValue,
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<input
|
|
24
|
+
v-model="modelValue"
|
|
25
|
+
data-slot="input"
|
|
26
|
+
:class="cn(
|
|
27
|
+
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
|
28
|
+
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
|
29
|
+
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
|
30
|
+
props.class,
|
|
31
|
+
)"
|
|
32
|
+
>
|
|
33
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Input } from "./Input.vue"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ScrollAreaRootProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import {
|
|
6
|
+
ScrollAreaCorner,
|
|
7
|
+
ScrollAreaRoot,
|
|
8
|
+
ScrollAreaViewport,
|
|
9
|
+
} from "reka-ui"
|
|
10
|
+
import { cn } from "@/lib/utils"
|
|
11
|
+
import ScrollBar from "./ScrollBar.vue"
|
|
12
|
+
|
|
13
|
+
const props = defineProps<ScrollAreaRootProps & { class?: HTMLAttributes["class"] }>()
|
|
14
|
+
|
|
15
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<ScrollAreaRoot
|
|
20
|
+
data-slot="scroll-area"
|
|
21
|
+
v-bind="delegatedProps"
|
|
22
|
+
:class="cn('relative', props.class)"
|
|
23
|
+
>
|
|
24
|
+
<ScrollAreaViewport
|
|
25
|
+
data-slot="scroll-area-viewport"
|
|
26
|
+
class="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
|
27
|
+
>
|
|
28
|
+
<slot />
|
|
29
|
+
</ScrollAreaViewport>
|
|
30
|
+
<ScrollBar />
|
|
31
|
+
<ScrollAreaCorner />
|
|
32
|
+
</ScrollAreaRoot>
|
|
33
|
+
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ScrollAreaScrollbarProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { ScrollAreaScrollbar, ScrollAreaThumb } from "reka-ui"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<ScrollAreaScrollbarProps & { class?: HTMLAttributes["class"] }>(), {
|
|
9
|
+
orientation: "vertical",
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<ScrollAreaScrollbar
|
|
17
|
+
data-slot="scroll-area-scrollbar"
|
|
18
|
+
v-bind="delegatedProps"
|
|
19
|
+
:class="
|
|
20
|
+
cn('flex touch-none p-px transition-colors select-none',
|
|
21
|
+
orientation === 'vertical'
|
|
22
|
+
&& 'h-full w-2.5 border-l border-l-transparent',
|
|
23
|
+
orientation === 'horizontal'
|
|
24
|
+
&& 'h-2.5 flex-col border-t border-t-transparent',
|
|
25
|
+
props.class)"
|
|
26
|
+
>
|
|
27
|
+
<ScrollAreaThumb
|
|
28
|
+
data-slot="scroll-area-thumb"
|
|
29
|
+
class="bg-border relative flex-1 rounded-full"
|
|
30
|
+
/>
|
|
31
|
+
</ScrollAreaScrollbar>
|
|
32
|
+
</template>
|
|
@@ -0,0 +1,29 @@
|
|
|
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 = withDefaults(defineProps<
|
|
9
|
+
SeparatorProps & { class?: HTMLAttributes["class"] }
|
|
10
|
+
>(), {
|
|
11
|
+
orientation: "horizontal",
|
|
12
|
+
decorative: true,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Separator
|
|
20
|
+
data-slot="separator"
|
|
21
|
+
v-bind="delegatedProps"
|
|
22
|
+
:class="
|
|
23
|
+
cn(
|
|
24
|
+
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
|
25
|
+
props.class,
|
|
26
|
+
)
|
|
27
|
+
"
|
|
28
|
+
/>
|
|
29
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Separator } from "./Separator.vue"
|
|
@@ -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="sheet"
|
|
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="sheet-close"
|
|
11
|
+
v-bind="props"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</DialogClose>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,62 @@
|
|
|
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 SheetOverlay from "./SheetOverlay.vue"
|
|
14
|
+
|
|
15
|
+
interface SheetContentProps extends DialogContentProps {
|
|
16
|
+
class?: HTMLAttributes["class"]
|
|
17
|
+
side?: "top" | "right" | "bottom" | "left"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
defineOptions({
|
|
21
|
+
inheritAttrs: false,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const props = withDefaults(defineProps<SheetContentProps>(), {
|
|
25
|
+
side: "right",
|
|
26
|
+
})
|
|
27
|
+
const emits = defineEmits<DialogContentEmits>()
|
|
28
|
+
|
|
29
|
+
const delegatedProps = reactiveOmit(props, "class", "side")
|
|
30
|
+
|
|
31
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<DialogPortal>
|
|
36
|
+
<SheetOverlay />
|
|
37
|
+
<DialogContent
|
|
38
|
+
data-slot="sheet-content"
|
|
39
|
+
:class="cn(
|
|
40
|
+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
|
41
|
+
side === 'right'
|
|
42
|
+
&& 'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
|
43
|
+
side === 'left'
|
|
44
|
+
&& 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
|
45
|
+
side === 'top'
|
|
46
|
+
&& 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b',
|
|
47
|
+
side === 'bottom'
|
|
48
|
+
&& 'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t',
|
|
49
|
+
props.class)"
|
|
50
|
+
v-bind="{ ...$attrs, ...forwarded }"
|
|
51
|
+
>
|
|
52
|
+
<slot />
|
|
53
|
+
|
|
54
|
+
<DialogClose
|
|
55
|
+
class="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary 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"
|
|
56
|
+
>
|
|
57
|
+
<X class="size-4" />
|
|
58
|
+
<span class="sr-only">Close</span>
|
|
59
|
+
</DialogClose>
|
|
60
|
+
</DialogContent>
|
|
61
|
+
</DialogPortal>
|
|
62
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
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 } 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
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<DialogDescription
|
|
15
|
+
data-slot="sheet-description"
|
|
16
|
+
:class="cn('text-muted-foreground text-sm', props.class)"
|
|
17
|
+
v-bind="delegatedProps"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</DialogDescription>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
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="sheet-footer"
|
|
11
|
+
:class="cn('mt-auto flex flex-col gap-2 p-4', props.class)
|
|
12
|
+
"
|
|
13
|
+
>
|
|
14
|
+
<slot />
|
|
15
|
+
</div>
|
|
16
|
+
</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="sheet-header"
|
|
11
|
+
:class="cn('flex flex-col gap-1.5 p-4', props.class)"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
</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="sheet-overlay"
|
|
16
|
+
: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)"
|
|
17
|
+
v-bind="delegatedProps"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</DialogOverlay>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogTitleProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { DialogTitle } from "reka-ui"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
|
|
10
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<DialogTitle
|
|
15
|
+
data-slot="sheet-title"
|
|
16
|
+
:class="cn('text-foreground font-semibold', props.class)"
|
|
17
|
+
v-bind="delegatedProps"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</DialogTitle>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DialogTriggerProps } from "reka-ui"
|
|
3
|
+
import { DialogTrigger } from "reka-ui"
|
|
4
|
+
|
|
5
|
+
const props = defineProps<DialogTriggerProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<DialogTrigger
|
|
10
|
+
data-slot="sheet-trigger"
|
|
11
|
+
v-bind="props"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</DialogTrigger>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as Sheet } from "./Sheet.vue"
|
|
2
|
+
export { default as SheetClose } from "./SheetClose.vue"
|
|
3
|
+
export { default as SheetContent } from "./SheetContent.vue"
|
|
4
|
+
export { default as SheetDescription } from "./SheetDescription.vue"
|
|
5
|
+
export { default as SheetFooter } from "./SheetFooter.vue"
|
|
6
|
+
export { default as SheetHeader } from "./SheetHeader.vue"
|
|
7
|
+
export { default as SheetTitle } from "./SheetTitle.vue"
|
|
8
|
+
export { default as SheetTrigger } from "./SheetTrigger.vue"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { TabsRootEmits, TabsRootProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { TabsRoot, useForwardPropsEmits } from "reka-ui"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const props = defineProps<TabsRootProps & { class?: HTMLAttributes["class"] }>()
|
|
9
|
+
const emits = defineEmits<TabsRootEmits>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
12
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<TabsRoot
|
|
17
|
+
v-slot="slotProps"
|
|
18
|
+
data-slot="tabs"
|
|
19
|
+
v-bind="forwarded"
|
|
20
|
+
:class="cn('flex flex-col gap-2', props.class)"
|
|
21
|
+
>
|
|
22
|
+
<slot v-bind="slotProps" />
|
|
23
|
+
</TabsRoot>
|
|
24
|
+
</template>
|