XspecT 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
Potentially problematic release.
This version of XspecT might be problematic. Click here for more details.
- xspect/classify.py +32 -0
- xspect/file_io.py +3 -9
- xspect/filter_sequences.py +56 -0
- xspect/main.py +52 -30
- xspect/mlst_feature/mlst_helper.py +102 -13
- xspect/mlst_feature/pub_mlst_handler.py +32 -6
- xspect/model_management.py +1 -15
- xspect/models/probabilistic_filter_mlst_model.py +160 -32
- xspect/models/probabilistic_filter_model.py +1 -0
- xspect/models/result.py +18 -6
- xspect/ncbi.py +8 -6
- xspect/train.py +13 -5
- xspect/web.py +173 -0
- xspect/xspect-web/.gitignore +24 -0
- xspect/xspect-web/README.md +54 -0
- xspect/xspect-web/components.json +21 -0
- xspect/xspect-web/dist/assets/index-CMG4V7fZ.js +290 -0
- xspect/xspect-web/dist/assets/index-jIKg1HIy.css +1 -0
- xspect/xspect-web/dist/index.html +14 -0
- xspect/xspect-web/dist/vite.svg +1 -0
- xspect/xspect-web/eslint.config.js +28 -0
- xspect/xspect-web/index.html +13 -0
- xspect/xspect-web/package-lock.json +6865 -0
- xspect/xspect-web/package.json +58 -0
- xspect/xspect-web/pnpm-lock.yaml +4317 -0
- xspect/xspect-web/public/vite.svg +1 -0
- xspect/xspect-web/src/App.tsx +29 -0
- xspect/xspect-web/src/api.tsx +62 -0
- xspect/xspect-web/src/assets/react.svg +1 -0
- xspect/xspect-web/src/components/classification-form.tsx +284 -0
- xspect/xspect-web/src/components/classify.tsx +18 -0
- xspect/xspect-web/src/components/data-table.tsx +78 -0
- xspect/xspect-web/src/components/dropdown-checkboxes.tsx +63 -0
- xspect/xspect-web/src/components/dropdown-slider.tsx +42 -0
- xspect/xspect-web/src/components/filter-form.tsx +423 -0
- xspect/xspect-web/src/components/filter.tsx +15 -0
- xspect/xspect-web/src/components/header.tsx +46 -0
- xspect/xspect-web/src/components/landing.tsx +7 -0
- xspect/xspect-web/src/components/models-details.tsx +138 -0
- xspect/xspect-web/src/components/models.tsx +53 -0
- xspect/xspect-web/src/components/result-chart.tsx +44 -0
- xspect/xspect-web/src/components/result.tsx +155 -0
- xspect/xspect-web/src/components/spinner.tsx +30 -0
- xspect/xspect-web/src/components/ui/accordion.tsx +64 -0
- xspect/xspect-web/src/components/ui/button.tsx +59 -0
- xspect/xspect-web/src/components/ui/card.tsx +92 -0
- xspect/xspect-web/src/components/ui/chart.tsx +351 -0
- xspect/xspect-web/src/components/ui/command.tsx +175 -0
- xspect/xspect-web/src/components/ui/dialog.tsx +135 -0
- xspect/xspect-web/src/components/ui/dropdown-menu.tsx +255 -0
- xspect/xspect-web/src/components/ui/file-upload.tsx +1459 -0
- xspect/xspect-web/src/components/ui/form.tsx +165 -0
- xspect/xspect-web/src/components/ui/input.tsx +21 -0
- xspect/xspect-web/src/components/ui/label.tsx +24 -0
- xspect/xspect-web/src/components/ui/navigation-menu.tsx +168 -0
- xspect/xspect-web/src/components/ui/popover.tsx +46 -0
- xspect/xspect-web/src/components/ui/select.tsx +183 -0
- xspect/xspect-web/src/components/ui/separator.tsx +26 -0
- xspect/xspect-web/src/components/ui/slider.tsx +61 -0
- xspect/xspect-web/src/components/ui/switch.tsx +29 -0
- xspect/xspect-web/src/components/ui/table.tsx +113 -0
- xspect/xspect-web/src/components/ui/tabs.tsx +64 -0
- xspect/xspect-web/src/index.css +120 -0
- xspect/xspect-web/src/lib/utils.ts +6 -0
- xspect/xspect-web/src/main.tsx +10 -0
- xspect/xspect-web/src/types.tsx +34 -0
- xspect/xspect-web/src/utils.tsx +6 -0
- xspect/xspect-web/src/vite-env.d.ts +1 -0
- xspect/xspect-web/tsconfig.app.json +32 -0
- xspect/xspect-web/tsconfig.json +13 -0
- xspect/xspect-web/tsconfig.node.json +24 -0
- xspect/xspect-web/vite.config.ts +24 -0
- {xspect-0.4.0.dist-info → xspect-0.5.0.dist-info}/METADATA +7 -8
- xspect-0.5.0.dist-info/RECORD +85 -0
- {xspect-0.4.0.dist-info → xspect-0.5.0.dist-info}/WHEEL +1 -1
- xspect/fastapi.py +0 -102
- xspect-0.4.0.dist-info/RECORD +0 -24
- {xspect-0.4.0.dist-info → xspect-0.5.0.dist-info}/entry_points.txt +0 -0
- {xspect-0.4.0.dist-info → xspect-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {xspect-0.4.0.dist-info → xspect-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
4
|
+
import {
|
|
5
|
+
Controller,
|
|
6
|
+
FormProvider,
|
|
7
|
+
useFormContext,
|
|
8
|
+
useFormState,
|
|
9
|
+
type ControllerProps,
|
|
10
|
+
type FieldPath,
|
|
11
|
+
type FieldValues,
|
|
12
|
+
} from "react-hook-form"
|
|
13
|
+
|
|
14
|
+
import { cn } from "@/lib/utils"
|
|
15
|
+
import { Label } from "@/components/ui/label"
|
|
16
|
+
|
|
17
|
+
const Form = FormProvider
|
|
18
|
+
|
|
19
|
+
type FormFieldContextValue<
|
|
20
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
21
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
22
|
+
> = {
|
|
23
|
+
name: TName
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const FormFieldContext = React.createContext<FormFieldContextValue>(
|
|
27
|
+
{} as FormFieldContextValue
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const FormField = <
|
|
31
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
32
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
33
|
+
>({
|
|
34
|
+
...props
|
|
35
|
+
}: ControllerProps<TFieldValues, TName>) => {
|
|
36
|
+
return (
|
|
37
|
+
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
38
|
+
<Controller {...props} />
|
|
39
|
+
</FormFieldContext.Provider>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const useFormField = () => {
|
|
44
|
+
const fieldContext = React.useContext(FormFieldContext)
|
|
45
|
+
const itemContext = React.useContext(FormItemContext)
|
|
46
|
+
const { getFieldState } = useFormContext()
|
|
47
|
+
const formState = useFormState({ name: fieldContext.name })
|
|
48
|
+
const fieldState = getFieldState(fieldContext.name, formState)
|
|
49
|
+
|
|
50
|
+
if (!fieldContext) {
|
|
51
|
+
throw new Error("useFormField should be used within <FormField>")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { id } = itemContext
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
id,
|
|
58
|
+
name: fieldContext.name,
|
|
59
|
+
formItemId: `${id}-form-item`,
|
|
60
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
61
|
+
formMessageId: `${id}-form-item-message`,
|
|
62
|
+
...fieldState,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type FormItemContextValue = {
|
|
67
|
+
id: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const FormItemContext = React.createContext<FormItemContextValue>(
|
|
71
|
+
{} as FormItemContextValue
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
75
|
+
const id = React.useId()
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<FormItemContext.Provider value={{ id }}>
|
|
79
|
+
<div
|
|
80
|
+
data-slot="form-item"
|
|
81
|
+
className={cn("grid gap-2", className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
</FormItemContext.Provider>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function FormLabel({
|
|
89
|
+
className,
|
|
90
|
+
...props
|
|
91
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
92
|
+
const { error, formItemId } = useFormField()
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Label
|
|
96
|
+
data-slot="form-label"
|
|
97
|
+
data-error={!!error}
|
|
98
|
+
className={cn("data-[error=true]:text-destructive", className)}
|
|
99
|
+
htmlFor={formItemId}
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
|
|
106
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<Slot
|
|
110
|
+
data-slot="form-control"
|
|
111
|
+
id={formItemId}
|
|
112
|
+
aria-describedby={
|
|
113
|
+
!error
|
|
114
|
+
? `${formDescriptionId}`
|
|
115
|
+
: `${formDescriptionId} ${formMessageId}`
|
|
116
|
+
}
|
|
117
|
+
aria-invalid={!!error}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
124
|
+
const { formDescriptionId } = useFormField()
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<p
|
|
128
|
+
data-slot="form-description"
|
|
129
|
+
id={formDescriptionId}
|
|
130
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
131
|
+
{...props}
|
|
132
|
+
/>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
|
137
|
+
const { error, formMessageId } = useFormField()
|
|
138
|
+
const body = error ? String(error?.message ?? "") : props.children
|
|
139
|
+
|
|
140
|
+
if (!body) {
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<p
|
|
146
|
+
data-slot="form-message"
|
|
147
|
+
id={formMessageId}
|
|
148
|
+
className={cn("text-destructive text-sm", className)}
|
|
149
|
+
{...props}
|
|
150
|
+
>
|
|
151
|
+
{body}
|
|
152
|
+
</p>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export {
|
|
157
|
+
useFormField,
|
|
158
|
+
Form,
|
|
159
|
+
FormItem,
|
|
160
|
+
FormLabel,
|
|
161
|
+
FormControl,
|
|
162
|
+
FormDescription,
|
|
163
|
+
FormMessage,
|
|
164
|
+
FormField,
|
|
165
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
6
|
+
return (
|
|
7
|
+
<input
|
|
8
|
+
type={type}
|
|
9
|
+
data-slot="input"
|
|
10
|
+
className={cn(
|
|
11
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex 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",
|
|
12
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
13
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Input }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
function Label({
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<LabelPrimitive.Root
|
|
14
|
+
data-slot="label"
|
|
15
|
+
className={cn(
|
|
16
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Label }
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
|
3
|
+
import { cva } from "class-variance-authority"
|
|
4
|
+
import { ChevronDownIcon } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
function NavigationMenu({
|
|
9
|
+
className,
|
|
10
|
+
children,
|
|
11
|
+
viewport = true,
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
|
|
14
|
+
viewport?: boolean
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<NavigationMenuPrimitive.Root
|
|
18
|
+
data-slot="navigation-menu"
|
|
19
|
+
data-viewport={viewport}
|
|
20
|
+
className={cn(
|
|
21
|
+
"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
{viewport && <NavigationMenuViewport />}
|
|
28
|
+
</NavigationMenuPrimitive.Root>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function NavigationMenuList({
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
|
|
36
|
+
return (
|
|
37
|
+
<NavigationMenuPrimitive.List
|
|
38
|
+
data-slot="navigation-menu-list"
|
|
39
|
+
className={cn(
|
|
40
|
+
"group flex flex-1 list-none items-center justify-center gap-1",
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function NavigationMenuItem({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
|
|
52
|
+
return (
|
|
53
|
+
<NavigationMenuPrimitive.Item
|
|
54
|
+
data-slot="navigation-menu-item"
|
|
55
|
+
className={cn("relative", className)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const navigationMenuTriggerStyle = cva(
|
|
62
|
+
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
function NavigationMenuTrigger({
|
|
66
|
+
className,
|
|
67
|
+
children,
|
|
68
|
+
...props
|
|
69
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
|
|
70
|
+
return (
|
|
71
|
+
<NavigationMenuPrimitive.Trigger
|
|
72
|
+
data-slot="navigation-menu-trigger"
|
|
73
|
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
{children}{" "}
|
|
77
|
+
<ChevronDownIcon
|
|
78
|
+
className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
79
|
+
aria-hidden="true"
|
|
80
|
+
/>
|
|
81
|
+
</NavigationMenuPrimitive.Trigger>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function NavigationMenuContent({
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
|
|
89
|
+
return (
|
|
90
|
+
<NavigationMenuPrimitive.Content
|
|
91
|
+
data-slot="navigation-menu-content"
|
|
92
|
+
className={cn(
|
|
93
|
+
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto",
|
|
94
|
+
"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
|
|
95
|
+
className
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function NavigationMenuViewport({
|
|
103
|
+
className,
|
|
104
|
+
...props
|
|
105
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
className={cn(
|
|
109
|
+
"absolute top-full left-0 isolate z-50 flex justify-center"
|
|
110
|
+
)}
|
|
111
|
+
>
|
|
112
|
+
<NavigationMenuPrimitive.Viewport
|
|
113
|
+
data-slot="navigation-menu-viewport"
|
|
114
|
+
className={cn(
|
|
115
|
+
"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
116
|
+
className
|
|
117
|
+
)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function NavigationMenuLink({
|
|
125
|
+
className,
|
|
126
|
+
...props
|
|
127
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
|
|
128
|
+
return (
|
|
129
|
+
<NavigationMenuPrimitive.Link
|
|
130
|
+
data-slot="navigation-menu-link"
|
|
131
|
+
className={cn(
|
|
132
|
+
"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4",
|
|
133
|
+
className
|
|
134
|
+
)}
|
|
135
|
+
{...props}
|
|
136
|
+
/>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function NavigationMenuIndicator({
|
|
141
|
+
className,
|
|
142
|
+
...props
|
|
143
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
|
|
144
|
+
return (
|
|
145
|
+
<NavigationMenuPrimitive.Indicator
|
|
146
|
+
data-slot="navigation-menu-indicator"
|
|
147
|
+
className={cn(
|
|
148
|
+
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
|
|
149
|
+
className
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
>
|
|
153
|
+
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
|
|
154
|
+
</NavigationMenuPrimitive.Indicator>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
NavigationMenu,
|
|
160
|
+
NavigationMenuList,
|
|
161
|
+
NavigationMenuItem,
|
|
162
|
+
NavigationMenuContent,
|
|
163
|
+
NavigationMenuTrigger,
|
|
164
|
+
NavigationMenuLink,
|
|
165
|
+
NavigationMenuIndicator,
|
|
166
|
+
NavigationMenuViewport,
|
|
167
|
+
navigationMenuTriggerStyle,
|
|
168
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Popover({
|
|
7
|
+
...props
|
|
8
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
9
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function PopoverTrigger({
|
|
13
|
+
...props
|
|
14
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
15
|
+
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function PopoverContent({
|
|
19
|
+
className,
|
|
20
|
+
align = "center",
|
|
21
|
+
sideOffset = 4,
|
|
22
|
+
...props
|
|
23
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
24
|
+
return (
|
|
25
|
+
<PopoverPrimitive.Portal>
|
|
26
|
+
<PopoverPrimitive.Content
|
|
27
|
+
data-slot="popover-content"
|
|
28
|
+
align={align}
|
|
29
|
+
sideOffset={sideOffset}
|
|
30
|
+
className={cn(
|
|
31
|
+
"bg-popover text-popover-foreground 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 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
</PopoverPrimitive.Portal>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function PopoverAnchor({
|
|
41
|
+
...props
|
|
42
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
43
|
+
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select"
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
function Select({
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
10
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function SelectGroup({
|
|
14
|
+
...props
|
|
15
|
+
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
|
16
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function SelectValue({
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
|
22
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function SelectTrigger({
|
|
26
|
+
className,
|
|
27
|
+
size = "default",
|
|
28
|
+
children,
|
|
29
|
+
...props
|
|
30
|
+
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
|
31
|
+
size?: "sm" | "default"
|
|
32
|
+
}) {
|
|
33
|
+
return (
|
|
34
|
+
<SelectPrimitive.Trigger
|
|
35
|
+
data-slot="select-trigger"
|
|
36
|
+
data-size={size}
|
|
37
|
+
className={cn(
|
|
38
|
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
<SelectPrimitive.Icon asChild>
|
|
45
|
+
<ChevronDownIcon className="size-4 opacity-50" />
|
|
46
|
+
</SelectPrimitive.Icon>
|
|
47
|
+
</SelectPrimitive.Trigger>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function SelectContent({
|
|
52
|
+
className,
|
|
53
|
+
children,
|
|
54
|
+
position = "popper",
|
|
55
|
+
...props
|
|
56
|
+
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
57
|
+
return (
|
|
58
|
+
<SelectPrimitive.Portal>
|
|
59
|
+
<SelectPrimitive.Content
|
|
60
|
+
data-slot="select-content"
|
|
61
|
+
className={cn(
|
|
62
|
+
"bg-popover text-popover-foreground 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 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
|
63
|
+
position === "popper" &&
|
|
64
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
position={position}
|
|
68
|
+
{...props}
|
|
69
|
+
>
|
|
70
|
+
<SelectScrollUpButton />
|
|
71
|
+
<SelectPrimitive.Viewport
|
|
72
|
+
className={cn(
|
|
73
|
+
"p-1",
|
|
74
|
+
position === "popper" &&
|
|
75
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</SelectPrimitive.Viewport>
|
|
80
|
+
<SelectScrollDownButton />
|
|
81
|
+
</SelectPrimitive.Content>
|
|
82
|
+
</SelectPrimitive.Portal>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function SelectLabel({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
|
90
|
+
return (
|
|
91
|
+
<SelectPrimitive.Label
|
|
92
|
+
data-slot="select-label"
|
|
93
|
+
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
|
94
|
+
{...props}
|
|
95
|
+
/>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function SelectItem({
|
|
100
|
+
className,
|
|
101
|
+
children,
|
|
102
|
+
...props
|
|
103
|
+
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
|
104
|
+
return (
|
|
105
|
+
<SelectPrimitive.Item
|
|
106
|
+
data-slot="select-item"
|
|
107
|
+
className={cn(
|
|
108
|
+
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
109
|
+
className
|
|
110
|
+
)}
|
|
111
|
+
{...props}
|
|
112
|
+
>
|
|
113
|
+
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
|
114
|
+
<SelectPrimitive.ItemIndicator>
|
|
115
|
+
<CheckIcon className="size-4" />
|
|
116
|
+
</SelectPrimitive.ItemIndicator>
|
|
117
|
+
</span>
|
|
118
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
119
|
+
</SelectPrimitive.Item>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function SelectSeparator({
|
|
124
|
+
className,
|
|
125
|
+
...props
|
|
126
|
+
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
127
|
+
return (
|
|
128
|
+
<SelectPrimitive.Separator
|
|
129
|
+
data-slot="select-separator"
|
|
130
|
+
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
|
131
|
+
{...props}
|
|
132
|
+
/>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function SelectScrollUpButton({
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
139
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
140
|
+
return (
|
|
141
|
+
<SelectPrimitive.ScrollUpButton
|
|
142
|
+
data-slot="select-scroll-up-button"
|
|
143
|
+
className={cn(
|
|
144
|
+
"flex cursor-default items-center justify-center py-1",
|
|
145
|
+
className
|
|
146
|
+
)}
|
|
147
|
+
{...props}
|
|
148
|
+
>
|
|
149
|
+
<ChevronUpIcon className="size-4" />
|
|
150
|
+
</SelectPrimitive.ScrollUpButton>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function SelectScrollDownButton({
|
|
155
|
+
className,
|
|
156
|
+
...props
|
|
157
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
158
|
+
return (
|
|
159
|
+
<SelectPrimitive.ScrollDownButton
|
|
160
|
+
data-slot="select-scroll-down-button"
|
|
161
|
+
className={cn(
|
|
162
|
+
"flex cursor-default items-center justify-center py-1",
|
|
163
|
+
className
|
|
164
|
+
)}
|
|
165
|
+
{...props}
|
|
166
|
+
>
|
|
167
|
+
<ChevronDownIcon className="size-4" />
|
|
168
|
+
</SelectPrimitive.ScrollDownButton>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
Select,
|
|
174
|
+
SelectContent,
|
|
175
|
+
SelectGroup,
|
|
176
|
+
SelectItem,
|
|
177
|
+
SelectLabel,
|
|
178
|
+
SelectScrollDownButton,
|
|
179
|
+
SelectScrollUpButton,
|
|
180
|
+
SelectSeparator,
|
|
181
|
+
SelectTrigger,
|
|
182
|
+
SelectValue,
|
|
183
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Separator({
|
|
7
|
+
className,
|
|
8
|
+
orientation = "horizontal",
|
|
9
|
+
decorative = true,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<SeparatorPrimitive.Root
|
|
14
|
+
data-slot="separator-root"
|
|
15
|
+
decorative={decorative}
|
|
16
|
+
orientation={orientation}
|
|
17
|
+
className={cn(
|
|
18
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { Separator }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SliderPrimitive from "@radix-ui/react-slider"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Slider({
|
|
7
|
+
className,
|
|
8
|
+
defaultValue,
|
|
9
|
+
value,
|
|
10
|
+
min = 0,
|
|
11
|
+
max = 100,
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof SliderPrimitive.Root>) {
|
|
14
|
+
const _values = React.useMemo(
|
|
15
|
+
() =>
|
|
16
|
+
Array.isArray(value)
|
|
17
|
+
? value
|
|
18
|
+
: Array.isArray(defaultValue)
|
|
19
|
+
? defaultValue
|
|
20
|
+
: [min, max],
|
|
21
|
+
[value, defaultValue, min, max]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<SliderPrimitive.Root
|
|
26
|
+
data-slot="slider"
|
|
27
|
+
defaultValue={defaultValue}
|
|
28
|
+
value={value}
|
|
29
|
+
min={min}
|
|
30
|
+
max={max}
|
|
31
|
+
className={cn(
|
|
32
|
+
"relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
<SliderPrimitive.Track
|
|
38
|
+
data-slot="slider-track"
|
|
39
|
+
className={cn(
|
|
40
|
+
"bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
<SliderPrimitive.Range
|
|
44
|
+
data-slot="slider-range"
|
|
45
|
+
className={cn(
|
|
46
|
+
"bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
|
|
47
|
+
)}
|
|
48
|
+
/>
|
|
49
|
+
</SliderPrimitive.Track>
|
|
50
|
+
{Array.from({ length: _values.length }, (_, index) => (
|
|
51
|
+
<SliderPrimitive.Thumb
|
|
52
|
+
data-slot="slider-thumb"
|
|
53
|
+
key={index}
|
|
54
|
+
className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</SliderPrimitive.Root>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { Slider }
|