@hiroleague/taskmanager 0.0.3 → 0.0.4
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/README.md +1 -1
- package/dist/assets/index-BpzHnKdP.css +1 -0
- package/dist/assets/index-DmNErTAP.js +273 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/skills/hiro-task-manager-cli/SKILL.md +6 -4
- package/skills/hiro-task-manager-cli/reference/cli-access-policy.md +1 -0
- package/skills/hiro-task-manager-cli/reference/releases.md +14 -0
- package/src/cli/commands/query.ts +56 -56
- package/src/cli/commands/releases.ts +22 -0
- package/src/cli/handlers/boards.test.ts +669 -669
- package/src/cli/handlers/cli-wiring.test.ts +38 -1
- package/src/cli/handlers/releases.ts +15 -0
- package/src/cli/handlers/search.test.ts +374 -374
- package/src/cli/handlers/search.ts +17 -17
- package/src/cli/lib/cli-http-errors.test.ts +85 -85
- package/src/cli/lib/write/releases.ts +64 -1
- package/src/cli/lib/write-result.test.ts +3 -0
- package/src/cli/lib/write-result.ts +3 -0
- package/src/cli/lib/writeCommands.breadth.test.ts +143 -0
- package/src/cli/lib/writeCommands.ts +1 -0
- package/src/cli/subprocess.real-stack.test.ts +625 -611
- package/src/cli/subprocess.smoke.test.ts +954 -954
- package/src/client/api/useBoardChangeStream.ts +421 -168
- package/src/client/api/useBoardIndexStream.ts +35 -0
- package/src/client/components/board/BoardStatsChips.tsx +233 -233
- package/src/client/components/board/BoardStatsContext.tsx +41 -41
- package/src/client/components/board/boardHeaderButtonStyles.ts +38 -38
- package/src/client/components/board/shortcuts/useBoardShortcutKeydown.ts +49 -49
- package/src/client/components/board/useBoardCanvasPanScroll.ts +108 -108
- package/src/client/components/board/useBoardTaskContainerDroppableReact.ts +33 -33
- package/src/client/components/board/useBoardTaskSortableReact.ts +26 -26
- package/src/client/components/layout/AppShell.tsx +5 -2
- package/src/client/components/layout/NotificationToasts.tsx +38 -1
- package/src/client/components/multi-select.tsx +1206 -1206
- package/src/client/components/routing/BoardPage.tsx +20 -20
- package/src/client/components/routing/NavigationRegistrar.tsx +13 -13
- package/src/client/components/task/TaskCard.tsx +643 -643
- package/src/client/components/ui/badge.tsx +49 -49
- package/src/client/components/ui/button.tsx +65 -65
- package/src/client/components/ui/command.tsx +193 -193
- package/src/client/components/ui/dialog.tsx +163 -163
- package/src/client/components/ui/input-group.tsx +155 -155
- package/src/client/components/ui/input.tsx +19 -19
- package/src/client/components/ui/popover.tsx +87 -87
- package/src/client/components/ui/separator.tsx +28 -28
- package/src/client/components/ui/textarea.tsx +18 -18
- package/src/client/index.css +248 -248
- package/src/client/lib/appNavigate.ts +16 -16
- package/src/client/lib/taskCardDate.ts +111 -111
- package/src/client/lib/utils.ts +6 -6
- package/src/client/store/notificationUi.ts +14 -0
- package/src/server/auth.ts +351 -351
- package/src/server/events.ts +31 -4
- package/src/server/migrations/registry.ts +43 -43
- package/src/server/notificationEvents.ts +8 -1
- package/src/server/routes/boards.ts +15 -1
- package/src/server/routes/trash.ts +6 -1
- package/src/shared/boardEvents.ts +6 -0
- package/src/shared/runtimeConfig.ts +256 -256
- package/dist/assets/index-hMFTu7sr.css +0 -1
- package/dist/assets/index-oKG1C41_.js +0 -273
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import { Dialog as DialogPrimitive } from "radix-ui"
|
|
3
|
-
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
import { Button } from "@/components/ui/button"
|
|
6
|
-
import { XIcon } from "lucide-react"
|
|
7
|
-
|
|
8
|
-
function Dialog({
|
|
9
|
-
...props
|
|
10
|
-
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
11
|
-
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function DialogTrigger({
|
|
15
|
-
...props
|
|
16
|
-
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
17
|
-
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function DialogPortal({
|
|
21
|
-
...props
|
|
22
|
-
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
23
|
-
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function DialogClose({
|
|
27
|
-
...props
|
|
28
|
-
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
29
|
-
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function DialogOverlay({
|
|
33
|
-
className,
|
|
34
|
-
...props
|
|
35
|
-
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
36
|
-
return (
|
|
37
|
-
<DialogPrimitive.Overlay
|
|
38
|
-
data-slot="dialog-overlay"
|
|
39
|
-
className={cn(
|
|
40
|
-
"fixed inset-0 isolate z-50 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
41
|
-
className
|
|
42
|
-
)}
|
|
43
|
-
{...props}
|
|
44
|
-
/>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function DialogContent({
|
|
49
|
-
className,
|
|
50
|
-
children,
|
|
51
|
-
showCloseButton = true,
|
|
52
|
-
...props
|
|
53
|
-
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
54
|
-
showCloseButton?: boolean
|
|
55
|
-
}) {
|
|
56
|
-
return (
|
|
57
|
-
<DialogPortal>
|
|
58
|
-
<DialogOverlay />
|
|
59
|
-
<DialogPrimitive.Content
|
|
60
|
-
data-slot="dialog-content"
|
|
61
|
-
className={cn(
|
|
62
|
-
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-xs/relaxed text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
63
|
-
className
|
|
64
|
-
)}
|
|
65
|
-
{...props}
|
|
66
|
-
>
|
|
67
|
-
{children}
|
|
68
|
-
{showCloseButton && (
|
|
69
|
-
<DialogPrimitive.Close data-slot="dialog-close" asChild>
|
|
70
|
-
<Button
|
|
71
|
-
variant="ghost"
|
|
72
|
-
className="absolute top-2 right-2"
|
|
73
|
-
size="icon-sm"
|
|
74
|
-
>
|
|
75
|
-
<XIcon
|
|
76
|
-
/>
|
|
77
|
-
<span className="sr-only">Close</span>
|
|
78
|
-
</Button>
|
|
79
|
-
</DialogPrimitive.Close>
|
|
80
|
-
)}
|
|
81
|
-
</DialogPrimitive.Content>
|
|
82
|
-
</DialogPortal>
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
87
|
-
return (
|
|
88
|
-
<div
|
|
89
|
-
data-slot="dialog-header"
|
|
90
|
-
className={cn("flex flex-col gap-1", className)}
|
|
91
|
-
{...props}
|
|
92
|
-
/>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function DialogFooter({
|
|
97
|
-
className,
|
|
98
|
-
showCloseButton = false,
|
|
99
|
-
children,
|
|
100
|
-
...props
|
|
101
|
-
}: React.ComponentProps<"div"> & {
|
|
102
|
-
showCloseButton?: boolean
|
|
103
|
-
}) {
|
|
104
|
-
return (
|
|
105
|
-
<div
|
|
106
|
-
data-slot="dialog-footer"
|
|
107
|
-
className={cn(
|
|
108
|
-
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
109
|
-
className
|
|
110
|
-
)}
|
|
111
|
-
{...props}
|
|
112
|
-
>
|
|
113
|
-
{children}
|
|
114
|
-
{showCloseButton && (
|
|
115
|
-
<DialogPrimitive.Close asChild>
|
|
116
|
-
<Button variant="outline">Close</Button>
|
|
117
|
-
</DialogPrimitive.Close>
|
|
118
|
-
)}
|
|
119
|
-
</div>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function DialogTitle({
|
|
124
|
-
className,
|
|
125
|
-
...props
|
|
126
|
-
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
127
|
-
return (
|
|
128
|
-
<DialogPrimitive.Title
|
|
129
|
-
data-slot="dialog-title"
|
|
130
|
-
className={cn("font-heading text-sm font-medium", className)}
|
|
131
|
-
{...props}
|
|
132
|
-
/>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function DialogDescription({
|
|
137
|
-
className,
|
|
138
|
-
...props
|
|
139
|
-
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
140
|
-
return (
|
|
141
|
-
<DialogPrimitive.Description
|
|
142
|
-
data-slot="dialog-description"
|
|
143
|
-
className={cn(
|
|
144
|
-
"text-xs/relaxed text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
145
|
-
className
|
|
146
|
-
)}
|
|
147
|
-
{...props}
|
|
148
|
-
/>
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export {
|
|
153
|
-
Dialog,
|
|
154
|
-
DialogClose,
|
|
155
|
-
DialogContent,
|
|
156
|
-
DialogDescription,
|
|
157
|
-
DialogFooter,
|
|
158
|
-
DialogHeader,
|
|
159
|
-
DialogOverlay,
|
|
160
|
-
DialogPortal,
|
|
161
|
-
DialogTitle,
|
|
162
|
-
DialogTrigger,
|
|
163
|
-
}
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Dialog as DialogPrimitive } from "radix-ui"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
import { Button } from "@/components/ui/button"
|
|
6
|
+
import { XIcon } from "lucide-react"
|
|
7
|
+
|
|
8
|
+
function Dialog({
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
11
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function DialogTrigger({
|
|
15
|
+
...props
|
|
16
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
17
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function DialogPortal({
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
23
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function DialogClose({
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
29
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function DialogOverlay({
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
36
|
+
return (
|
|
37
|
+
<DialogPrimitive.Overlay
|
|
38
|
+
data-slot="dialog-overlay"
|
|
39
|
+
className={cn(
|
|
40
|
+
"fixed inset-0 isolate z-50 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function DialogContent({
|
|
49
|
+
className,
|
|
50
|
+
children,
|
|
51
|
+
showCloseButton = true,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
54
|
+
showCloseButton?: boolean
|
|
55
|
+
}) {
|
|
56
|
+
return (
|
|
57
|
+
<DialogPortal>
|
|
58
|
+
<DialogOverlay />
|
|
59
|
+
<DialogPrimitive.Content
|
|
60
|
+
data-slot="dialog-content"
|
|
61
|
+
className={cn(
|
|
62
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-xs/relaxed text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
{showCloseButton && (
|
|
69
|
+
<DialogPrimitive.Close data-slot="dialog-close" asChild>
|
|
70
|
+
<Button
|
|
71
|
+
variant="ghost"
|
|
72
|
+
className="absolute top-2 right-2"
|
|
73
|
+
size="icon-sm"
|
|
74
|
+
>
|
|
75
|
+
<XIcon
|
|
76
|
+
/>
|
|
77
|
+
<span className="sr-only">Close</span>
|
|
78
|
+
</Button>
|
|
79
|
+
</DialogPrimitive.Close>
|
|
80
|
+
)}
|
|
81
|
+
</DialogPrimitive.Content>
|
|
82
|
+
</DialogPortal>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
87
|
+
return (
|
|
88
|
+
<div
|
|
89
|
+
data-slot="dialog-header"
|
|
90
|
+
className={cn("flex flex-col gap-1", className)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function DialogFooter({
|
|
97
|
+
className,
|
|
98
|
+
showCloseButton = false,
|
|
99
|
+
children,
|
|
100
|
+
...props
|
|
101
|
+
}: React.ComponentProps<"div"> & {
|
|
102
|
+
showCloseButton?: boolean
|
|
103
|
+
}) {
|
|
104
|
+
return (
|
|
105
|
+
<div
|
|
106
|
+
data-slot="dialog-footer"
|
|
107
|
+
className={cn(
|
|
108
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
109
|
+
className
|
|
110
|
+
)}
|
|
111
|
+
{...props}
|
|
112
|
+
>
|
|
113
|
+
{children}
|
|
114
|
+
{showCloseButton && (
|
|
115
|
+
<DialogPrimitive.Close asChild>
|
|
116
|
+
<Button variant="outline">Close</Button>
|
|
117
|
+
</DialogPrimitive.Close>
|
|
118
|
+
)}
|
|
119
|
+
</div>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function DialogTitle({
|
|
124
|
+
className,
|
|
125
|
+
...props
|
|
126
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
127
|
+
return (
|
|
128
|
+
<DialogPrimitive.Title
|
|
129
|
+
data-slot="dialog-title"
|
|
130
|
+
className={cn("font-heading text-sm font-medium", className)}
|
|
131
|
+
{...props}
|
|
132
|
+
/>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function DialogDescription({
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
139
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
140
|
+
return (
|
|
141
|
+
<DialogPrimitive.Description
|
|
142
|
+
data-slot="dialog-description"
|
|
143
|
+
className={cn(
|
|
144
|
+
"text-xs/relaxed text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
145
|
+
className
|
|
146
|
+
)}
|
|
147
|
+
{...props}
|
|
148
|
+
/>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export {
|
|
153
|
+
Dialog,
|
|
154
|
+
DialogClose,
|
|
155
|
+
DialogContent,
|
|
156
|
+
DialogDescription,
|
|
157
|
+
DialogFooter,
|
|
158
|
+
DialogHeader,
|
|
159
|
+
DialogOverlay,
|
|
160
|
+
DialogPortal,
|
|
161
|
+
DialogTitle,
|
|
162
|
+
DialogTrigger,
|
|
163
|
+
}
|
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
-
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
7
|
-
import { Button } from "@/components/ui/button"
|
|
8
|
-
import { Input } from "@/components/ui/input"
|
|
9
|
-
import { Textarea } from "@/components/ui/textarea"
|
|
10
|
-
|
|
11
|
-
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
12
|
-
return (
|
|
13
|
-
<div
|
|
14
|
-
data-slot="input-group"
|
|
15
|
-
role="group"
|
|
16
|
-
className={cn(
|
|
17
|
-
"group/input-group relative flex h-7 w-full min-w-0 items-center rounded-md border border-input bg-input/20 transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-2 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
|
|
18
|
-
className
|
|
19
|
-
)}
|
|
20
|
-
{...props}
|
|
21
|
-
/>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const inputGroupAddonVariants = cva(
|
|
26
|
-
"flex h-auto cursor-text items-center justify-center gap-1 py-2 text-xs/relaxed font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-[calc(var(--radius-sm)-2px)] **:data-[slot=kbd]:bg-muted-foreground/10 **:data-[slot=kbd]:px-1 **:data-[slot=kbd]:text-[0.625rem] [&>svg:not([class*='size-'])]:size-3.5",
|
|
27
|
-
{
|
|
28
|
-
variants: {
|
|
29
|
-
align: {
|
|
30
|
-
"inline-start":
|
|
31
|
-
"order-first pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem]",
|
|
32
|
-
"inline-end":
|
|
33
|
-
"order-last pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem]",
|
|
34
|
-
"block-start":
|
|
35
|
-
"order-first w-full justify-start px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
|
|
36
|
-
"block-end":
|
|
37
|
-
"order-last w-full justify-start px-2 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2",
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
defaultVariants: {
|
|
41
|
-
align: "inline-start",
|
|
42
|
-
},
|
|
43
|
-
}
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
function InputGroupAddon({
|
|
47
|
-
className,
|
|
48
|
-
align = "inline-start",
|
|
49
|
-
...props
|
|
50
|
-
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
|
51
|
-
return (
|
|
52
|
-
<div
|
|
53
|
-
role="group"
|
|
54
|
-
data-slot="input-group-addon"
|
|
55
|
-
data-align={align}
|
|
56
|
-
className={cn(inputGroupAddonVariants({ align }), className)}
|
|
57
|
-
onClick={(e) => {
|
|
58
|
-
if ((e.target as HTMLElement).closest("button")) {
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
e.currentTarget.parentElement?.querySelector("input")?.focus()
|
|
62
|
-
}}
|
|
63
|
-
{...props}
|
|
64
|
-
/>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const inputGroupButtonVariants = cva(
|
|
69
|
-
"flex items-center gap-2 rounded-md text-xs/relaxed shadow-none",
|
|
70
|
-
{
|
|
71
|
-
variants: {
|
|
72
|
-
size: {
|
|
73
|
-
xs: "h-5 gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1 [&>svg:not([class*='size-'])]:size-3",
|
|
74
|
-
sm: "gap-1",
|
|
75
|
-
"icon-xs": "size-6 p-0 has-[>svg]:p-0",
|
|
76
|
-
"icon-sm": "size-7 p-0 has-[>svg]:p-0",
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
defaultVariants: {
|
|
80
|
-
size: "xs",
|
|
81
|
-
},
|
|
82
|
-
}
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
function InputGroupButton({
|
|
86
|
-
className,
|
|
87
|
-
type = "button",
|
|
88
|
-
variant = "ghost",
|
|
89
|
-
size = "xs",
|
|
90
|
-
...props
|
|
91
|
-
}: Omit<React.ComponentProps<typeof Button>, "size"> &
|
|
92
|
-
VariantProps<typeof inputGroupButtonVariants>) {
|
|
93
|
-
return (
|
|
94
|
-
<Button
|
|
95
|
-
type={type}
|
|
96
|
-
data-size={size}
|
|
97
|
-
variant={variant}
|
|
98
|
-
className={cn(inputGroupButtonVariants({ size }), className)}
|
|
99
|
-
{...props}
|
|
100
|
-
/>
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
|
105
|
-
return (
|
|
106
|
-
<span
|
|
107
|
-
className={cn(
|
|
108
|
-
"flex items-center gap-2 text-xs/relaxed text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
109
|
-
className
|
|
110
|
-
)}
|
|
111
|
-
{...props}
|
|
112
|
-
/>
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function InputGroupInput({
|
|
117
|
-
className,
|
|
118
|
-
...props
|
|
119
|
-
}: React.ComponentProps<"input">) {
|
|
120
|
-
return (
|
|
121
|
-
<Input
|
|
122
|
-
data-slot="input-group-control"
|
|
123
|
-
className={cn(
|
|
124
|
-
"flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
125
|
-
className
|
|
126
|
-
)}
|
|
127
|
-
{...props}
|
|
128
|
-
/>
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function InputGroupTextarea({
|
|
133
|
-
className,
|
|
134
|
-
...props
|
|
135
|
-
}: React.ComponentProps<"textarea">) {
|
|
136
|
-
return (
|
|
137
|
-
<Textarea
|
|
138
|
-
data-slot="input-group-control"
|
|
139
|
-
className={cn(
|
|
140
|
-
"flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
141
|
-
className
|
|
142
|
-
)}
|
|
143
|
-
{...props}
|
|
144
|
-
/>
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export {
|
|
149
|
-
InputGroup,
|
|
150
|
-
InputGroupAddon,
|
|
151
|
-
InputGroupButton,
|
|
152
|
-
InputGroupText,
|
|
153
|
-
InputGroupInput,
|
|
154
|
-
InputGroupTextarea,
|
|
155
|
-
}
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Button } from "@/components/ui/button"
|
|
8
|
+
import { Input } from "@/components/ui/input"
|
|
9
|
+
import { Textarea } from "@/components/ui/textarea"
|
|
10
|
+
|
|
11
|
+
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
data-slot="input-group"
|
|
15
|
+
role="group"
|
|
16
|
+
className={cn(
|
|
17
|
+
"group/input-group relative flex h-7 w-full min-w-0 items-center rounded-md border border-input bg-input/20 transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-2 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const inputGroupAddonVariants = cva(
|
|
26
|
+
"flex h-auto cursor-text items-center justify-center gap-1 py-2 text-xs/relaxed font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-[calc(var(--radius-sm)-2px)] **:data-[slot=kbd]:bg-muted-foreground/10 **:data-[slot=kbd]:px-1 **:data-[slot=kbd]:text-[0.625rem] [&>svg:not([class*='size-'])]:size-3.5",
|
|
27
|
+
{
|
|
28
|
+
variants: {
|
|
29
|
+
align: {
|
|
30
|
+
"inline-start":
|
|
31
|
+
"order-first pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem]",
|
|
32
|
+
"inline-end":
|
|
33
|
+
"order-last pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem]",
|
|
34
|
+
"block-start":
|
|
35
|
+
"order-first w-full justify-start px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
|
|
36
|
+
"block-end":
|
|
37
|
+
"order-last w-full justify-start px-2 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: {
|
|
41
|
+
align: "inline-start",
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
function InputGroupAddon({
|
|
47
|
+
className,
|
|
48
|
+
align = "inline-start",
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
role="group"
|
|
54
|
+
data-slot="input-group-addon"
|
|
55
|
+
data-align={align}
|
|
56
|
+
className={cn(inputGroupAddonVariants({ align }), className)}
|
|
57
|
+
onClick={(e) => {
|
|
58
|
+
if ((e.target as HTMLElement).closest("button")) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus()
|
|
62
|
+
}}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const inputGroupButtonVariants = cva(
|
|
69
|
+
"flex items-center gap-2 rounded-md text-xs/relaxed shadow-none",
|
|
70
|
+
{
|
|
71
|
+
variants: {
|
|
72
|
+
size: {
|
|
73
|
+
xs: "h-5 gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1 [&>svg:not([class*='size-'])]:size-3",
|
|
74
|
+
sm: "gap-1",
|
|
75
|
+
"icon-xs": "size-6 p-0 has-[>svg]:p-0",
|
|
76
|
+
"icon-sm": "size-7 p-0 has-[>svg]:p-0",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
defaultVariants: {
|
|
80
|
+
size: "xs",
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
function InputGroupButton({
|
|
86
|
+
className,
|
|
87
|
+
type = "button",
|
|
88
|
+
variant = "ghost",
|
|
89
|
+
size = "xs",
|
|
90
|
+
...props
|
|
91
|
+
}: Omit<React.ComponentProps<typeof Button>, "size"> &
|
|
92
|
+
VariantProps<typeof inputGroupButtonVariants>) {
|
|
93
|
+
return (
|
|
94
|
+
<Button
|
|
95
|
+
type={type}
|
|
96
|
+
data-size={size}
|
|
97
|
+
variant={variant}
|
|
98
|
+
className={cn(inputGroupButtonVariants({ size }), className)}
|
|
99
|
+
{...props}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
|
105
|
+
return (
|
|
106
|
+
<span
|
|
107
|
+
className={cn(
|
|
108
|
+
"flex items-center gap-2 text-xs/relaxed text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
109
|
+
className
|
|
110
|
+
)}
|
|
111
|
+
{...props}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function InputGroupInput({
|
|
117
|
+
className,
|
|
118
|
+
...props
|
|
119
|
+
}: React.ComponentProps<"input">) {
|
|
120
|
+
return (
|
|
121
|
+
<Input
|
|
122
|
+
data-slot="input-group-control"
|
|
123
|
+
className={cn(
|
|
124
|
+
"flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function InputGroupTextarea({
|
|
133
|
+
className,
|
|
134
|
+
...props
|
|
135
|
+
}: React.ComponentProps<"textarea">) {
|
|
136
|
+
return (
|
|
137
|
+
<Textarea
|
|
138
|
+
data-slot="input-group-control"
|
|
139
|
+
className={cn(
|
|
140
|
+
"flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent",
|
|
141
|
+
className
|
|
142
|
+
)}
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
InputGroup,
|
|
150
|
+
InputGroupAddon,
|
|
151
|
+
InputGroupButton,
|
|
152
|
+
InputGroupText,
|
|
153
|
+
InputGroupInput,
|
|
154
|
+
InputGroupTextarea,
|
|
155
|
+
}
|