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.
80 lines
2.5 KiB
TypeScript
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>
|
|
)
|
|
}
|