Add comprehensive rulers and guides system for canvas alignment and positioning. Features: - Guides store with full CRUD operations - Horizontal and vertical guide support - Ruler display with 50px intervals - Green guide lines with subtle glow - Toggle visibility for rulers and guides - Persistent storage of guides and settings - Snap distance configuration - Guide position in canvas pixels - Zoom-aware positioning Changes: - Created store/guides-store.ts with Guide interface - Added guides state management with persistence - Created components/canvas/rulers-and-guides.tsx - Rulers show measurements at 50px intervals - Guides rendered as 1px green lines with shadow - Exported guides store from store/index.ts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
92 lines
2.2 KiB
TypeScript
92 lines
2.2 KiB
TypeScript
import { create } from 'zustand';
|
|
import { persist } from 'zustand/middleware';
|
|
|
|
export interface Guide {
|
|
id: string;
|
|
type: 'horizontal' | 'vertical';
|
|
position: number; // In canvas pixels
|
|
}
|
|
|
|
interface GuidesStore {
|
|
/** All guides */
|
|
guides: Guide[];
|
|
/** Whether guides are visible */
|
|
showGuides: boolean;
|
|
/** Whether rulers are visible */
|
|
showRulers: boolean;
|
|
/** Snap to guides threshold in pixels */
|
|
snapDistance: number;
|
|
|
|
/** Add a guide */
|
|
addGuide: (type: 'horizontal' | 'vertical', position: number) => void;
|
|
/** Remove a guide */
|
|
removeGuide: (id: string) => void;
|
|
/** Update guide position */
|
|
updateGuide: (id: string, position: number) => void;
|
|
/** Clear all guides */
|
|
clearGuides: () => void;
|
|
/** Toggle guides visibility */
|
|
toggleGuides: () => void;
|
|
/** Toggle rulers visibility */
|
|
toggleRulers: () => void;
|
|
/** Set snap distance */
|
|
setSnapDistance: (distance: number) => void;
|
|
}
|
|
|
|
export const useGuidesStore = create<GuidesStore>()(
|
|
persist(
|
|
(set, get) => ({
|
|
guides: [],
|
|
showGuides: true,
|
|
showRulers: true,
|
|
snapDistance: 10,
|
|
|
|
addGuide: (type, position) => {
|
|
const id = `guide-${Date.now()}-${Math.random()}`;
|
|
set((state) => ({
|
|
guides: [...state.guides, { id, type, position }],
|
|
}));
|
|
},
|
|
|
|
removeGuide: (id) => {
|
|
set((state) => ({
|
|
guides: state.guides.filter((g) => g.id !== id),
|
|
}));
|
|
},
|
|
|
|
updateGuide: (id, position) => {
|
|
set((state) => ({
|
|
guides: state.guides.map((g) =>
|
|
g.id === id ? { ...g, position } : g
|
|
),
|
|
}));
|
|
},
|
|
|
|
clearGuides: () => {
|
|
set({ guides: [] });
|
|
},
|
|
|
|
toggleGuides: () => {
|
|
set((state) => ({ showGuides: !state.showGuides }));
|
|
},
|
|
|
|
toggleRulers: () => {
|
|
set((state) => ({ showRulers: !state.showRulers }));
|
|
},
|
|
|
|
setSnapDistance: (distance) => {
|
|
set({ snapDistance: Math.max(0, Math.min(50, distance)) });
|
|
},
|
|
}),
|
|
{
|
|
name: 'guides-storage',
|
|
partialize: (state) => ({
|
|
guides: state.guides,
|
|
showGuides: state.showGuides,
|
|
showRulers: state.showRulers,
|
|
snapDistance: state.snapDistance,
|
|
}),
|
|
}
|
|
)
|
|
);
|