selftune 0.2.2 → 0.2.6

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.
Files changed (53) hide show
  1. package/README.md +11 -0
  2. package/apps/local-dashboard/dist/assets/index-C75H1Q3n.css +1 -0
  3. package/apps/local-dashboard/dist/assets/index-axE4kz3Q.js +15 -0
  4. package/apps/local-dashboard/dist/assets/vendor-ui-r2k_Ku_V.js +346 -0
  5. package/apps/local-dashboard/dist/index.html +3 -3
  6. package/cli/selftune/analytics.ts +354 -0
  7. package/cli/selftune/badge/badge.ts +2 -2
  8. package/cli/selftune/dashboard-server.ts +3 -3
  9. package/cli/selftune/evolution/evolve-body.ts +1 -1
  10. package/cli/selftune/evolution/evolve.ts +1 -1
  11. package/cli/selftune/index.ts +15 -1
  12. package/cli/selftune/init.ts +5 -1
  13. package/cli/selftune/observability.ts +63 -2
  14. package/cli/selftune/orchestrate.ts +1 -1
  15. package/cli/selftune/quickstart.ts +1 -1
  16. package/cli/selftune/status.ts +2 -2
  17. package/cli/selftune/types.ts +1 -0
  18. package/cli/selftune/utils/llm-call.ts +2 -1
  19. package/package.json +6 -4
  20. package/packages/ui/README.md +113 -0
  21. package/packages/ui/index.ts +10 -0
  22. package/packages/ui/package.json +62 -0
  23. package/packages/ui/src/components/ActivityTimeline.tsx +171 -0
  24. package/packages/ui/src/components/EvidenceViewer.tsx +718 -0
  25. package/packages/ui/src/components/EvolutionTimeline.tsx +252 -0
  26. package/packages/ui/src/components/InfoTip.tsx +19 -0
  27. package/packages/ui/src/components/OrchestrateRunsPanel.tsx +164 -0
  28. package/packages/ui/src/components/index.ts +7 -0
  29. package/packages/ui/src/components/section-cards.tsx +155 -0
  30. package/packages/ui/src/components/skill-health-grid.tsx +686 -0
  31. package/packages/ui/src/lib/constants.tsx +43 -0
  32. package/packages/ui/src/lib/format.ts +37 -0
  33. package/packages/ui/src/lib/index.ts +3 -0
  34. package/packages/ui/src/lib/utils.ts +6 -0
  35. package/packages/ui/src/primitives/badge.tsx +52 -0
  36. package/packages/ui/src/primitives/button.tsx +58 -0
  37. package/packages/ui/src/primitives/card.tsx +103 -0
  38. package/packages/ui/src/primitives/checkbox.tsx +27 -0
  39. package/packages/ui/src/primitives/collapsible.tsx +7 -0
  40. package/packages/ui/src/primitives/dropdown-menu.tsx +266 -0
  41. package/packages/ui/src/primitives/index.ts +55 -0
  42. package/packages/ui/src/primitives/label.tsx +20 -0
  43. package/packages/ui/src/primitives/select.tsx +197 -0
  44. package/packages/ui/src/primitives/table.tsx +114 -0
  45. package/packages/ui/src/primitives/tabs.tsx +82 -0
  46. package/packages/ui/src/primitives/tooltip.tsx +64 -0
  47. package/packages/ui/src/types.ts +87 -0
  48. package/packages/ui/tsconfig.json +17 -0
  49. package/skill/SKILL.md +3 -0
  50. package/skill/Workflows/Telemetry.md +59 -0
  51. package/apps/local-dashboard/dist/assets/index-C4EOTFZ2.js +0 -15
  52. package/apps/local-dashboard/dist/assets/index-bl-Webyd.css +0 -1
  53. package/apps/local-dashboard/dist/assets/vendor-ui-D7_zX_qy.js +0 -346
