rnd panel fixed for mobile devices
This commit is contained in:
parent
9707f31094
commit
5b3d96c7eb
7 changed files with 233 additions and 168 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
import { useEffect, useCallback, useContext } from 'react';
|
import { useEffect, useCallback, useContext } from 'react';
|
||||||
import CanvasContext from './Context/canvasContext/CanvasContext';
|
import CanvasContext from './Context/canvasContext/CanvasContext';
|
||||||
import ActiveObjectContext from './Context/activeObject/ObjectContext';
|
import ActiveObjectContext from './Context/activeObject/ObjectContext';
|
||||||
import { Rnd } from 'react-rnd';
|
|
||||||
import OpenContext from './Context/openContext/OpenContext';
|
import OpenContext from './Context/openContext/OpenContext';
|
||||||
import CanvasSetting from './CanvasSetting';
|
import CanvasSetting from './CanvasSetting';
|
||||||
import { EditPanel } from './EditPanel';
|
import { EditPanel } from './EditPanel';
|
||||||
|
|
@ -79,21 +78,9 @@ const Canvas = () => {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-center relative w-full h-full overflow-hidden'>
|
<div className='flex flex-col items-center relative w-full h-full overflow-hidden'>
|
||||||
|
|
||||||
{openSetting && (
|
{openSetting &&
|
||||||
<Rnd
|
<CanvasSetting />
|
||||||
className='z-[1000]'
|
}
|
||||||
default={{
|
|
||||||
x: 0,
|
|
||||||
y: 20,
|
|
||||||
}}
|
|
||||||
minWidth={220}
|
|
||||||
maxWidth={250}
|
|
||||||
minHeight={150}
|
|
||||||
bounds='parent'
|
|
||||||
>
|
|
||||||
<CanvasSetting />
|
|
||||||
</Rnd>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
openPanel &&
|
openPanel &&
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardHeader, CardTitle } from './ui/card';
|
import { Card, CardHeader, CardTitle } from './ui/card';
|
||||||
import { Rnd } from 'react-rnd';
|
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { Separator } from './ui/separator';
|
import { Separator } from './ui/separator';
|
||||||
|
import RndComponent from './Layouts/RndComponent';
|
||||||
|
|
||||||
const resolutions = [
|
const resolutions = [
|
||||||
{ value: '720p', label: 'HD (1280x720)', width: 1280, height: 720 },
|
{ value: '720p', label: 'HD (1280x720)', width: 1280, height: 720 },
|
||||||
|
|
@ -73,28 +73,33 @@ const CanvasCapture = () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rndValue = {
|
||||||
|
valueX: 0,
|
||||||
|
valueY: 20,
|
||||||
|
width: 250,
|
||||||
|
height: 150,
|
||||||
|
minWidth: 250,
|
||||||
|
maxWidth: 300,
|
||||||
|
minHeight: 150,
|
||||||
|
maxHeight: 300,
|
||||||
|
bound: "parent"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{captureOpen && (
|
{captureOpen && (
|
||||||
<Rnd
|
<RndComponent value={rndValue}>
|
||||||
className='z-[1000]'
|
|
||||||
default={{ x: 0, y: 20 }}
|
|
||||||
minWidth={250}
|
|
||||||
maxWidth={300}
|
|
||||||
minHeight={150}
|
|
||||||
bounds='parent'
|
|
||||||
>
|
|
||||||
<Card className='space-y-2 p-2'>
|
<Card className='space-y-2 p-2'>
|
||||||
<CardHeader className='p-0'>
|
<CardHeader className='p-0'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<Button variant={'ghost'} onClick={() => setCaptureOpen(false)}>
|
<Button className="rnd-escape" variant={'ghost'} onClick={() => setCaptureOpen(false)}>
|
||||||
<X className='cursor-pointer' />
|
<X className='cursor-pointer' />
|
||||||
</Button>
|
</Button>
|
||||||
<CardTitle className='text-lg mr-1'>Capture Panel</CardTitle>
|
<CardTitle className='text-lg mr-1'>Capture Panel</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4'>
|
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4 rnd-escape'>
|
||||||
<div className='space-y-2'>
|
<div className='space-y-2'>
|
||||||
<Label htmlFor='resolution'>Resolution</Label>
|
<Label htmlFor='resolution'>Resolution</Label>
|
||||||
<Select onValueChange={setResolution} defaultValue={resolution}>
|
<Select onValueChange={setResolution} defaultValue={resolution}>
|
||||||
|
|
@ -126,11 +131,11 @@ const CanvasCapture = () => {
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={captureImage} className='w-full'>
|
<Button onClick={captureImage} className='w-full rnd-escape'>
|
||||||
Capture Canvas
|
Capture Canvas
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
</Rnd>
|
</RndComponent>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import { Input } from './ui/input';
|
||||||
import { Slider } from './ui/slider';
|
import { Slider } from './ui/slider';
|
||||||
import { fabric } from 'fabric';
|
import { fabric } from 'fabric';
|
||||||
import OpenContext from './Context/openContext/OpenContext';
|
import OpenContext from './Context/openContext/OpenContext';
|
||||||
|
import { ScrollArea } from './ui/scroll-area';
|
||||||
|
import RndComponent from './Layouts/RndComponent';
|
||||||
|
|
||||||
const CanvasSetting = () => {
|
const CanvasSetting = () => {
|
||||||
const { canvas } = useContext(CanvasContext);
|
const { canvas } = useContext(CanvasContext);
|
||||||
|
|
@ -155,104 +157,120 @@ const CanvasSetting = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rndValue = {
|
||||||
|
valueX: 0,
|
||||||
|
valueY: 20,
|
||||||
|
width: 250,
|
||||||
|
height: 0,
|
||||||
|
minWidth: 250,
|
||||||
|
maxWidth: 300,
|
||||||
|
minHeight: 0,
|
||||||
|
maxHeight: 400,
|
||||||
|
bound: "parent"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="px-2 py-2">
|
<RndComponent value={rndValue}>
|
||||||
<CardTitle className="flex items-center flex-wrap justify-between gap-1">Canvas Setting <Button variant="secondary" onClick={() => setOpenSetting(false)}><X /></Button> </CardTitle>
|
<Card className="px-2 py-2">
|
||||||
<Separator className="mt-4" />
|
<CardTitle className="flex items-center flex-wrap justify-between gap-1">Canvas Setting <Button className="rnd-escape" variant="secondary" onClick={() => setOpenSetting(false)}><X /></Button> </CardTitle>
|
||||||
<div>
|
|
||||||
|
|
||||||
<ColorComponent />
|
|
||||||
|
|
||||||
<div className='flex flex-col my-2 gap-2'>
|
|
||||||
<div>
|
|
||||||
<Label>Background:</Label>
|
|
||||||
<div className='flex items-center w-fit gap-2 flex-wrap relative'>
|
|
||||||
<Button className="top-0 absolute flex items-center w-[30px]">
|
|
||||||
<UploadIcon className="cursor-pointer" />
|
|
||||||
<Input
|
|
||||||
ref={bgImgRef}
|
|
||||||
className="absolute top-0 opacity-0"
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
onChange={setBackgroundImage}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button variant="secondary" className="ml-[35px]" onClick={removeBackgroundImage}><Trash2 /></Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>Background Overlay:</Label>
|
|
||||||
<div className='flex items-center w-fit gap-2 flex-wrap relative'>
|
|
||||||
<Button className="top-0 absolute flex items-center w-[30px]">
|
|
||||||
<UploadIcon className="cursor-pointer" />
|
|
||||||
<Input
|
|
||||||
className="absolute top-0 opacity-0"
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
onChange={setBackgroundOverlayImage}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button variant="secondary" className="ml-[35px]" onClick={removeBackgroundOverlayImage}><Trash2 /></Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Separator className="mt-4" />
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
|
||||||
<Label>
|
|
||||||
Adjust Opacity:
|
|
||||||
</Label>
|
|
||||||
<Slider
|
|
||||||
defaultValue={[1.0]} // Default value, you can set it to 0.0 or another value
|
|
||||||
min={0.0}
|
|
||||||
max={1.0}
|
|
||||||
step={0.01} // Step size for fine control
|
|
||||||
onValueChange={(value) => {
|
|
||||||
const newOpacity = value[0]; // Extract slider value
|
|
||||||
adjustBackgroundOpacity(newOpacity); // Adjust Fabric.js background opacity
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Separator className="mt-4" />
|
<Separator className="mt-4" />
|
||||||
|
<ScrollArea className="h-[400px] xl:h-fit lg:h-fit md:h-fit">
|
||||||
|
<div className='rnd-escape'>
|
||||||
|
|
||||||
<div className='flex gap-2 my-2'>
|
<ColorComponent />
|
||||||
<div className='flex flex-col gap-2'>
|
|
||||||
<Label>
|
|
||||||
Width:
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
value={canvasSettings.width}
|
|
||||||
onChange={(e) => {
|
|
||||||
if (canvasSettings?.width > parseInt(e.target.value)) {
|
|
||||||
handleChange('width', parseInt(e.target.value, 10));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col my-2 gap-2 rnd-escape'>
|
||||||
<Label>
|
<div>
|
||||||
Height:
|
<Label>Background:</Label>
|
||||||
</Label>
|
<div className='flex items-center w-fit gap-2 flex-wrap relative'>
|
||||||
<Input
|
<Button className="top-0 absolute flex items-center w-[30px]">
|
||||||
type="number"
|
<UploadIcon className="cursor-pointer" />
|
||||||
value={canvasSettings.height}
|
<Input
|
||||||
onChange={(e) => {
|
ref={bgImgRef}
|
||||||
if (canvasSettings?.height > parseInt(e.target.value)) {
|
className="absolute top-0 opacity-0"
|
||||||
handleChange('height', parseInt(e.target.value, 10));
|
type="file"
|
||||||
}
|
accept="image/*"
|
||||||
}}
|
onChange={setBackgroundImage}
|
||||||
/>
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button variant="secondary" className="ml-[35px]" onClick={removeBackgroundImage}><Trash2 /></Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>Background Overlay:</Label>
|
||||||
|
<div className='flex items-center w-fit gap-2 flex-wrap relative'>
|
||||||
|
<Button className="top-0 absolute flex items-center w-[30px]">
|
||||||
|
<UploadIcon className="cursor-pointer" />
|
||||||
|
<Input
|
||||||
|
className="absolute top-0 opacity-0"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
onChange={setBackgroundOverlayImage}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button variant="secondary" className="ml-[35px]" onClick={removeBackgroundOverlayImage}><Trash2 /></Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="mt-4" />
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-2 rnd-escape'>
|
||||||
|
<Label>
|
||||||
|
Adjust Opacity:
|
||||||
|
</Label>
|
||||||
|
<Slider
|
||||||
|
defaultValue={[1.0]} // Default value, you can set it to 0.0 or another value
|
||||||
|
min={0.0}
|
||||||
|
max={1.0}
|
||||||
|
step={0.01} // Step size for fine control
|
||||||
|
onValueChange={(value) => {
|
||||||
|
const newOpacity = value[0]; // Extract slider value
|
||||||
|
adjustBackgroundOpacity(newOpacity); // Adjust Fabric.js background opacity
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="mt-4" />
|
||||||
|
|
||||||
|
<div className='flex gap-2 my-2'>
|
||||||
|
<div className='flex flex-col gap-2'>
|
||||||
|
<Label>
|
||||||
|
Width:
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
value={canvasSettings.width}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (canvasSettings?.width > parseInt(e.target.value)) {
|
||||||
|
handleChange('width', parseInt(e.target.value, 10));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-2'>
|
||||||
|
<Label>
|
||||||
|
Height:
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
value={canvasSettings.height}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (canvasSettings?.height > parseInt(e.target.value)) {
|
||||||
|
handleChange('height', parseInt(e.target.value, 10));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ScrollArea>
|
||||||
</div>
|
</Card>
|
||||||
</Card>
|
</RndComponent>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { Rnd } from 'react-rnd';
|
|
||||||
import { useCallback, useContext, useState } from "react"
|
import { useCallback, useContext, useState } from "react"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
|
|
@ -10,6 +9,7 @@ import OpenContext from './Context/openContext/OpenContext';
|
||||||
import CanvasContext from './Context/canvasContext/CanvasContext';
|
import CanvasContext from './Context/canvasContext/CanvasContext';
|
||||||
import ActiveObjectContext from './Context/activeObject/ObjectContext';
|
import ActiveObjectContext from './Context/activeObject/ObjectContext';
|
||||||
import { fabric } from 'fabric';
|
import { fabric } from 'fabric';
|
||||||
|
import RndComponent from './Layouts/RndComponent';
|
||||||
|
|
||||||
export function EditPanel() {
|
export function EditPanel() {
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
|
|
@ -189,31 +189,31 @@ export function EditPanel() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rndValue = {
|
||||||
|
valueX: 0,
|
||||||
|
valueY: 20,
|
||||||
|
width: 250,
|
||||||
|
height: 0,
|
||||||
|
minWidth: 250,
|
||||||
|
maxWidth: 300,
|
||||||
|
minHeight: 0,
|
||||||
|
maxHeight: 0,
|
||||||
|
bound: "parent"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Rnd
|
<RndComponent value={rndValue}>
|
||||||
default={{
|
|
||||||
x: 0,
|
|
||||||
y: 20,
|
|
||||||
width: 300,
|
|
||||||
height: 'auto',
|
|
||||||
}}
|
|
||||||
minWidth={200}
|
|
||||||
maxWidth={300}
|
|
||||||
bounds="parent"
|
|
||||||
enableResizing={{ right: true }}
|
|
||||||
className="z-[1000]"
|
|
||||||
>
|
|
||||||
<Card className="w-full shadow-lg">
|
<Card className="w-full shadow-lg">
|
||||||
<CardHeader className="p-1 mr-12">
|
<CardHeader className="p-1 mr-12">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Button variant={"ghost"} onClick={() => setOpenPanel(false)}><X /></Button>
|
<Button className="rnd-escape" variant={"ghost"} onClick={() => setOpenPanel(false)}><X /></Button>
|
||||||
<CardTitle className="text-lg">Edit Panel</CardTitle>
|
<CardTitle className="text-lg">Edit Panel</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<Collapsible open={!isCollapsed} onOpenChange={(open) => setIsCollapsed(!open)}>
|
<Collapsible open={!isCollapsed} onOpenChange={(open) => setIsCollapsed(!open)}>
|
||||||
<CollapsibleTrigger asChild>
|
<CollapsibleTrigger asChild>
|
||||||
<Button variant="ghost" size="sm" className="absolute top-1 right-2">
|
<Button variant="ghost" size="sm" className="absolute top-1 right-2 rnd-escape">
|
||||||
{isCollapsed ? <ChevronDown className="h-4 w-4" /> : <ChevronUp className="h-4 w-4" />}
|
{isCollapsed ? <ChevronDown className="h-4 w-4" /> : <ChevronUp className="h-4 w-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
|
|
@ -373,7 +373,7 @@ export function EditPanel() {
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</Card>
|
</Card>
|
||||||
</Rnd>
|
</RndComponent>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
28
src/components/Layouts/RndComponent.jsx
Normal file
28
src/components/Layouts/RndComponent.jsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Rnd } from 'react-rnd';
|
||||||
|
|
||||||
|
const RndComponent = ({ children, value }) => {
|
||||||
|
|
||||||
|
const { valueX, valueY, width, height, minWidth, maxWidth, minHeight, maxHeight, bound } = value;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Rnd
|
||||||
|
default={{
|
||||||
|
x: valueX,
|
||||||
|
y: valueY,
|
||||||
|
width: width,
|
||||||
|
height: 'auto',
|
||||||
|
}}
|
||||||
|
minWidth={minWidth}
|
||||||
|
maxWidth={maxWidth}
|
||||||
|
maxHeight={maxHeight}
|
||||||
|
bounds={bound}
|
||||||
|
className="z-[1000]"
|
||||||
|
cancel=".rnd-escape"
|
||||||
|
>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
</Rnd>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RndComponent
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import { Button } from './ui/button'
|
import { Button } from './ui/button'
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from './ui/card'
|
import { Card, CardHeader, CardTitle } from './ui/card'
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'
|
||||||
import { useContext, useState } from 'react'
|
import { useContext, useState } from 'react'
|
||||||
import { PencilRuler, Shapes, Store, Upload, ChevronDown, ChevronUp, X } from 'lucide-react';
|
import { PencilRuler, Shapes, Store, Upload, ChevronDown, ChevronUp, X } from 'lucide-react';
|
||||||
import { Rnd } from 'react-rnd';
|
|
||||||
import OpenContext from './Context/openContext/OpenContext';
|
import OpenContext from './Context/openContext/OpenContext';
|
||||||
import AllIconsPage from './EachComponent/Icons/AllIcons'
|
import AllIconsPage from './EachComponent/Icons/AllIcons'
|
||||||
import { Separator } from './ui/separator'
|
import { Separator } from './ui/separator'
|
||||||
|
|
@ -12,34 +11,35 @@ import { ScrollArea } from './ui/scroll-area'
|
||||||
import AddShapes from './Layouts/AddShapes'
|
import AddShapes from './Layouts/AddShapes'
|
||||||
import UploadImage from './EachComponent/UploadImage'
|
import UploadImage from './EachComponent/UploadImage'
|
||||||
import CustomizeShape from './EachComponent/CustomizeShape'
|
import CustomizeShape from './EachComponent/CustomizeShape'
|
||||||
|
import RndComponent from './Layouts/RndComponent'
|
||||||
|
|
||||||
const ObjectPanel = () => {
|
const ObjectPanel = () => {
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
const { tabValue, setTabValue, setOpenObjectPanel } = useContext(OpenContext);
|
const { tabValue, setTabValue, setOpenObjectPanel } = useContext(OpenContext);
|
||||||
|
|
||||||
|
const rndValue = {
|
||||||
|
valueX: 0,
|
||||||
|
valueY: 20,
|
||||||
|
width: 250,
|
||||||
|
height: 0,
|
||||||
|
minWidth: 250,
|
||||||
|
maxWidth: 300,
|
||||||
|
minHeight: 0,
|
||||||
|
maxHeight: 400,
|
||||||
|
bound: "parent"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Rnd
|
<RndComponent value={rndValue}>
|
||||||
default={{
|
|
||||||
x: 0,
|
|
||||||
y: 20,
|
|
||||||
width: 300,
|
|
||||||
height: 'auto',
|
|
||||||
}}
|
|
||||||
minWidth={270}
|
|
||||||
maxWidth={300}
|
|
||||||
maxHeight={500}
|
|
||||||
bounds="parent"
|
|
||||||
enableResizing={{ right: true }}
|
|
||||||
className="z-40"
|
|
||||||
>
|
|
||||||
<Card className="w-full shadow-lg">
|
<Card className="w-full shadow-lg">
|
||||||
<CardHeader className="p-1 mr-12">
|
<CardHeader className="p-1 mr-12">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Button variant={"ghost"} size={"sm"} onClick={() => setOpenObjectPanel(false)}><X /></Button>
|
<Button className="rnd-escape" variant={"ghost"} size={"sm"} onClick={() => setOpenObjectPanel(false)}><X /></Button>
|
||||||
<CardTitle className="text-lg">Object Panel</CardTitle>
|
<CardTitle className="text-lg">Object Panel</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<Collapsible open={!isCollapsed} onOpenChange={(open) => setIsCollapsed(!open)}>
|
<Collapsible className="rnd-escape" open={!isCollapsed} onOpenChange={(open) => setIsCollapsed(!open)}>
|
||||||
|
|
||||||
<CollapsibleTrigger asChild>
|
<CollapsibleTrigger asChild>
|
||||||
<Button variant="ghost" size="sm" className="absolute top-1 right-2">
|
<Button variant="ghost" size="sm" className="absolute top-1 right-2">
|
||||||
|
|
@ -48,21 +48,48 @@ const ObjectPanel = () => {
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
|
|
||||||
<CollapsibleContent>
|
<CollapsibleContent>
|
||||||
<CardContent className="p-2">
|
<ScrollArea className="h-[400px] xl:h-fit lg:h-fit md:h-fit">
|
||||||
<Tabs className="w-full h-fit"
|
<Tabs className="w-full h-fit"
|
||||||
value={tabValue}
|
value={tabValue}
|
||||||
onValueChange={(value) => setTabValue(value)} // Sync tab state with context
|
onValueChange={(value) => setTabValue(value)} // Sync tab state with context
|
||||||
>
|
>
|
||||||
|
|
||||||
<TabsList className="grid w-full grid-cols-4 h-fit gap-1">
|
<TabsList className="grid w-full grid-cols-4 h-fit gap-1">
|
||||||
<TabsTrigger value="icons" className="flex flex-col gap-1 text-xs" onClick={() => setTabValue("icons")}>
|
<TabsTrigger
|
||||||
<Store className="h-4 w-4" />Icons
|
value="icons"
|
||||||
|
className="flex flex-col gap-1 text-xs"
|
||||||
|
onClick={() => setTabValue("icons")}
|
||||||
|
>
|
||||||
|
<Store className="h-4 w-4" />
|
||||||
|
<span className="hidden sm:block">Icons</span>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
|
||||||
<TabsTrigger value="shapes" className="flex flex-wrap gap-1 text-xs" onClick={() => setTabValue("shapes")}><Shapes className="h-4 w-4" />Shapes</TabsTrigger>
|
<TabsTrigger
|
||||||
<TabsTrigger value="images" className="flex flex-wrap gap-1 text-xs" onClick={() => setTabValue("images")}><Upload className="h-4 w-4" />Images</TabsTrigger>
|
value="shapes"
|
||||||
|
className="flex flex-col gap-1 text-xs"
|
||||||
|
onClick={() => setTabValue("shapes")}
|
||||||
|
>
|
||||||
|
<Shapes className="h-4 w-4" />
|
||||||
|
<span className="hidden sm:block">Shapes</span>
|
||||||
|
</TabsTrigger>
|
||||||
|
|
||||||
<TabsTrigger value="customize" className="flex flex-wrap gap-1 text-xs" onClick={() => setTabValue("customize")}><PencilRuler className="h-4 w-4" />Customize</TabsTrigger>
|
<TabsTrigger
|
||||||
|
value="images"
|
||||||
|
className="flex flex-col gap-1 text-xs"
|
||||||
|
onClick={() => setTabValue("images")}
|
||||||
|
>
|
||||||
|
<Upload className="h-4 w-4" />
|
||||||
|
<span className="hidden sm:block">Images</span>
|
||||||
|
</TabsTrigger>
|
||||||
|
|
||||||
|
<TabsTrigger
|
||||||
|
value="customize"
|
||||||
|
className="flex flex-col gap-1 text-xs"
|
||||||
|
onClick={() => setTabValue("customize")}
|
||||||
|
>
|
||||||
|
<PencilRuler className="h-4 w-4" />
|
||||||
|
<span className="hidden sm:block">Customize</span>
|
||||||
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
{/* All icons */}
|
{/* All icons */}
|
||||||
|
|
@ -109,7 +136,7 @@ const ObjectPanel = () => {
|
||||||
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
</CardContent>
|
</ScrollArea>
|
||||||
|
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
|
|
||||||
|
|
@ -117,7 +144,7 @@ const ObjectPanel = () => {
|
||||||
|
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
</Rnd>
|
</RndComponent>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const ScrollArea = React.forwardRef(({ className, children, ...props }, ref) =>
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("relative overflow-hidden", className)}
|
className={cn("relative overflow-hidden", className)}
|
||||||
{...props}>
|
{...props}>
|
||||||
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit] p-1">
|
||||||
{children}
|
{children}
|
||||||
</ScrollAreaPrimitive.Viewport>
|
</ScrollAreaPrimitive.Viewport>
|
||||||
<ScrollBar />
|
<ScrollBar />
|
||||||
|
|
@ -24,9 +24,9 @@ const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...pr
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex touch-none select-none transition-colors",
|
"flex touch-none select-none transition-colors",
|
||||||
orientation === "vertical" &&
|
orientation === "vertical" &&
|
||||||
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
||||||
orientation === "horizontal" &&
|
orientation === "horizontal" &&
|
||||||
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}>
|
{...props}>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue