feat: add background panel for solid and gradient backgrounds

feat: implement code inspector with language detection and theme selection

feat: create text inspector for text properties and styling

style: add global styles and custom scrollbar for better UI

chore: initialize main entry point for the application

feat: set up Zustand store for canvas state management

feat: define types for canvas elements and background options

feat: implement code highlighting utility with language detection

chore: configure TypeScript settings for the project

chore: set up Vite configuration for React and Tailwind CSS
This commit is contained in:
2026-01-07 16:07:30 +02:00
commit bb5a9e0715
30 changed files with 6844 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import React, { useRef } from 'react';
import { Group, Arrow as KonvaArrow, Circle } from 'react-konva';
import type Konva from 'konva';
import type { ArrowElement } from '../../types';
interface ArrowProps {
element: ArrowElement;
isSelected: boolean;
onSelect: () => void;
onChange: (updates: Partial<ArrowElement>) => void;
}
const Arrow: React.FC<ArrowProps> = ({ element, isSelected, onSelect, onChange }) => {
const arrowRef = useRef<Konva.Arrow>(null);
const { points, props } = element;
// Flatten points for Konva
const flatPoints = points.flatMap(p => [p.x, p.y]);
const handlePointDrag = (index: number, e: Konva.KonvaEventObject<DragEvent>) => {
const newPoints = [...points];
newPoints[index] = {
x: e.target.x(),
y: e.target.y(),
};
onChange({ points: newPoints });
};
// Arrow head pointer
const pointerLength = props.head === 'none' ? 0 : props.thickness * 4;
const pointerWidth = props.head === 'none' ? 0 : props.thickness * 3;
return (
<Group>
<KonvaArrow
ref={arrowRef}
points={flatPoints}
stroke={props.color}
strokeWidth={props.thickness}
fill={props.head === 'filled' ? props.color : 'transparent'}
pointerLength={pointerLength}
pointerWidth={pointerWidth}
tension={props.style === 'curved' ? 0.5 : 0}
lineCap="round"
lineJoin="round"
onClick={onSelect}
onTap={onSelect}
hitStrokeWidth={20}
/>
{/* Control points when selected */}
{isSelected && points.map((point, index) => (
<Circle
key={index}
x={point.x}
y={point.y}
radius={8}
fill="#3b82f6"
stroke="#ffffff"
strokeWidth={2}
draggable={!element.locked}
onDragMove={(e) => handlePointDrag(index, e)}
onDragEnd={(e) => handlePointDrag(index, e)}
/>
))}
</Group>
);
};
export default Arrow;