@@ -0,0 +1,43 @@
1
+ import {
2
+ AlertTriangleIcon,
3
+ CheckCircleIcon,
4
+ CircleDotIcon,
5
+ HelpCircleIcon,
6
+ XCircleIcon,
7
+ } from "lucide-react";
8
+ import type { SkillHealthStatus } from "../types";
9
+
10
+ export const STATUS_CONFIG: Record<
11
+ SkillHealthStatus,
12
+ {
13
+ icon: React.ReactNode;
14
+ variant: "default" | "secondary" | "destructive" | "outline";
15
+ label: string;
16
+ }
17
+ > = {
18
+ HEALTHY: {
19
+ icon: <CheckCircleIcon className="size-4 text-emerald-600" />,
20
+ variant: "outline",
21
+ label: "Healthy",
22
+ },
23
+ WARNING: {
24
+ icon: <AlertTriangleIcon className="size-4 text-amber-500" />,
25
+ variant: "secondary",
26
+ label: "Warning",
27
+ },
28
+ CRITICAL: {
29
+ icon: <XCircleIcon className="size-4 text-red-500" />,
30
+ variant: "destructive",
31
+ label: "Critical",
32
+ },
33
+ UNGRADED: {
34
+ icon: <CircleDotIcon className="size-4 text-muted-foreground" />,
35
+ variant: "secondary",
36
+ label: "Ungraded",
37
+ },
38
+ UNKNOWN: {
39
+ icon: <HelpCircleIcon className="size-4 text-muted-foreground/60" />,
40
+ variant: "secondary",
41
+ label: "Unknown",
42
+ },
43
+ };
@@ -0,0 +1,37 @@
1
+ import type { SkillHealthStatus } from "../types";
2
+
3
+ export function deriveStatus(passRate: number, checks: number): SkillHealthStatus {
4
+ if (checks < 5) return "UNGRADED";
5
+ if (passRate >= 0.8) return "HEALTHY";
6
+ if (passRate >= 0.5) return "WARNING";
7
+ return "CRITICAL";
8
+ }
9
+
10
+ export function formatRate(rate: number | null | undefined): string {
11
+ if (rate === null || rate === undefined || !Number.isFinite(rate)) return "--";
12
+ return `${Math.round(rate * 100)}%`;
13
+ }
14
+
15
+ export function sortByPassRateAndChecks<T extends { passRate: number | null; checks: number }>(
16
+ items: T[],
17
+ ): T[] {
18
+ return [...items].sort((a, b) => {
19
+ const aRate = a.passRate ?? 1;
20
+ const bRate = b.passRate ?? 1;
21
+ if (aRate !== bRate) return aRate - bRate;
22
+ return b.checks - a.checks;
23
+ });
24
+ }
25
+
26
+ export function timeAgo(timestamp: string): string {
27
+ const ts = new Date(timestamp).getTime();
28
+ if (Number.isNaN(ts)) return "--";
29
+ const diff = Math.max(0, Date.now() - ts);
30
+ const mins = Math.floor(diff / 60000);
31
+ if (mins < 1) return "just now";
32
+ if (mins < 60) return `${mins}m ago`;
33
+ const hours = Math.floor(mins / 60);
34
+ if (hours < 24) return `${hours}h ago`;
35
+ const days = Math.floor(hours / 24);
36
+ return `${days}d ago`;
37
+ }
@@ -0,0 +1,3 @@
1
+ export { STATUS_CONFIG } from "./constants";
2
+ export { deriveStatus, formatRate, sortByPassRateAndChecks, timeAgo } from "./format";
3
+ export { cn } from "./utils";
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,52 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
+ destructive:
16
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
17
+ outline:
18
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
19
+ ghost:
20
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ },
27
+ }
28
+ )
29
+
30
+ function Badge({
31
+ className,
32
+ variant = "default",
33
+ render,
34
+ ...props
35
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
36
+ return useRender({
37
+ defaultTagName: "span",
38
+ props: mergeProps<"span">(
39
+ {
40
+ className: cn(badgeVariants({ variant }), className),
41
+ },
42
+ props
43
+ ),
44
+ render,
45
+ state: {
46
+ slot: "badge",
47
+ variant,
48
+ },
49
+ })
50
+ }
51
+
52
+ export { Badge, badgeVariants }
@@ -0,0 +1,58 @@
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "../lib/utils"
5
+
6
+ const buttonVariants = cva(
7
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
12
+ outline:
13
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
14
+ secondary:
15
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
16
+ ghost:
17
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
18
+ destructive:
19
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default:
24
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
25
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
26
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
27
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
28
+ icon: "size-8",
29
+ "icon-xs":
30
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
31
+ "icon-sm":
32
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
33
+ "icon-lg": "size-9",
34
+ },
35
+ },
36
+ defaultVariants: {
37
+ variant: "default",
38
+ size: "default",
39
+ },
40
+ }
41
+ )
42
+
43
+ function Button({
44
+ className,
45
+ variant = "default",
46
+ size = "default",
47
+ ...props
48
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
49
+ return (
50
+ <ButtonPrimitive
51
+ data-slot="button"
52
+ className={cn(buttonVariants({ variant, size, className }))}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ export { Button, buttonVariants }
@@ -0,0 +1,103 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../lib/utils"
4
+
5
+ function Card({
6
+ className,
7
+ size = "default",
8
+ ...props
9
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
10
+ return (
11
+ <div
12
+ data-slot="card"
13
+ data-size={size}
14
+ className={cn(
15
+ "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
24
+ return (
25
+ <div
26
+ data-slot="card-header"
27
+ className={cn(
28
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
29
+ className
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
37
+ return (
38
+ <div
39
+ data-slot="card-title"
40
+ className={cn(
41
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
50
+ return (
51
+ <div
52
+ data-slot="card-description"
53
+ className={cn("text-sm text-muted-foreground", className)}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ data-slot="card-action"
63
+ className={cn(
64
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
65
+ className
66
+ )}
67
+ {...props}
68
+ />
69
+ )
70
+ }
71
+
72
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ data-slot="card-content"
76
+ className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
77
+ {...props}
78
+ />
79
+ )
80
+ }
81
+
82
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ data-slot="card-footer"
86
+ className={cn(
87
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ export {
96
+ Card,
97
+ CardHeader,
98
+ CardFooter,
99
+ CardTitle,
100
+ CardAction,
101
+ CardDescription,
102
+ CardContent,
103
+ }
@@ -0,0 +1,27 @@
1
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
2
+
3
+ import { cn } from "../lib/utils"
4
+ import { CheckIcon } from "lucide-react"
5
+
6
+ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
7
+ return (
8
+ <CheckboxPrimitive.Root
9
+ data-slot="checkbox"
10
+ className={cn(
11
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
12
+ className
13
+ )}
14
+ {...props}
15
+ >
16
+ <CheckboxPrimitive.Indicator
17
+ data-slot="checkbox-indicator"
18
+ className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
19
+ >
20
+ <CheckIcon
21
+ />
22
+ </CheckboxPrimitive.Indicator>
23
+ </CheckboxPrimitive.Root>
24
+ )
25
+ }
26
+
27
+ export { Checkbox }
@@ -0,0 +1,7 @@
1
+ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
2
+
3
+ const Collapsible = CollapsiblePrimitive.Root
4
+ const CollapsibleTrigger = CollapsiblePrimitive.Trigger
5
+ const CollapsibleContent = CollapsiblePrimitive.Panel
6
+
7
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,266 @@
1
+ import * as React from "react"
2
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu"
3
+
4
+ import { cn } from "../lib/utils"
5
+ import { ChevronRightIcon, CheckIcon } from "lucide-react"
6
+
7
+ function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
8
+ return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
9
+ }
10
+
11
+ function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
12
+ return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
13
+ }
14
+
15
+ function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
16
+ return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
17
+ }
18
+
19
+ function DropdownMenuContent({
20
+ align = "start",
21
+ alignOffset = 0,
22
+ side = "bottom",
23
+ sideOffset = 4,
24
+ className,
25
+ ...props
26
+ }: MenuPrimitive.Popup.Props &
27
+ Pick<
28
+ MenuPrimitive.Positioner.Props,
29
+ "align" | "alignOffset" | "side" | "sideOffset"
30
+ >) {
31
+ return (
32
+ <MenuPrimitive.Portal>
33
+ <MenuPrimitive.Positioner
34
+ className="isolate z-50 outline-hidden"
35
+ align={align}
36
+ alignOffset={alignOffset}
37
+ side={side}
38
+ sideOffset={sideOffset}
39
+ >
40
+ <MenuPrimitive.Popup
41
+ data-slot="dropdown-menu-content"
42
+ className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className )}
43
+ {...props}
44
+ />
45
+ </MenuPrimitive.Positioner>
46
+ </MenuPrimitive.Portal>
47
+ )
48
+ }
49
+
50
+ function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
51
+ return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
52
+ }
53
+
54
+ function DropdownMenuLabel({
55
+ className,
56
+ inset,
57
+ ...props
58
+ }: MenuPrimitive.GroupLabel.Props & {
59
+ inset?: boolean
60
+ }) {
61
+ return (
62
+ <MenuPrimitive.GroupLabel
63
+ data-slot="dropdown-menu-label"
64
+ data-inset={inset}
65
+ className={cn(
66
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
67
+ className
68
+ )}
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ function DropdownMenuItem({
75
+ className,
76
+ inset,
77
+ variant = "default",
78
+ ...props
79
+ }: MenuPrimitive.Item.Props & {
80
+ inset?: boolean
81
+ variant?: "default" | "destructive"
82
+ }) {
83
+ return (
84
+ <MenuPrimitive.Item
85
+ data-slot="dropdown-menu-item"
86
+ data-inset={inset}
87
+ data-variant={variant}
88
+ className={cn(
89
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:[&_svg]:text-destructive",
90
+ className
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
98
+ return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
99
+ }
100
+
101
+ function DropdownMenuSubTrigger({
102
+ className,
103
+ inset,
104
+ children,
105
+ ...props
106
+ }: MenuPrimitive.SubmenuTrigger.Props & {
107
+ inset?: boolean
108
+ }) {
109
+ return (
110
+ <MenuPrimitive.SubmenuTrigger
111
+ data-slot="dropdown-menu-sub-trigger"
112
+ data-inset={inset}
113
+ className={cn(
114
+ "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
115
+ className
116
+ )}
117
+ {...props}
118
+ >
119
+ {children}
120
+ <ChevronRightIcon className="ml-auto" />
121
+ </MenuPrimitive.SubmenuTrigger>
122
+ )
123
+ }
124
+
125
+ function DropdownMenuSubContent({
126
+ align = "start",
127
+ alignOffset = -3,
128
+ side = "right",
129
+ sideOffset = 0,
130
+ className,
131
+ ...props
132
+ }: React.ComponentProps<typeof DropdownMenuContent>) {
133
+ return (
134
+ <DropdownMenuContent
135
+ data-slot="dropdown-menu-sub-content"
136
+ className={cn("w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 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 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", className )}
137
+ align={align}
138
+ alignOffset={alignOffset}
139
+ side={side}
140
+ sideOffset={sideOffset}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ function DropdownMenuCheckboxItem({
147
+ className,
148
+ children,
149
+ checked,
150
+ inset,
151
+ ...props
152
+ }: MenuPrimitive.CheckboxItem.Props & {
153
+ inset?: boolean
154
+ }) {
155
+ return (
156
+ <MenuPrimitive.CheckboxItem
157
+ data-slot="dropdown-menu-checkbox-item"
158
+ data-inset={inset}
159
+ className={cn(
160
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
161
+ className
162
+ )}
163
+ checked={checked}
164
+ {...props}
165
+ >
166
+ <span
167
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
168
+ data-slot="dropdown-menu-checkbox-item-indicator"
169
+ >
170
+ <MenuPrimitive.CheckboxItemIndicator>
171
+ <CheckIcon
172
+ />
173
+ </MenuPrimitive.CheckboxItemIndicator>
174
+ </span>
175
+ {children}
176
+ </MenuPrimitive.CheckboxItem>
177
+ )
178
+ }
179
+
180
+ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
181
+ return (
182
+ <MenuPrimitive.RadioGroup
183
+ data-slot="dropdown-menu-radio-group"
184
+ {...props}
185
+ />
186
+ )
187
+ }
188
+
189
+ function DropdownMenuRadioItem({
190
+ className,
191
+ children,
192
+ inset,
193
+ ...props
194
+ }: MenuPrimitive.RadioItem.Props & {
195
+ inset?: boolean
196
+ }) {
197
+ return (
198
+ <MenuPrimitive.RadioItem
199
+ data-slot="dropdown-menu-radio-item"
200
+ data-inset={inset}
201
+ className={cn(
202
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
203
+ className
204
+ )}
205
+ {...props}
206
+ >
207
+ <span
208
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
209
+ data-slot="dropdown-menu-radio-item-indicator"
210
+ >
211
+ <MenuPrimitive.RadioItemIndicator>
212
+ <CheckIcon
213
+ />
214
+ </MenuPrimitive.RadioItemIndicator>
215
+ </span>
216
+ {children}
217
+ </MenuPrimitive.RadioItem>
218
+ )
219
+ }
220
+
221
+ function DropdownMenuSeparator({
222
+ className,
223
+ ...props
224
+ }: MenuPrimitive.Separator.Props) {
225
+ return (
226
+ <MenuPrimitive.Separator
227
+ data-slot="dropdown-menu-separator"
228
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
229
+ {...props}
230
+ />
231
+ )
232
+ }
233
+
234
+ function DropdownMenuShortcut({
235
+ className,
236
+ ...props
237
+ }: React.ComponentProps<"span">) {
238
+ return (
239
+ <span
240
+ data-slot="dropdown-menu-shortcut"
241
+ className={cn(
242
+ "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
243
+ className
244
+ )}
245
+ {...props}
246
+ />
247
+ )
248
+ }
249
+
250
+ export {
251
+ DropdownMenu,
252
+ DropdownMenuPortal,
253
+ DropdownMenuTrigger,
254
+ DropdownMenuContent,
255
+ DropdownMenuGroup,
256
+ DropdownMenuLabel,
257
+ DropdownMenuItem,
258
+ DropdownMenuCheckboxItem,
259
+ DropdownMenuRadioGroup,
260
+ DropdownMenuRadioItem,
261
+ DropdownMenuSeparator,
262
+ DropdownMenuShortcut,
263
+ DropdownMenuSub,
264
+ DropdownMenuSubTrigger,
265
+ DropdownMenuSubContent,
266
+ }
@@ -0,0 +1,55 @@
1
+ export { Badge, badgeVariants } from "./badge";
2
+ export { Button, buttonVariants } from "./button";
3
+ export {
4
+ Card,
5
+ CardAction,
6
+ CardContent,
7
+ CardDescription,
8
+ CardFooter,
9
+ CardHeader,
10
+ CardTitle,
11
+ } from "./card";
12
+ export { Checkbox } from "./checkbox";
13
+ export { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./collapsible";
14
+ export {
15
+ DropdownMenu,
16
+ DropdownMenuCheckboxItem,
17
+ DropdownMenuContent,
18
+ DropdownMenuGroup,
19
+ DropdownMenuItem,
20
+ DropdownMenuLabel,
21
+ DropdownMenuPortal,
22
+ DropdownMenuRadioGroup,
23
+ DropdownMenuRadioItem,
24
+ DropdownMenuSeparator,
25
+ DropdownMenuShortcut,
26
+ DropdownMenuSub,
27
+ DropdownMenuSubContent,
28
+ DropdownMenuSubTrigger,
29
+ DropdownMenuTrigger,
30
+ } from "./dropdown-menu";
31
+ export { Label } from "./label";
32
+ export {
33
+ Select,
34
+ SelectContent,
35
+ SelectGroup,
36
+ SelectItem,
37
+ SelectLabel,
38
+ SelectScrollDownButton,
39
+ SelectScrollUpButton,
40
+ SelectSeparator,
41
+ SelectTrigger,
42
+ SelectValue,
43
+ } from "./select";
44
+ export {
45
+ Table,
46
+ TableBody,
47
+ TableCaption,
48
+ TableCell,
49
+ TableFooter,
50
+ TableHead,
51
+ TableHeader,
52
+ TableRow,
53
+ } from "./table";
54
+ export { Tabs, TabsContent, TabsList, TabsTrigger, tabsListVariants } from "./tabs";
55
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip";
@@ -0,0 +1,20 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ function Label({ className, ...props }: React.ComponentProps<"label">) {
8
+ return (
9
+ <label
10
+ data-slot="label"
11
+ className={cn(
12
+ "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",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ export { Label }