gradients, colorpicker tabs
This commit is contained in:
Generated
+111
@@ -12,6 +12,7 @@
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-switch": "^1.2.6",
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"@uiw/react-color-colorful": "^2.9.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.545.0",
|
||||
@@ -309,6 +310,16 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
||||
@@ -2600,6 +2611,106 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/color-convert": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.9.0.tgz",
|
||||
"integrity": "sha512-tFm6iac8iN3VL9IIAXKAVpBX6ZQH7ucCvb+EgZNM5y8prRWlk53cERnP4RycE3wnYb/HUKW0lrngoygQnEWAHg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-alpha": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-alpha/-/react-color-alpha-2.9.0.tgz",
|
||||
"integrity": "sha512-tP9zs2KUPzIGvdtTBTNlDEdwHWcNJ3Ju/nnpPTsKERRJF2vzucb3v18JzihX0ACiOXU9+JVqgpAVgvoZXMeITA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.9.0",
|
||||
"@uiw/react-drag-event-interactive": "2.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-colorful": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-colorful/-/react-color-colorful-2.9.0.tgz",
|
||||
"integrity": "sha512-qw7zhgX9J4aydK0hKKLroXMYp0tw3ASNuZM1fQNwXXIpOkEW4zO+PHTkzUBpbII68wGS8tAxsZessTWNpAVi0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.9.0",
|
||||
"@uiw/react-color-alpha": "2.9.0",
|
||||
"@uiw/react-color-hue": "2.9.0",
|
||||
"@uiw/react-color-saturation": "2.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-hue": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-hue/-/react-color-hue-2.9.0.tgz",
|
||||
"integrity": "sha512-2Ix027ref3ppiVq+OQkbyKr6O8fLTH+n0wEW4xhHfa3kV8mBa2bEu8jAjrkSwO6uElaE6OJcuqYe2llyKRlIFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.9.0",
|
||||
"@uiw/react-color-alpha": "2.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-saturation": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-saturation/-/react-color-saturation-2.9.0.tgz",
|
||||
"integrity": "sha512-tBARqsW0ap+gwByGKSid1nYaGJd6dw2MTMwCABF9rebPQHtYbN/YgBjl9dNnp6XDGd+VBhH4RbpM38WV7J1F4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.9.0",
|
||||
"@uiw/react-drag-event-interactive": "2.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-drag-event-interactive": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-2.9.0.tgz",
|
||||
"integrity": "sha512-oBqrClsSuYA3IjkSHp4uHOBLgPkR98KeKeheqCRltF8w/a1CPaFCl43pyKyxwXaTV6qM6cb3VkT3JRCHMNqTzA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/structured-clone": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-switch": "^1.2.6",
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"@uiw/react-color-colorful": "^2.9.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.545.0",
|
||||
|
||||
@@ -1,50 +1,100 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { useState } from "react";
|
||||
import Colorful from '@uiw/react-color-colorful';
|
||||
import { hsvaToHex } from '@uiw/color-convert';
|
||||
|
||||
const WALLPAPER_COUNT = 12;
|
||||
const WALLPAPER_PATHS = Array.from({ length: WALLPAPER_COUNT }, (_, i) => `/wallpapers/wallpaper${i + 1}.jpg`);
|
||||
const GRADIENTS = [
|
||||
"linear-gradient( 111.6deg, rgba(114,167,232,1) 9.4%, rgba(253,129,82,1) 43.9%, rgba(253,129,82,1) 54.8%, rgba(249,202,86,1) 86.3% )",
|
||||
"linear-gradient(120deg, #d4fc79 0%, #96e6a1 100%)",
|
||||
"radial-gradient( circle farthest-corner at 3.2% 49.6%, rgba(80,12,139,0.87) 0%, rgba(161,10,144,0.72) 83.6% )",
|
||||
"linear-gradient( 111.6deg, rgba(0,56,68,1) 0%, rgba(163,217,185,1) 51.5%, rgba(231, 148, 6, 1) 88.6% )",
|
||||
"linear-gradient( 107.7deg, rgba(235,230,44,0.55) 8.4%, rgba(252,152,15,1) 90.3% )",
|
||||
"linear-gradient( 91deg, rgba(72,154,78,1) 5.2%, rgba(251,206,70,1) 95.9% )",
|
||||
"radial-gradient( circle farthest-corner at 10% 20%, rgba(2,37,78,1) 0%, rgba(4,56,126,1) 19.7%, rgba(85,245,221,1) 100.2% )",
|
||||
"linear-gradient( 109.6deg, rgba(15,2,2,1) 11.2%, rgba(36,163,190,1) 91.1% )",
|
||||
"linear-gradient(135deg, #FBC8B4, #2447B1)",
|
||||
"linear-gradient(109.6deg, #F635A6, #36D860)",
|
||||
"linear-gradient(90deg, #FF0101, #4DFF01)",
|
||||
"linear-gradient(315deg, #EC0101, #5044A9)",
|
||||
];
|
||||
|
||||
interface SettingsPanelProps {
|
||||
selected: string;
|
||||
onWallpaperChange: (path: string) => void;
|
||||
shadowEnabled: boolean;
|
||||
onShadowChange: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
export default function SettingsPanel({ selected, onWallpaperChange, shadowEnabled, onShadowChange }: SettingsPanelProps) {
|
||||
export default function SettingsPanel({ selected, onWallpaperChange }: SettingsPanelProps) {
|
||||
const [hsva, setHsva] = useState({ h: 0, s: 0, v: 68, a: 1 });
|
||||
const [gradient, setGradient] = useState<string>(GRADIENTS[0]);
|
||||
|
||||
return (
|
||||
<div className="flex-[3] min-w-0 bg-card border border-border rounded-xl p-8 flex flex-col shadow-sm">
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Switch checked={shadowEnabled} onCheckedChange={onShadowChange} />
|
||||
<Switch/>
|
||||
<div className="text-sm">Shadow</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-6">
|
||||
<div className="text-lg mb-2">Choose Background</div>
|
||||
<div className="grid grid-cols-6 gap-3">
|
||||
{WALLPAPER_PATHS.map((path, idx) => (
|
||||
<div
|
||||
key={path}
|
||||
className={cn(
|
||||
"aspect-square rounded-lg border-2 overflow-hidden cursor-pointer transition-all w-16 h-16",
|
||||
selected === path
|
||||
? "border-primary/40 ring-1 ring-primary/40 scale-105"
|
||||
: "border-border hover:border-primary/60 hover:scale-105"
|
||||
)}
|
||||
style={{ backgroundImage: `url(${path})`, backgroundSize: "cover", backgroundPosition: "center" }}
|
||||
aria-label={`Wallpaper ${idx + 1}`}
|
||||
tabIndex={0}
|
||||
onClick={() => onWallpaperChange(path)}
|
||||
onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') onWallpaperChange(path); }}
|
||||
role="button"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 w-full flex items-center justify-center text-muted-foreground text-base">
|
||||
Settings
|
||||
</div>
|
||||
<Tabs defaultValue="image" className="mb-6">
|
||||
<TabsList className="mb-4">
|
||||
<TabsTrigger value="image">Image</TabsTrigger>
|
||||
<TabsTrigger value="color">Color</TabsTrigger>
|
||||
<TabsTrigger value="gradient">Gradient</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="image">
|
||||
<div className="grid grid-cols-6 gap-3">
|
||||
{WALLPAPER_PATHS.map((path, idx) => (
|
||||
<div
|
||||
key={path}
|
||||
className={cn(
|
||||
"aspect-square rounded-lg border-2 overflow-hidden cursor-pointer transition-all w-16 h-16",
|
||||
selected === path
|
||||
? "border-primary/40 ring-1 ring-primary/40 scale-105"
|
||||
: "border-border hover:border-primary/60 hover:scale-105"
|
||||
)}
|
||||
style={{ backgroundImage: `url(${path})`, backgroundSize: "cover", backgroundPosition: "center" }}
|
||||
aria-label={`Wallpaper ${idx + 1}`}
|
||||
onClick={() => onWallpaperChange(path)}
|
||||
role="button"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="color">
|
||||
<Colorful
|
||||
color={hsva}
|
||||
disableAlpha={true}
|
||||
onChange={(color) => {
|
||||
setHsva(color.hsva);
|
||||
onWallpaperChange(hsvaToHex(color.hsva));
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="gradient">
|
||||
<div className="grid grid-cols-6 gap-3">
|
||||
{GRADIENTS.map((g, idx) => (
|
||||
<div
|
||||
key={g}
|
||||
className={cn(
|
||||
"aspect-square rounded-lg border-2 overflow-hidden cursor-pointer transition-all w-16 h-16",
|
||||
gradient === g ? "border-primary ring-1 ring-primary/40 scale-105" : "border-border hover:border-primary/60 hover:scale-105"
|
||||
)}
|
||||
style={{ background: g }}
|
||||
aria-label={`Gradient ${idx + 1}`}
|
||||
onClick={() => { setGradient(g); onWallpaperChange(g); }}
|
||||
role="button"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,10 +112,15 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(({
|
||||
}
|
||||
};
|
||||
|
||||
const isImageUrl = wallpaper?.startsWith('/wallpapers/') || wallpaper?.startsWith('http');
|
||||
const backgroundStyle = isImageUrl
|
||||
? { backgroundImage: `url(${wallpaper || '/wallpapers/wallpaper1.jpg'})` }
|
||||
: { background: wallpaper || '/wallpapers/wallpaper1.jpg' };
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full aspect-video rounded-sm p-12 flex items-center justify-center overflow-hidden bg-cover bg-center"
|
||||
style={{ backgroundImage: `url(${wallpaper || '/wallpapers/wallpaper1.jpg'})` }}
|
||||
style={backgroundStyle}
|
||||
>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
|
||||
Reference in New Issue
Block a user