Update
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
@@ -29,20 +30,31 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
const [isBold, setIsBold] = useState(true);
|
||||
const [isItalic, setIsItalic] = useState(false);
|
||||
const [fontFamily, setFontFamily] = useState('Montserrat');
|
||||
const [fillColor, setFillColor] = useState('#ffffff');
|
||||
const [strokeColor, setStrokeColor] = useState('#000000');
|
||||
const [strokeWidth, setStrokeWidth] = useState(2);
|
||||
|
||||
// Font size constraints
|
||||
const MIN_FONT_SIZE = 8;
|
||||
const MAX_FONT_SIZE = 120;
|
||||
const FONT_SIZE_STEP = 2;
|
||||
|
||||
// Stroke width constraints
|
||||
const MIN_STROKE_WIDTH = 0;
|
||||
const MAX_STROKE_WIDTH = 10;
|
||||
const STROKE_WIDTH_STEP = 1;
|
||||
|
||||
// Update state when selected element changes - THIS KEEPS SIDEBAR IN SYNC WITH TRANSFORMER
|
||||
useEffect(() => {
|
||||
if (selectedTextElement) {
|
||||
setTextValue(selectedTextElement.text || '');
|
||||
setFontSize(selectedTextElement.fontSize || 24); // Always use current fontSize from element
|
||||
setFontSize(selectedTextElement.fontSize || 24);
|
||||
setIsBold(selectedTextElement.fontWeight === 'bold' || selectedTextElement.fontWeight === 700 || true);
|
||||
setIsItalic(selectedTextElement.fontStyle === 'italic' || false);
|
||||
setFontFamily(selectedTextElement.fontFamily || 'Montserrat');
|
||||
setFillColor(selectedTextElement.fill || '#ffffff');
|
||||
setStrokeColor(selectedTextElement.stroke || '#000000');
|
||||
setStrokeWidth(selectedTextElement.strokeWidth || 2);
|
||||
}
|
||||
}, [selectedTextElement]);
|
||||
|
||||
@@ -72,6 +84,45 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
}
|
||||
};
|
||||
|
||||
// Handle stroke width changes
|
||||
const handleStrokeWidthChange = (newWidth) => {
|
||||
const clampedWidth = Math.max(MIN_STROKE_WIDTH, Math.min(MAX_STROKE_WIDTH, newWidth));
|
||||
setStrokeWidth(clampedWidth);
|
||||
|
||||
if (selectedTextElement) {
|
||||
emitter.emit('text-update', {
|
||||
elementId: selectedTextElement.id,
|
||||
updates: { strokeWidth: clampedWidth },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handle fill color changes
|
||||
const handleFillColorChange = (e) => {
|
||||
const newColor = e.target.value;
|
||||
setFillColor(newColor);
|
||||
|
||||
if (selectedTextElement) {
|
||||
emitter.emit('text-update', {
|
||||
elementId: selectedTextElement.id,
|
||||
updates: { fill: newColor },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handle stroke color changes
|
||||
const handleStrokeColorChange = (e) => {
|
||||
const newColor = e.target.value;
|
||||
setStrokeColor(newColor);
|
||||
|
||||
if (selectedTextElement) {
|
||||
emitter.emit('text-update', {
|
||||
elementId: selectedTextElement.id,
|
||||
updates: { stroke: newColor },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handle font family changes
|
||||
const handleFontFamilyChange = (newFontFamily) => {
|
||||
setFontFamily(newFontFamily);
|
||||
@@ -120,9 +171,19 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
handleFontSizeChange(fontSize - FONT_SIZE_STEP);
|
||||
};
|
||||
|
||||
// Increase stroke width
|
||||
const increaseStrokeWidth = () => {
|
||||
handleStrokeWidthChange(strokeWidth + STROKE_WIDTH_STEP);
|
||||
};
|
||||
|
||||
// Decrease stroke width
|
||||
const decreaseStrokeWidth = () => {
|
||||
handleStrokeWidthChange(strokeWidth - STROKE_WIDTH_STEP);
|
||||
};
|
||||
|
||||
return (
|
||||
<Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||
<SheetContent side="right" className="max-[140px] w-full overflow-y-auto">
|
||||
<SheetContent side="right" className="max-[140px] w-full overflow-y-auto dark:bg-neutral-900">
|
||||
<SheetHeader>
|
||||
<SheetTitle className="flex items-center gap-3">
|
||||
<Type className="h-6 w-6" />
|
||||
@@ -140,13 +201,23 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
value={textValue}
|
||||
onChange={handleTextChange}
|
||||
placeholder="Enter your text..."
|
||||
className="mt-2 text-center text-nowrap"
|
||||
className="mt-2 text-center text-nowrap dark:bg-neutral-800"
|
||||
rows={4}
|
||||
style={{
|
||||
fontFamily: fontFamily,
|
||||
fontSize: `${fontSize * 0.6}px`, // Cap preview size for readability
|
||||
fontWeight: isBold ? 'bold' : 'normal',
|
||||
fontStyle: isItalic ? 'italic' : 'normal',
|
||||
color: fillColor,
|
||||
textShadow:
|
||||
strokeWidth > 0
|
||||
? `
|
||||
-${strokeWidth * 0.6}px -${strokeWidth * 0.6}px 0 ${strokeColor},
|
||||
${strokeWidth * 0.6}px -${strokeWidth * 0.6}px 0 ${strokeColor},
|
||||
-${strokeWidth * 0.6}px ${strokeWidth * 0.6}px 0 ${strokeColor},
|
||||
${strokeWidth * 0.6}px ${strokeWidth * 0.6}px 0 ${strokeColor}
|
||||
`
|
||||
: 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -181,7 +252,7 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
<label className="text-sm font-medium">Font Size</label>
|
||||
<div className="mt-2 flex items-center justify-between rounded-lg border p-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="default"
|
||||
size="icon"
|
||||
onClick={decreaseFontSize}
|
||||
disabled={fontSize <= MIN_FONT_SIZE}
|
||||
@@ -196,7 +267,7 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="default"
|
||||
size="icon"
|
||||
onClick={increaseFontSize}
|
||||
disabled={fontSize >= MAX_FONT_SIZE}
|
||||
@@ -220,8 +291,8 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
<label className="text-sm font-medium">Font Style</label>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<Button
|
||||
variant={isBold ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
variant={isBold ? 'default' : 'secondary'}
|
||||
size=""
|
||||
onClick={handleBoldToggle}
|
||||
className="flex flex-1 items-center gap-2"
|
||||
>
|
||||
@@ -230,8 +301,8 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant={isItalic ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
variant={isItalic ? 'default' : 'secondary'}
|
||||
size=""
|
||||
onClick={handleItalicToggle}
|
||||
className="flex flex-1 items-center gap-2"
|
||||
>
|
||||
@@ -240,6 +311,55 @@ export default function TextSidebar({ isOpen, onClose }) {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Font Color */}
|
||||
<div>
|
||||
<label className="text-sm font-medium">Font Color</label>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<Input className="h-10 w-20" type="color" value={fillColor} onChange={handleFillColorChange} />
|
||||
<Input type="text" value={fillColor} onChange={handleFillColorChange} placeholder="#ffffff" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Outline Color */}
|
||||
<div>
|
||||
<label className="text-sm font-medium">Outline Color</label>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<Input className="h-10 w-20" type="color" value={strokeColor} onChange={handleStrokeColorChange} />
|
||||
<Input type="text" value={strokeColor} onChange={handleStrokeColorChange} placeholder="#000000" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Outline Thickness */}
|
||||
<div>
|
||||
<label className="text-sm font-medium">Outline Thickness</label>
|
||||
<div className="mt-2 flex items-center justify-between rounded-lg border p-2">
|
||||
<Button
|
||||
variant="default"
|
||||
size="icon"
|
||||
onClick={decreaseStrokeWidth}
|
||||
disabled={strokeWidth <= MIN_STROKE_WIDTH}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-lg font-semibold">{strokeWidth}</span>
|
||||
<span className="text-sm text-gray-500">px</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="default"
|
||||
size="icon"
|
||||
onClick={increaseStrokeWidth}
|
||||
disabled={strokeWidth >= MAX_STROKE_WIDTH}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center text-gray-500">
|
||||
|
||||
Reference in New Issue
Block a user