chore: remove debugging throughout codebase
This commit is contained in:
parent
dc0a8e7c96
commit
1fa5442f21
|
|
@ -1,303 +1,302 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import {
|
||||
Tick02Icon,
|
||||
ArrowRightIcon,
|
||||
CircleIcon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function ContextMenu({
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "context-menu",
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<ContextMenuPrimitive.Root onOpenChange={handleOpenChange} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
||||
|
||||
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
||||
|
||||
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
||||
|
||||
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
||||
|
||||
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
||||
|
||||
const contextMenuItemVariants = cva(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-3 py-1.5 text-sm text-foreground/85 outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-3.5 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"focus:bg-accent focus:text-accent-foreground [&_svg]:text-muted-foreground",
|
||||
destructive:
|
||||
"text-destructive focus:bg-destructive/10 focus:text-destructive [&_svg]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const ContextMenuSubTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean;
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ className, inset, children, variant = "default", icon, ...props },
|
||||
ref,
|
||||
) => (
|
||||
<ContextMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
"data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
<HugeiconsIcon
|
||||
icon={ArrowRightIcon}
|
||||
className="ml-auto text-muted-foreground/80"
|
||||
/>
|
||||
</ContextMenuPrimitive.SubTrigger>
|
||||
),
|
||||
);
|
||||
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
||||
|
||||
const ContextMenuSubContent = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 min-w-48 overflow-hidden rounded-md border shadow-xl p-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
||||
|
||||
const ContextMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content> & {
|
||||
container?: HTMLElement | null;
|
||||
}
|
||||
>(({ className, container, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Portal container={container ?? undefined}>
|
||||
<ContextMenuPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 min-w-48 overflow-hidden rounded-md border shadow-xl p-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</ContextMenuPrimitive.Portal>
|
||||
));
|
||||
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
||||
|
||||
const ContextMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
|
||||
inset?: boolean;
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
textRight?: string;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
inset,
|
||||
variant = "default",
|
||||
icon,
|
||||
children,
|
||||
textRight,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const shouldInsetContent = inset || Boolean(icon);
|
||||
|
||||
return (
|
||||
<ContextMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
shouldInsetContent && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="absolute left-3 flex size-3.5 items-center justify-center text-muted-foreground [&_svg]:size-3.5 [&_svg]:shrink-0">
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
{textRight && (
|
||||
<span className="ml-auto text-[0.60rem] tracking-widest text-muted-foreground/80 mb-0.5">
|
||||
{textRight}
|
||||
</span>
|
||||
)}
|
||||
</ContextMenuPrimitive.Item>
|
||||
);
|
||||
},
|
||||
);
|
||||
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
||||
|
||||
const ContextMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem> & {
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ className, children, checked, variant = "default", icon, ...props },
|
||||
ref,
|
||||
) => (
|
||||
<ContextMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
"pr-2 pl-8",
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-3 flex size-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.ItemIndicator>
|
||||
<HugeiconsIcon icon={Tick02Icon} className="size-4" />
|
||||
</ContextMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.CheckboxItem>
|
||||
),
|
||||
);
|
||||
ContextMenuCheckboxItem.displayName =
|
||||
ContextMenuPrimitive.CheckboxItem.displayName;
|
||||
|
||||
const ContextMenuRadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem> & {
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, children, variant = "default", icon, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(contextMenuItemVariants({ variant }), "pr-2 pl-8", className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.ItemIndicator>
|
||||
<HugeiconsIcon icon={CircleIcon} className="size-2 fill-current" />
|
||||
</ContextMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.RadioItem>
|
||||
));
|
||||
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
||||
|
||||
const ContextMenuLabel = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
||||
inset?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, inset, icon, children, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-1.5 text-sm font-semibold text-foreground",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.Label>
|
||||
));
|
||||
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
||||
|
||||
const ContextMenuSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("bg-border mx-1 my-1.5 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
||||
|
||||
const ContextMenuShortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground opacity-60",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
||||
|
||||
export {
|
||||
ContextMenu,
|
||||
ContextMenuTrigger,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuCheckboxItem,
|
||||
ContextMenuRadioItem,
|
||||
ContextMenuLabel,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuShortcut,
|
||||
ContextMenuGroup,
|
||||
ContextMenuPortal,
|
||||
ContextMenuSub,
|
||||
ContextMenuSubContent,
|
||||
ContextMenuSubTrigger,
|
||||
ContextMenuRadioGroup,
|
||||
};
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import {
|
||||
Tick02Icon,
|
||||
ArrowRightIcon,
|
||||
CircleIcon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function ContextMenu({
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<ContextMenuPrimitive.Root onOpenChange={handleOpenChange} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
||||
|
||||
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
||||
|
||||
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
||||
|
||||
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
||||
|
||||
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
||||
|
||||
const contextMenuItemVariants = cva(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-3 py-1.5 text-sm text-foreground/85 outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-3.5 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"focus:bg-accent focus:text-accent-foreground [&_svg]:text-muted-foreground",
|
||||
destructive:
|
||||
"text-destructive focus:bg-destructive/10 focus:text-destructive [&_svg]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const ContextMenuSubTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean;
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ className, inset, children, variant = "default", icon, ...props },
|
||||
ref,
|
||||
) => (
|
||||
<ContextMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
"data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
<HugeiconsIcon
|
||||
icon={ArrowRightIcon}
|
||||
className="ml-auto text-muted-foreground/80"
|
||||
/>
|
||||
</ContextMenuPrimitive.SubTrigger>
|
||||
),
|
||||
);
|
||||
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
||||
|
||||
const ContextMenuSubContent = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 min-w-48 overflow-hidden rounded-md border shadow-xl p-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
||||
|
||||
const ContextMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content> & {
|
||||
container?: HTMLElement | null;
|
||||
}
|
||||
>(({ className, container, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Portal container={container ?? undefined}>
|
||||
<ContextMenuPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 min-w-48 overflow-hidden rounded-md border shadow-xl p-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</ContextMenuPrimitive.Portal>
|
||||
));
|
||||
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
||||
|
||||
const ContextMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
|
||||
inset?: boolean;
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
textRight?: string;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
inset,
|
||||
variant = "default",
|
||||
icon,
|
||||
children,
|
||||
textRight,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const shouldInsetContent = inset || Boolean(icon);
|
||||
|
||||
return (
|
||||
<ContextMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
shouldInsetContent && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="absolute left-3 flex size-3.5 items-center justify-center text-muted-foreground [&_svg]:size-3.5 [&_svg]:shrink-0">
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
{textRight && (
|
||||
<span className="ml-auto text-[0.60rem] tracking-widest text-muted-foreground/80 mb-0.5">
|
||||
{textRight}
|
||||
</span>
|
||||
)}
|
||||
</ContextMenuPrimitive.Item>
|
||||
);
|
||||
},
|
||||
);
|
||||
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
||||
|
||||
const ContextMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem> & {
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ className, children, checked, variant = "default", icon, ...props },
|
||||
ref,
|
||||
) => (
|
||||
<ContextMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
contextMenuItemVariants({ variant }),
|
||||
"pr-2 pl-8",
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-3 flex size-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.ItemIndicator>
|
||||
<HugeiconsIcon icon={Tick02Icon} className="size-4" />
|
||||
</ContextMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.CheckboxItem>
|
||||
),
|
||||
);
|
||||
ContextMenuCheckboxItem.displayName =
|
||||
ContextMenuPrimitive.CheckboxItem.displayName;
|
||||
|
||||
const ContextMenuRadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem> & {
|
||||
variant?: VariantProps<typeof contextMenuItemVariants>["variant"];
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, children, variant = "default", icon, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(contextMenuItemVariants({ variant }), "pr-2 pl-8", className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.ItemIndicator>
|
||||
<HugeiconsIcon icon={CircleIcon} className="size-2 fill-current" />
|
||||
</ContextMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.RadioItem>
|
||||
));
|
||||
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
||||
|
||||
const ContextMenuLabel = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
||||
inset?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, inset, icon, children, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-1.5 text-sm font-semibold text-foreground",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{icon && (
|
||||
<span className="size-4 shrink-0 text-muted-foreground">{icon}</span>
|
||||
)}
|
||||
{children}
|
||||
</ContextMenuPrimitive.Label>
|
||||
));
|
||||
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
||||
|
||||
const ContextMenuSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<ContextMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("bg-border mx-1 my-1.5 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
||||
|
||||
const ContextMenuShortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground opacity-60",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
||||
|
||||
export {
|
||||
ContextMenu,
|
||||
ContextMenuTrigger,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuCheckboxItem,
|
||||
ContextMenuRadioItem,
|
||||
ContextMenuLabel,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuShortcut,
|
||||
ContextMenuGroup,
|
||||
ContextMenuPortal,
|
||||
ContextMenuSub,
|
||||
ContextMenuSubContent,
|
||||
ContextMenuSubTrigger,
|
||||
ContextMenuRadioGroup,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,145 +1,148 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Dialog as DialogPrimitive } from "radix-ui";
|
||||
import { X } from "lucide-react";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Dialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "dialog",
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<DialogPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-250 backdrop-blur-sm bg-black/10",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover fixed top-[50%] left-[50%] z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200",
|
||||
className,
|
||||
)}
|
||||
onCloseAutoFocus={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-6 right-6 cursor-pointer opacity-70 hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
||||
<X className="size-5 text-muted-foreground" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn("flex flex-col space-y-2 text-left border-b p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
const DialogBody = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("p-6 flex flex-col gap-4", className)} {...props} />
|
||||
);
|
||||
DialogBody.displayName = "DialogBody";
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex gap-3 flex-col-reverse sm:flex-row sm:justify-end p-6 py-5 border-t",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg leading-none font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogPortal,
|
||||
DialogOverlay,
|
||||
DialogTrigger,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogBody,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
};
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Dialog as DialogPrimitive } from "radix-ui";
|
||||
import { X } from "lucide-react";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Dialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<DialogPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-250 backdrop-blur-sm bg-black/10",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover fixed top-[50%] left-[50%] z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200",
|
||||
className,
|
||||
)}
|
||||
onCloseAutoFocus={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-6 right-6 cursor-pointer opacity-70 hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
||||
<X className="size-5 text-muted-foreground" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn("flex flex-col space-y-2 text-left border-b p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
const DialogBody = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("p-6 flex flex-col gap-4", className)} {...props} />
|
||||
);
|
||||
DialogBody.displayName = "DialogBody";
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex gap-3 flex-col-reverse sm:flex-row sm:justify-end p-6 py-5 border-t",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg leading-none font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogPortal,
|
||||
DialogOverlay,
|
||||
DialogTrigger,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogBody,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ function DropdownMenu({
|
|||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "dropdown-menu",
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
|
|
@ -105,12 +104,12 @@ const DropdownMenuContent = React.forwardRef<
|
|||
e.preventDefault();
|
||||
}}
|
||||
className={cn(
|
||||
"group/menu bg-popover text-popover-foreground z-50 min-w-32 overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
"group/menu bg-popover text-popover-foreground z-50 min-w-32 overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
));
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +1,51 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Popover as PopoverPrimitive } from "radix-ui";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Popover({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "popover",
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<PopoverPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const PopoverTrigger = PopoverPrimitive.Trigger;
|
||||
|
||||
const PopoverAnchor = PopoverPrimitive.Anchor;
|
||||
|
||||
const PopoverClose = PopoverPrimitive.Close;
|
||||
|
||||
const PopoverContent = React.forwardRef<
|
||||
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 w-72 rounded-md border p-4 shadow-[0_0_10px_rgba(0,0,0,0.15)] outline-hidden",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
));
|
||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose };
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Popover as PopoverPrimitive } from "radix-ui";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Popover({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<PopoverPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const PopoverTrigger = PopoverPrimitive.Trigger;
|
||||
|
||||
const PopoverAnchor = PopoverPrimitive.Anchor;
|
||||
|
||||
const PopoverClose = PopoverPrimitive.Close;
|
||||
|
||||
const PopoverContent = React.forwardRef<
|
||||
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 w-72 rounded-md border p-4 shadow-[0_0_10px_rgba(0,0,0,0.15)] outline-hidden",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
));
|
||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose };
|
||||
|
|
|
|||
|
|
@ -1,221 +1,224 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Select as SelectPrimitive } from "radix-ui";
|
||||
import { Check } from "lucide-react";
|
||||
import { ArrowUpIcon, ArrowDownIcon } from "@hugeicons/core-free-icons";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Select({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "select",
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<SelectPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
const SelectGroup = SelectPrimitive.Group;
|
||||
|
||||
const SelectValue = SelectPrimitive.Value;
|
||||
|
||||
const selectItemVariants = cva(
|
||||
"relative flex cursor-pointer select-none items-center gap-1.5 rounded-sm px-2 py-1 text-sm text-foreground/85 outline-hidden data-[highlighted]:bg-popover-hover data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "",
|
||||
destructive:
|
||||
"text-destructive data-[highlighted]:bg-destructive/5 data-[highlighted]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const selectTriggerVariants = cva(
|
||||
"border-border ring-offset-background placeholder:text-muted-foreground flex h-7 w-auto cursor-pointer items-center justify-between gap-1 rounded-md border px-2.5 text-sm whitespace-nowrap transition-none focus:border-primary focus:ring-0 focus:ring-primary/10 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-accent",
|
||||
outline: "bg-background hover:bg-accent/50",
|
||||
},
|
||||
size: {
|
||||
default: "",
|
||||
sm: "rounded-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const SelectTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> &
|
||||
VariantProps<typeof selectTriggerVariants> & {
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, children, icon, variant, size, ...props }, ref) => (
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(selectTriggerVariants({ variant, size }), className)}
|
||||
{...props}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{icon && (
|
||||
<span className="text-muted-foreground [&_svg]:size-3.5 shrink-0">
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<HugeiconsIcon icon={ArrowDownIcon} className="size-4" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
));
|
||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
||||
|
||||
const SelectScrollUpButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollUpButton
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<HugeiconsIcon icon={ArrowUpIcon} className="size-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
));
|
||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
||||
|
||||
const SelectScrollDownButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollDownButton
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<HugeiconsIcon icon={ArrowDownIcon} className="size-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
));
|
||||
SelectScrollDownButton.displayName =
|
||||
SelectPrimitive.ScrollDownButton.displayName;
|
||||
|
||||
const SelectContent = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
||||
<SelectPrimitive.Portal>
|
||||
<SelectPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 max-h-(--radix-select-content-available-height) min-w-32 overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className,
|
||||
)}
|
||||
position={position}
|
||||
onCloseAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
position === "popper" &&
|
||||
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Viewport>
|
||||
<SelectScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
));
|
||||
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
||||
|
||||
const SelectLabel = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"px-2 pb-1 pt-0.5 text-[11px] font-bold uppercase tracking-wider text-muted-foreground",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
||||
|
||||
const SelectItem = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> & {
|
||||
variant?: VariantProps<typeof selectItemVariants>["variant"];
|
||||
}
|
||||
>(({ className, children, variant = "default", ...props }, ref) => (
|
||||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(selectItemVariants({ variant }), "pl-6 pr-2", className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-1.5 flex size-3.5 items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<Check className="size-3.5" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||
</SelectPrimitive.Item>
|
||||
));
|
||||
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
||||
|
||||
const SelectSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("bg-border mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
||||
|
||||
export {
|
||||
Select,
|
||||
SelectGroup,
|
||||
SelectValue,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectLabel,
|
||||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectScrollUpButton,
|
||||
SelectScrollDownButton,
|
||||
};
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Select as SelectPrimitive } from "radix-ui";
|
||||
import { Check } from "lucide-react";
|
||||
import { ArrowUpIcon, ArrowDownIcon } from "@hugeicons/core-free-icons";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Select({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<SelectPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const SelectGroup = SelectPrimitive.Group;
|
||||
|
||||
const SelectValue = SelectPrimitive.Value;
|
||||
|
||||
const selectItemVariants = cva(
|
||||
"relative flex cursor-pointer select-none items-center gap-1.5 rounded-sm px-2 py-1 text-sm text-foreground/85 outline-hidden data-[highlighted]:bg-popover-hover data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "",
|
||||
destructive:
|
||||
"text-destructive data-[highlighted]:bg-destructive/5 data-[highlighted]:text-destructive",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const selectTriggerVariants = cva(
|
||||
"border-border ring-offset-background placeholder:text-muted-foreground flex h-7 w-auto cursor-pointer items-center justify-between gap-1 rounded-md border px-2.5 text-sm whitespace-nowrap transition-none focus:border-primary focus:ring-0 focus:ring-primary/10 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-accent",
|
||||
outline: "bg-background hover:bg-accent/50",
|
||||
},
|
||||
size: {
|
||||
default: "",
|
||||
sm: "rounded-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const SelectTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> &
|
||||
VariantProps<typeof selectTriggerVariants> & {
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
>(({ className, children, icon, variant, size, ...props }, ref) => (
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(selectTriggerVariants({ variant, size }), className)}
|
||||
{...props}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{icon && (
|
||||
<span className="text-muted-foreground [&_svg]:size-3.5 shrink-0">
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<HugeiconsIcon icon={ArrowDownIcon} className="size-4" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
));
|
||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
||||
|
||||
const SelectScrollUpButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollUpButton
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<HugeiconsIcon icon={ArrowUpIcon} className="size-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
));
|
||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
||||
|
||||
const SelectScrollDownButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollDownButton
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<HugeiconsIcon icon={ArrowDownIcon} className="size-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
));
|
||||
SelectScrollDownButton.displayName =
|
||||
SelectPrimitive.ScrollDownButton.displayName;
|
||||
|
||||
const SelectContent = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
||||
<SelectPrimitive.Portal>
|
||||
<SelectPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground z-50 max-h-(--radix-select-content-available-height) min-w-32 overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className,
|
||||
)}
|
||||
position={position}
|
||||
onCloseAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
position === "popper" &&
|
||||
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Viewport>
|
||||
<SelectScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
));
|
||||
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
||||
|
||||
const SelectLabel = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"px-2 pb-1 pt-0.5 text-[11px] font-bold uppercase tracking-wider text-muted-foreground",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
||||
|
||||
const SelectItem = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> & {
|
||||
variant?: VariantProps<typeof selectItemVariants>["variant"];
|
||||
}
|
||||
>(({ className, children, variant = "default", ...props }, ref) => (
|
||||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(selectItemVariants({ variant }), "pl-6 pr-2", className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-1.5 flex size-3.5 items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<Check className="size-3.5" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||
</SelectPrimitive.Item>
|
||||
));
|
||||
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
||||
|
||||
const SelectSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("bg-border mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
||||
|
||||
export {
|
||||
Select,
|
||||
SelectGroup,
|
||||
SelectValue,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectLabel,
|
||||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectScrollUpButton,
|
||||
SelectScrollDownButton,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,157 +1,160 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Dialog as SheetPrimitive } from "radix-ui";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Sheet({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
source: "sheet",
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<SheetPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
const SheetTrigger = SheetPrimitive.Trigger;
|
||||
|
||||
const SheetClose = SheetPrimitive.Close;
|
||||
|
||||
const SheetPortal = SheetPrimitive.Portal;
|
||||
|
||||
const SheetOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={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-200 bg-black/50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
));
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
"fixed z-250 gap-4 bg-background p-6 shadow-lg transition ease data-[state=closed]:duration-250 data-[state=open]:duration-250 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
||||
bottom:
|
||||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||
right:
|
||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> {}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
SheetContentProps
|
||||
>(({ side = "right", className, children, ...props }, ref) => (
|
||||
<SheetPortal>
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
||||
<X className="size-5" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
{children}
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
));
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||
|
||||
const SheetHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetHeader.displayName = "SheetHeader";
|
||||
|
||||
const SheetFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-4",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetFooter.displayName = "SheetFooter";
|
||||
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-foreground text-lg font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetPortal,
|
||||
SheetOverlay,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
};
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Dialog as SheetPrimitive } from "radix-ui";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
import { cn } from "@/utils/ui";
|
||||
import { useOverlayOpenChange } from "./use-overlay-open-change";
|
||||
|
||||
function Sheet({
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||
const handleOpenChange = useOverlayOpenChange({
|
||||
open,
|
||||
onOpenChange,
|
||||
});
|
||||
return (
|
||||
<SheetPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const SheetTrigger = SheetPrimitive.Trigger;
|
||||
|
||||
const SheetClose = SheetPrimitive.Close;
|
||||
|
||||
const SheetPortal = SheetPrimitive.Portal;
|
||||
|
||||
const SheetOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={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-200 bg-black/50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
));
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
"fixed z-250 gap-4 bg-background p-6 shadow-lg transition ease data-[state=closed]:duration-250 data-[state=open]:duration-250 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
||||
bottom:
|
||||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||
right:
|
||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> {}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
SheetContentProps
|
||||
>(({ side = "right", className, children, ...props }, ref) => (
|
||||
<SheetPortal>
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
onOpenAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
||||
<X className="size-5" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
{children}
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
));
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||
|
||||
const SheetHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetHeader.displayName = "SheetHeader";
|
||||
|
||||
const SheetFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-4",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
SheetFooter.displayName = "SheetFooter";
|
||||
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-foreground text-lg font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetPortal,
|
||||
SheetOverlay,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,78 +1,55 @@
|
|||
import { useCallback, useEffect, useId, useRef } from "react";
|
||||
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
||||
|
||||
export function useOverlayOpenChange({
|
||||
source,
|
||||
open,
|
||||
onOpenChange,
|
||||
}: {
|
||||
source: string;
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}) {
|
||||
const { openOverlay, closeOverlay } = useKeybindingsStore();
|
||||
const isTrackedRef = useRef(false);
|
||||
const isControlled = typeof open === "boolean";
|
||||
const overlayId = useId();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isControlled) return;
|
||||
|
||||
if (open && !isTrackedRef.current) {
|
||||
openOverlay(overlayId, source);
|
||||
isTrackedRef.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!open && isTrackedRef.current) {
|
||||
closeOverlay(overlayId, source);
|
||||
isTrackedRef.current = false;
|
||||
}
|
||||
}, [closeOverlay, isControlled, open, openOverlay, overlayId, source]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (!isTrackedRef.current) return;
|
||||
// #region agent log
|
||||
fetch(
|
||||
"http://127.0.0.1:7245/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Debug-Session-Id": "3997d9",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sessionId: "3997d9",
|
||||
runId: "post-fix",
|
||||
hypothesisId: "H2",
|
||||
location: "use-overlay-open-change.ts:cleanup",
|
||||
message: "Overlay closed during unmount cleanup",
|
||||
data: { source, overlayId },
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
},
|
||||
).catch(() => {});
|
||||
// #endregion
|
||||
closeOverlay(overlayId, source);
|
||||
isTrackedRef.current = false;
|
||||
};
|
||||
}, [closeOverlay, overlayId, source]);
|
||||
|
||||
return useCallback(
|
||||
(nextOpen: boolean) => {
|
||||
if (!isControlled) {
|
||||
if (nextOpen && !isTrackedRef.current) {
|
||||
openOverlay(overlayId, source);
|
||||
isTrackedRef.current = true;
|
||||
} else if (!nextOpen && isTrackedRef.current) {
|
||||
closeOverlay(overlayId, source);
|
||||
isTrackedRef.current = false;
|
||||
}
|
||||
}
|
||||
|
||||
onOpenChange?.(nextOpen);
|
||||
},
|
||||
[closeOverlay, isControlled, onOpenChange, openOverlay, overlayId, source],
|
||||
);
|
||||
}
|
||||
import { useCallback, useEffect, useId, useRef } from "react";
|
||||
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
||||
|
||||
export function useOverlayOpenChange({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: {
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}) {
|
||||
const { openOverlay, closeOverlay } = useKeybindingsStore();
|
||||
const isTrackedRef = useRef(false);
|
||||
const isControlled = typeof open === "boolean";
|
||||
const overlayId = useId();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isControlled) return;
|
||||
|
||||
if (open && !isTrackedRef.current) {
|
||||
openOverlay(overlayId);
|
||||
isTrackedRef.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!open && isTrackedRef.current) {
|
||||
closeOverlay(overlayId);
|
||||
isTrackedRef.current = false;
|
||||
}
|
||||
}, [closeOverlay, isControlled, open, openOverlay, overlayId]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (!isTrackedRef.current) return;
|
||||
closeOverlay(overlayId);
|
||||
isTrackedRef.current = false;
|
||||
};
|
||||
}, [closeOverlay, overlayId]);
|
||||
|
||||
return useCallback(
|
||||
(nextOpen: boolean) => {
|
||||
if (!isControlled) {
|
||||
if (nextOpen && !isTrackedRef.current) {
|
||||
openOverlay(overlayId);
|
||||
isTrackedRef.current = true;
|
||||
} else if (!nextOpen && isTrackedRef.current) {
|
||||
closeOverlay(overlayId);
|
||||
isTrackedRef.current = false;
|
||||
}
|
||||
}
|
||||
|
||||
onOpenChange?.(nextOpen);
|
||||
},
|
||||
[closeOverlay, isControlled, onOpenChange, openOverlay, overlayId],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -528,12 +528,10 @@ export class ProjectManager {
|
|||
}
|
||||
|
||||
async prepareExit(): Promise<void> {
|
||||
console.log("prepareExit", this.active);
|
||||
if (!this.active) return;
|
||||
|
||||
try {
|
||||
const didUpdateThumbnail = await this.updateThumbnailFromTimeline();
|
||||
console.log("didUpdateThumbnail", didUpdateThumbnail);
|
||||
if (didUpdateThumbnail) {
|
||||
await this.editor.save.flush();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,68 +21,10 @@ export function useKeybindingsListener() {
|
|||
|
||||
useEffect(() => {
|
||||
const eventOptions: AddEventListenerOptions = { capture: true };
|
||||
// #region agent log
|
||||
fetch("http://127.0.0.1:7245/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Debug-Session-Id": "3997d9",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sessionId: "3997d9",
|
||||
runId: "initial",
|
||||
hypothesisId: "H1",
|
||||
location: "use-keybindings.ts:effect",
|
||||
message: "Keybindings listener mounted",
|
||||
data: {
|
||||
overlayDepth,
|
||||
isLoadingProject,
|
||||
isRecording,
|
||||
keybindingCount: Object.keys(keybindings).length,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
}).catch(() => {});
|
||||
// #endregion
|
||||
const handleKeyDown = (ev: KeyboardEvent) => {
|
||||
const normalizedKey = (ev.key ?? "").toLowerCase();
|
||||
const shouldLogKey =
|
||||
ev.code === "Space" ||
|
||||
ev.code.startsWith("Key") ||
|
||||
["escape", "delete", "backspace", "enter"].includes(normalizedKey);
|
||||
|
||||
if (overlayDepth > 0 || isLoadingProject || isRecording) {
|
||||
if (shouldLogKey) {
|
||||
// #region agent log
|
||||
fetch(
|
||||
"http://127.0.0.1:7245/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Debug-Session-Id": "3997d9",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sessionId: "3997d9",
|
||||
runId: "initial",
|
||||
hypothesisId: "H2",
|
||||
location: "use-keybindings.ts:blocked",
|
||||
message: "Shortcut blocked by runtime gate",
|
||||
data: {
|
||||
key: ev.key,
|
||||
code: ev.code,
|
||||
overlayDepth,
|
||||
isLoadingProject,
|
||||
isRecording,
|
||||
targetTag:
|
||||
ev.target instanceof HTMLElement ? ev.target.tagName : null,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
},
|
||||
).catch(() => {});
|
||||
// #endregion
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -93,43 +35,6 @@ export function useKeybindingsListener() {
|
|||
isTypableDOMElement({ element: activeElement });
|
||||
const boundAction = binding ? keybindings[binding] : undefined;
|
||||
|
||||
if (shouldLogKey || binding || boundAction) {
|
||||
// #region agent log
|
||||
fetch(
|
||||
"http://127.0.0.1:7245/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Debug-Session-Id": "3997d9",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sessionId: "3997d9",
|
||||
runId: "initial",
|
||||
hypothesisId: !binding ? "H3" : isTextInput ? "H5" : "H4",
|
||||
location: "use-keybindings.ts:keydown",
|
||||
message: "Shortcut keydown observed",
|
||||
data: {
|
||||
key: ev.key,
|
||||
code: ev.code,
|
||||
binding,
|
||||
boundAction: boundAction ?? null,
|
||||
isTextInput,
|
||||
keybindingCount: Object.keys(keybindings).length,
|
||||
activeTag:
|
||||
activeElement instanceof HTMLElement
|
||||
? activeElement.tagName
|
||||
: null,
|
||||
targetTag:
|
||||
ev.target instanceof HTMLElement ? ev.target.tagName : null,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
},
|
||||
).catch(() => {});
|
||||
// #endregion
|
||||
}
|
||||
|
||||
if (normalizedKey === "escape" && isTextInput) {
|
||||
activeElement.blur();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -57,29 +57,6 @@ export const invokeAction: InvokeActionFunc = <A extends TAction>(
|
|||
args?: TArgOfAction<A>,
|
||||
trigger?: TInvocationTrigger,
|
||||
) => {
|
||||
if (trigger === "keypress") {
|
||||
// #region agent log
|
||||
fetch("http://127.0.0.1:7245/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Debug-Session-Id": "3997d9",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sessionId: "3997d9",
|
||||
runId: "initial",
|
||||
hypothesisId: "H4",
|
||||
location: "actions/registry.ts:invokeAction",
|
||||
message: "Action invoked from keypress",
|
||||
data: {
|
||||
action,
|
||||
handlerCount: boundActions[action]?.length ?? 0,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
}).catch(() => {});
|
||||
// #endregion
|
||||
}
|
||||
boundActions[action]?.forEach((handler) => {
|
||||
handler(args, trigger);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ class WasmCompositor {
|
|||
string,
|
||||
{ source: CanvasImageSource; width: number; height: number }
|
||||
>();
|
||||
private _debugLogged = false;
|
||||
|
||||
ensureInitialized({ width, height }: { width: number; height: number }) {
|
||||
if (!this.canvas) {
|
||||
|
|
@ -121,20 +120,6 @@ class WasmCompositor {
|
|||
}
|
||||
|
||||
render(frame: FrameDescriptor) {
|
||||
if (!this._debugLogged) {
|
||||
this._debugLogged = true;
|
||||
const firstLayer = frame.items.find((item) => item.type === "layer");
|
||||
console.log(
|
||||
"[compositor] first frame — canvas size:",
|
||||
JSON.stringify({ width: frame.width, height: frame.height }),
|
||||
"| first layer transform:",
|
||||
firstLayer && firstLayer.type === "layer"
|
||||
? JSON.stringify(firstLayer.transform)
|
||||
: "none",
|
||||
"| webgpu available:",
|
||||
typeof navigator !== "undefined" && "gpu" in navigator,
|
||||
);
|
||||
}
|
||||
renderFrame(frame);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,18 +13,11 @@ export function initializeGpuRenderer(): Promise<void> {
|
|||
initPromise = initializeGpu()
|
||||
.then(() => {
|
||||
gpuAvailable = true;
|
||||
// #region agent log
|
||||
fetch('http://127.0.0.1:7408/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'b140a6'},body:JSON.stringify({sessionId:'b140a6',location:'gpu-renderer.ts',message:'GPU init SUCCESS',data:{userAgent:navigator.userAgent},timestamp:Date.now()})}).catch(()=>{});
|
||||
// #endregion
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
gpuAvailable = false;
|
||||
const message =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.warn(`GPU renderer unavailable: ${message}`);
|
||||
// #region agent log
|
||||
fetch('http://127.0.0.1:7408/ingest/669b22f8-172b-4e65-aa3f-1c702ede83f7',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'b140a6'},body:JSON.stringify({sessionId:'b140a6',location:'gpu-renderer.ts',message:'GPU init FAILED',data:{error:message,userAgent:navigator.userAgent,hasGpu:!!navigator.gpu},timestamp:Date.now()})}).catch(()=>{});
|
||||
// #endregion
|
||||
});
|
||||
}
|
||||
return initPromise;
|
||||
|
|
|
|||
Loading…
Reference in New Issue