Aymeric Rabot 6c99851006 Refactor asset types and improve UI primitives
Replaces usage of the Asset type with AssetInput across editor components and hooks for consistency with core types. Adds default dimensions fallback for asset placement logic. Refactors UI primitives (button, sidebar, opacity control) to support forwarding refs and asChild prop, and updates imports for primitives. Updates Radix UI dependencies in package.json and bun.lock.
2026-01-30 22:01:25 -05:00

80 lines
2.5 KiB
TypeScript

'use client'
import { Eye, EyeOff } from 'lucide-react'
import { useState } from 'react'
import { Button } from '@/components/ui/primitives/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/primitives/popover'
import { Slider } from '@/components/ui/primitives/slider'
import { cn } from '@/lib/utils'
interface OpacityControlProps {
visible?: boolean
opacity?: number
onVisibilityToggle: () => void
onOpacityChange: (opacity: number) => void
className?: string
}
export function OpacityControl({
visible = true,
opacity = 100,
onVisibilityToggle,
onOpacityChange,
className,
}: OpacityControlProps) {
const [isOpen, setIsOpen] = useState(false)
const actualOpacity = opacity ?? 100
const isHidden = visible === false || actualOpacity === 0
return (
<Popover onOpenChange={setIsOpen} open={isOpen}>
<div className={cn('flex items-center gap-1', className)}>
{!isHidden && actualOpacity < 100 && (
<span className="text-muted-foreground text-xs">{actualOpacity}%</span>
)}
<PopoverTrigger asChild>
<Button
className={cn(
'h-5 w-5 p-0 transition-opacity',
isHidden ? 'opacity-100' : 'opacity-0 group-hover/item:opacity-100',
)}
onClick={(e) => {
e.stopPropagation()
// If clicking the button (not opening popover), toggle visibility
if (!isOpen) {
onVisibilityToggle()
}
}}
size="sm"
variant="ghost"
>
{isHidden ? <EyeOff className="h-3 w-3" /> : <Eye className="h-3 w-3" />}
</Button>
</PopoverTrigger>
<PopoverContent
align="end"
className="w-48 p-3"
onClick={(e) => e.stopPropagation()}
side="right"
>
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="font-medium text-sm">Opacity</span>
<span className="text-muted-foreground text-xs">{actualOpacity}%</span>
</div>
<Slider
max={100}
min={0}
onValueChange={(values: number[]) => {
if (values[0] !== undefined) onOpacityChange(values[0])
}}
step={1}
value={[actualOpacity]}
/>
</div>
</PopoverContent>
</div>
</Popover>
)
}