summaryrefslogtreecommitdiff
path: root/apps/web/src/components/ui
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/ui')
-rw-r--r--apps/web/src/components/ui/accordion.tsx2
-rw-r--r--apps/web/src/components/ui/alert-dialog.tsx2
-rw-r--r--apps/web/src/components/ui/aspect-ratio.tsx2
-rw-r--r--apps/web/src/components/ui/avatar.tsx2
-rw-r--r--apps/web/src/components/ui/breadcrumb.tsx4
-rw-r--r--apps/web/src/components/ui/button.tsx4
-rw-r--r--apps/web/src/components/ui/checkbox.tsx2
-rw-r--r--apps/web/src/components/ui/collapsible.tsx2
-rw-r--r--apps/web/src/components/ui/command.tsx2
-rw-r--r--apps/web/src/components/ui/context-menu.tsx2
-rw-r--r--apps/web/src/components/ui/dialog.tsx2
-rw-r--r--apps/web/src/components/ui/dropdown-menu.tsx2
-rw-r--r--apps/web/src/components/ui/form.tsx10
-rw-r--r--apps/web/src/components/ui/hover-card.tsx2
-rw-r--r--apps/web/src/components/ui/input.tsx2
-rw-r--r--apps/web/src/components/ui/label.tsx2
-rw-r--r--apps/web/src/components/ui/menubar.tsx2
-rw-r--r--apps/web/src/components/ui/navigation-menu.tsx2
-rw-r--r--apps/web/src/components/ui/popover.tsx2
-rw-r--r--apps/web/src/components/ui/progress.tsx2
-rw-r--r--apps/web/src/components/ui/radio-group.tsx2
-rw-r--r--apps/web/src/components/ui/scroll-area.tsx2
-rw-r--r--apps/web/src/components/ui/select.tsx2
-rw-r--r--apps/web/src/components/ui/separator.tsx2
-rw-r--r--apps/web/src/components/ui/sheet.tsx2
-rw-r--r--apps/web/src/components/ui/sidebar.tsx12
-rw-r--r--apps/web/src/components/ui/slider.tsx2
-rw-r--r--apps/web/src/components/ui/switch.tsx2
-rw-r--r--apps/web/src/components/ui/tabs.tsx2
-rw-r--r--apps/web/src/components/ui/toast.tsx2
-rw-r--r--apps/web/src/components/ui/toggle-group.tsx2
-rw-r--r--apps/web/src/components/ui/toggle.tsx2
-rw-r--r--apps/web/src/components/ui/tooltip.tsx2
-rw-r--r--apps/web/src/components/ui/video-player.tsx121
34 files changed, 165 insertions, 44 deletions
diff --git a/apps/web/src/components/ui/accordion.tsx b/apps/web/src/components/ui/accordion.tsx
index 2fe12b37..68edd869 100644
--- a/apps/web/src/components/ui/accordion.tsx
+++ b/apps/web/src/components/ui/accordion.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as AccordionPrimitive from "@radix-ui/react-accordion";
+import { Accordion as AccordionPrimitive } from "radix-ui";
import { ChevronDown } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/alert-dialog.tsx b/apps/web/src/components/ui/alert-dialog.tsx
index ea8ab4f1..2cce235c 100644
--- a/apps/web/src/components/ui/alert-dialog.tsx
+++ b/apps/web/src/components/ui/alert-dialog.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
+import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
import { buttonVariants } from "./button";
diff --git a/apps/web/src/components/ui/aspect-ratio.tsx b/apps/web/src/components/ui/aspect-ratio.tsx
index d6a5226f..6f90bbb8 100644
--- a/apps/web/src/components/ui/aspect-ratio.tsx
+++ b/apps/web/src/components/ui/aspect-ratio.tsx
@@ -1,6 +1,6 @@
"use client"
-import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
+import { AspectRatio as AspectRatioPrimitive } from "radix-ui"
const AspectRatio = AspectRatioPrimitive.Root
diff --git a/apps/web/src/components/ui/avatar.tsx b/apps/web/src/components/ui/avatar.tsx
index 4c6f6a4b..7979c415 100644
--- a/apps/web/src/components/ui/avatar.tsx
+++ b/apps/web/src/components/ui/avatar.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as AvatarPrimitive from "@radix-ui/react-avatar";
+import { Avatar as AvatarPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/breadcrumb.tsx b/apps/web/src/components/ui/breadcrumb.tsx
index 987b14df..d9df9bf5 100644
--- a/apps/web/src/components/ui/breadcrumb.tsx
+++ b/apps/web/src/components/ui/breadcrumb.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
+import { Slot as SlotPrimitive } from "radix-ui";
import { ChevronRight, MoreHorizontal } from "lucide-react";
import { cn } from "../../lib/utils";
@@ -45,7 +45,7 @@ const BreadcrumbLink = React.forwardRef<
asChild?: boolean;
}
>(({ asChild, className, ...props }, ref) => {
- const Comp = asChild ? Slot : "a";
+ const Comp = asChild ? SlotPrimitive.Slot : "a";
return (
<Comp
diff --git a/apps/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx
index 67b4eca1..f5863e20 100644
--- a/apps/web/src/components/ui/button.tsx
+++ b/apps/web/src/components/ui/button.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
+import { Slot as SlotPrimitive } from "radix-ui";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
@@ -42,7 +42,7 @@ export interface ButtonProps
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button";
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
diff --git a/apps/web/src/components/ui/checkbox.tsx b/apps/web/src/components/ui/checkbox.tsx
index bedc253e..2b74bc52 100644
--- a/apps/web/src/components/ui/checkbox.tsx
+++ b/apps/web/src/components/ui/checkbox.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
+import { Checkbox as CheckboxPrimitive } from "radix-ui";
import { Check } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/collapsible.tsx b/apps/web/src/components/ui/collapsible.tsx
index 9fa48946..6642d604 100644
--- a/apps/web/src/components/ui/collapsible.tsx
+++ b/apps/web/src/components/ui/collapsible.tsx
@@ -1,6 +1,6 @@
"use client"
-import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
+import { Collapsible as CollapsiblePrimitive } from "radix-ui"
const Collapsible = CollapsiblePrimitive.Root
diff --git a/apps/web/src/components/ui/command.tsx b/apps/web/src/components/ui/command.tsx
index 58ba329e..29f29cf2 100644
--- a/apps/web/src/components/ui/command.tsx
+++ b/apps/web/src/components/ui/command.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import { type DialogProps } from "@radix-ui/react-dialog";
+import { type DialogProps } from "radix-ui";
import { Command as CommandPrimitive } from "cmdk";
import { Search } from "lucide-react";
diff --git a/apps/web/src/components/ui/context-menu.tsx b/apps/web/src/components/ui/context-menu.tsx
index 4cc152f6..defa0755 100644
--- a/apps/web/src/components/ui/context-menu.tsx
+++ b/apps/web/src/components/ui/context-menu.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
+import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
import { Check, ChevronRight, Circle } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/dialog.tsx b/apps/web/src/components/ui/dialog.tsx
index 985f5603..0a487d0a 100644
--- a/apps/web/src/components/ui/dialog.tsx
+++ b/apps/web/src/components/ui/dialog.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { Dialog as DialogPrimitive } from "radix-ui";
import { X } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/dropdown-menu.tsx b/apps/web/src/components/ui/dropdown-menu.tsx
index 74839c7c..2b653e3b 100644
--- a/apps/web/src/components/ui/dropdown-menu.tsx
+++ b/apps/web/src/components/ui/dropdown-menu.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
+import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
import { Check, ChevronRight, Circle } from "lucide-react";
import { cva, type VariantProps } from "class-variance-authority";
diff --git a/apps/web/src/components/ui/form.tsx b/apps/web/src/components/ui/form.tsx
index d8328f55..cb4f53a9 100644
--- a/apps/web/src/components/ui/form.tsx
+++ b/apps/web/src/components/ui/form.tsx
@@ -1,8 +1,8 @@
"use client";
import * as React from "react";
-import * as LabelPrimitive from "@radix-ui/react-label";
-import { Slot } from "@radix-ui/react-slot";
+import { Label as LabelPrimitive, Slot as SlotPrimitive } from "radix-ui";
+
import {
Controller,
ControllerProps,
@@ -104,14 +104,14 @@ const FormLabel = React.forwardRef<
FormLabel.displayName = "FormLabel";
const FormControl = React.forwardRef<
- React.ElementRef<typeof Slot>,
- React.ComponentPropsWithoutRef<typeof Slot>
+ React.ElementRef<typeof SlotPrimitive.Slot>,
+ React.ComponentPropsWithoutRef<typeof SlotPrimitive.Slot>
>(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } =
useFormField();
return (
- <Slot
+ <SlotPrimitive.Slot
ref={ref}
id={formItemId}
aria-describedby={
diff --git a/apps/web/src/components/ui/hover-card.tsx b/apps/web/src/components/ui/hover-card.tsx
index d5a01936..c3958fcf 100644
--- a/apps/web/src/components/ui/hover-card.tsx
+++ b/apps/web/src/components/ui/hover-card.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
+import { HoverCard as HoverCardPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/input.tsx b/apps/web/src/components/ui/input.tsx
index c458e036..42f4c452 100644
--- a/apps/web/src/components/ui/input.tsx
+++ b/apps/web/src/components/ui/input.tsx
@@ -16,7 +16,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
type,
showPassword,
onShowPasswordChange,
- value = "",
+ value,
...props
},
ref
diff --git a/apps/web/src/components/ui/label.tsx b/apps/web/src/components/ui/label.tsx
index fdcf3ffa..877af15b 100644
--- a/apps/web/src/components/ui/label.tsx
+++ b/apps/web/src/components/ui/label.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as LabelPrimitive from "@radix-ui/react-label";
+import { Label as LabelPrimitive } from "radix-ui";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/menubar.tsx b/apps/web/src/components/ui/menubar.tsx
index a2fdb934..642ffa2b 100644
--- a/apps/web/src/components/ui/menubar.tsx
+++ b/apps/web/src/components/ui/menubar.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as MenubarPrimitive from "@radix-ui/react-menubar";
+import { Menubar as MenubarPrimitive } from "radix-ui";
import { Check, ChevronRight, Circle } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/navigation-menu.tsx b/apps/web/src/components/ui/navigation-menu.tsx
index 5e3ed067..b5dd3622 100644
--- a/apps/web/src/components/ui/navigation-menu.tsx
+++ b/apps/web/src/components/ui/navigation-menu.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
+import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui";
import { cva } from "class-variance-authority";
import { ChevronDown } from "lucide-react";
diff --git a/apps/web/src/components/ui/popover.tsx b/apps/web/src/components/ui/popover.tsx
index a8c94079..cc4f6508 100644
--- a/apps/web/src/components/ui/popover.tsx
+++ b/apps/web/src/components/ui/popover.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as PopoverPrimitive from "@radix-ui/react-popover";
+import { Popover as PopoverPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/progress.tsx b/apps/web/src/components/ui/progress.tsx
index 887c1747..283ba17a 100644
--- a/apps/web/src/components/ui/progress.tsx
+++ b/apps/web/src/components/ui/progress.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as ProgressPrimitive from "@radix-ui/react-progress";
+import { Progress as ProgressPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/radio-group.tsx b/apps/web/src/components/ui/radio-group.tsx
index b43405c6..cc07d34f 100644
--- a/apps/web/src/components/ui/radio-group.tsx
+++ b/apps/web/src/components/ui/radio-group.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
+import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
import { Circle } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/scroll-area.tsx b/apps/web/src/components/ui/scroll-area.tsx
index b5b1b41b..6b7c3c53 100644
--- a/apps/web/src/components/ui/scroll-area.tsx
+++ b/apps/web/src/components/ui/scroll-area.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
+import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/select.tsx b/apps/web/src/components/ui/select.tsx
index c2ee4ef5..a0f5f7b2 100644
--- a/apps/web/src/components/ui/select.tsx
+++ b/apps/web/src/components/ui/select.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as SelectPrimitive from "@radix-ui/react-select";
+import { Select as SelectPrimitive } from "radix-ui";
import { Check, ChevronDown, ChevronUp } from "lucide-react";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/separator.tsx b/apps/web/src/components/ui/separator.tsx
index 8e6ad205..6138cabf 100644
--- a/apps/web/src/components/ui/separator.tsx
+++ b/apps/web/src/components/ui/separator.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as SeparatorPrimitive from "@radix-ui/react-separator";
+import { Separator as SeparatorPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/sheet.tsx b/apps/web/src/components/ui/sheet.tsx
index c0a2ed99..6aa092dc 100644
--- a/apps/web/src/components/ui/sheet.tsx
+++ b/apps/web/src/components/ui/sheet.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as SheetPrimitive from "@radix-ui/react-dialog";
+import { Dialog as SheetPrimitive } from "radix-ui";
import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-react";
diff --git a/apps/web/src/components/ui/sidebar.tsx b/apps/web/src/components/ui/sidebar.tsx
index 53902fbe..e69d8751 100644
--- a/apps/web/src/components/ui/sidebar.tsx
+++ b/apps/web/src/components/ui/sidebar.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import { Slot } from "@radix-ui/react-slot";
+import { Slot as SlotPrimitive } from "radix-ui";
import { VariantProps, cva } from "class-variance-authority";
import { PanelLeft } from "lucide-react";
@@ -432,7 +432,7 @@ const SidebarGroupLabel = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & { asChild?: boolean }
>(({ className, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "div";
+ const Comp = asChild ? SlotPrimitive.Slot : "div";
return (
<Comp
@@ -453,7 +453,7 @@ const SidebarGroupAction = React.forwardRef<
HTMLButtonElement,
React.ComponentProps<"button"> & { asChild?: boolean }
>(({ className, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button";
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
return (
<Comp
@@ -553,7 +553,7 @@ const SidebarMenuButton = React.forwardRef<
},
ref
) => {
- const Comp = asChild ? Slot : "button";
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
const { isMobile, state } = useSidebar();
const button = (
@@ -599,7 +599,7 @@ const SidebarMenuAction = React.forwardRef<
showOnHover?: boolean;
}
>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button";
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
return (
<Comp
@@ -713,7 +713,7 @@ const SidebarMenuSubButton = React.forwardRef<
isActive?: boolean;
}
>(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
- const Comp = asChild ? Slot : "a";
+ const Comp = asChild ? SlotPrimitive.Slot : "a";
return (
<Comp
diff --git a/apps/web/src/components/ui/slider.tsx b/apps/web/src/components/ui/slider.tsx
index 2181bf0c..4789ae17 100644
--- a/apps/web/src/components/ui/slider.tsx
+++ b/apps/web/src/components/ui/slider.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as SliderPrimitive from "@radix-ui/react-slider";
+import { Slider as SliderPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/switch.tsx b/apps/web/src/components/ui/switch.tsx
index 8e5be044..ba324f1d 100644
--- a/apps/web/src/components/ui/switch.tsx
+++ b/apps/web/src/components/ui/switch.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as SwitchPrimitives from "@radix-ui/react-switch";
+import { Switch as SwitchPrimitives } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/tabs.tsx b/apps/web/src/components/ui/tabs.tsx
index d60091cb..a51a28a2 100644
--- a/apps/web/src/components/ui/tabs.tsx
+++ b/apps/web/src/components/ui/tabs.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as TabsPrimitive from "@radix-ui/react-tabs";
+import { Tabs as TabsPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/toast.tsx b/apps/web/src/components/ui/toast.tsx
index ed8adcb7..bf89e350 100644
--- a/apps/web/src/components/ui/toast.tsx
+++ b/apps/web/src/components/ui/toast.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as ToastPrimitives from "@radix-ui/react-toast";
+import { Toast as ToastPrimitives } from "radix-ui";
import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-react";
diff --git a/apps/web/src/components/ui/toggle-group.tsx b/apps/web/src/components/ui/toggle-group.tsx
index 692a80ba..5842a07d 100644
--- a/apps/web/src/components/ui/toggle-group.tsx
+++ b/apps/web/src/components/ui/toggle-group.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
+import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
import { type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/toggle.tsx b/apps/web/src/components/ui/toggle.tsx
index 7d75e8ea..a4bfda42 100644
--- a/apps/web/src/components/ui/toggle.tsx
+++ b/apps/web/src/components/ui/toggle.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as TogglePrimitive from "@radix-ui/react-toggle";
+import { Toggle as TogglePrimitive } from "radix-ui";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/tooltip.tsx b/apps/web/src/components/ui/tooltip.tsx
index d3940b50..a2fb0a01 100644
--- a/apps/web/src/components/ui/tooltip.tsx
+++ b/apps/web/src/components/ui/tooltip.tsx
@@ -1,7 +1,7 @@
"use client";
import * as React from "react";
-import * as TooltipPrimitive from "@radix-ui/react-tooltip";
+import { Tooltip as TooltipPrimitive } from "radix-ui";
import { cn } from "../../lib/utils";
diff --git a/apps/web/src/components/ui/video-player.tsx b/apps/web/src/components/ui/video-player.tsx
new file mode 100644
index 00000000..d31f7113
--- /dev/null
+++ b/apps/web/src/components/ui/video-player.tsx
@@ -0,0 +1,121 @@
+"use client";
+
+import { useRef, useEffect } from "react";
+import { Button } from "./button";
+import { Play, Pause, Volume2 } from "lucide-react";
+import { usePlaybackStore } from "@/stores/playback-store";
+
+interface VideoPlayerProps {
+ src: string;
+ poster?: string;
+ className?: string;
+ startTime?: number;
+}
+
+export function VideoPlayer({ src, poster, className = "", startTime = 0 }: VideoPlayerProps) {
+ const videoRef = useRef<HTMLVideoElement>(null);
+ const { isPlaying, currentTime, volume, play, pause, setVolume, setDuration, setCurrentTime } = usePlaybackStore();
+
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
+
+ const handleTimeUpdate = () => {
+ setCurrentTime(video.currentTime);
+ };
+
+ const handleLoadedMetadata = () => {
+ setDuration(video.duration);
+ if (startTime > 0) {
+ video.currentTime = startTime;
+ }
+ };
+
+ const handleSeekEvent = (e: CustomEvent) => {
+ video.currentTime = e.detail.time;
+ };
+
+ video.addEventListener("timeupdate", handleTimeUpdate);
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
+ window.addEventListener("playback-seek", handleSeekEvent as EventListener);
+
+ return () => {
+ video.removeEventListener("timeupdate", handleTimeUpdate);
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
+ window.removeEventListener("playback-seek", handleSeekEvent as EventListener);
+ };
+ }, [setCurrentTime, setDuration]);
+
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
+
+ if (isPlaying) {
+ video.play().catch(console.error);
+ } else {
+ video.pause();
+ }
+ }, [isPlaying]);
+
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
+ video.volume = volume;
+ }, [volume]);
+
+ const handleSeek = (e: React.MouseEvent<HTMLVideoElement>) => {
+ const video = videoRef.current;
+ if (!video) return;
+
+ const rect = video.getBoundingClientRect();
+ const x = e.clientX - rect.left;
+ const percentage = x / rect.width;
+ const newTime = percentage * video.duration;
+
+ video.currentTime = newTime;
+ setCurrentTime(newTime);
+ };
+
+ return (
+ <div className={`relative group ${className}`}>
+ <video
+ ref={videoRef}
+ src={src}
+ poster={poster}
+ className="w-full h-full object-cover cursor-pointer"
+ onClick={handleSeek}
+ playsInline
+ preload="metadata"
+ />
+
+ <div className="absolute inset-0 bg-black/20 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" />
+
+ <div className="absolute bottom-2 left-2 right-2 flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
+ <Button
+ variant="ghost"
+ size="icon"
+ className="h-8 w-8 bg-black/50 text-white hover:bg-black/70"
+ onClick={isPlaying ? pause : play}
+ >
+ {isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
+ </Button>
+
+ <div className="flex-1 h-1 bg-white/30 rounded-full overflow-hidden">
+ <div
+ className="h-full bg-white transition-all duration-100"
+ style={{ width: `${(currentTime / usePlaybackStore.getState().duration) * 100}%` }}
+ />
+ </div>
+
+ <Button
+ variant="ghost"
+ size="icon"
+ className="h-8 w-8 bg-black/50 text-white hover:bg-black/70"
+ onClick={() => setVolume(volume > 0 ? 0 : 1)}
+ >
+ <Volume2 className="h-4 w-4" />
+ </Button>
+ </div>
+ </div>
+ );
+} \ No newline at end of file