You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
10 KiB

# Divi-Like Visual Builder Plan
## Overview
Transform the current PDF editor into a Divi-inspired visual builder with intuitive inline controls, drag-and-drop functionality, and seamless element manipulation.
## Current State vs Target State
### Current State
- Toolbar-based insertion from sidebar
- Basic selection with outline highlighting
- No inline insertion controls
- No drag-and-drop
- No hover action menus
### Target State (Divi-like)
- Inline '+' buttons between elements for contextual insertion
- Hover action menus with settings, duplicate, delete, move
- Full drag-and-drop support with visual feedback
- Ghost previews and drop zone indicators
---
## Feature 1: Inline Insertion System
### Description
Add '+' buttons that appear between elements and at the end of containers, allowing users to insert new elements at specific positions.
### Visual Design
```
┌─────────────────────────────────────┐
│ Section │
│ ┌─────────────────────────────────┐ │
│ │ Row │ │
│ │ ┌───────────┐ ┌───────────┐ │ │
│ │ │ Column │ │ Column │ │ │
│ │ │ [Text] │ │ [Image] │ │ │
│ │ │ │ │ │ │ │
│ │ │ [+] │ │ [+] │ │ │
│ │ └───────────┘ └───────────┘ │ │
│ │ [+] │ │ ← Add column button
│ └─────────────────────────────────┘ │
│ [+] │ ← Add row button
└─────────────────────────────────────┘
```
### Components Needed
#### InsertButton.svelte
```typescript
interface Props {
position: 'before' | 'after' | 'inside'
parentId: string
index: number
allowedTypes: NodeType[]
oninsert: (type: NodeType, parentId: string, index: number) => void
}
```
#### InsertionPopup.svelte
- Appears when clicking '+'
- Shows allowed element types based on context
- Respects hierarchy rules
### Behavior
1. Insert buttons appear on hover over containers
2. Clicking '+' shows a popup with allowed types
3. Selecting a type inserts at that exact position
4. Buttons are context-aware (only show valid options)
---
## Feature 2: Hover Action Menu
### Description
Display a floating toolbar when hovering over elements with quick actions.
### Visual Design
```
┌─────────────────────────────────────┐
│ [⚙️] [📋] [🗑️] [⋮] ← Action menu │
├─────────────────────────────────────┤
│ │
│ Element Content │
│ │
└─────────────────────────────────────┘
```
### Actions
| Icon | Action | Description |
|------|--------|-------------|
| ⚙️ | Settings | Open properties panel for this element |
| 📋 | Duplicate | Clone the element |
| 🗑️ | Delete | Remove the element |
| ⋮ | More | Expand for additional options (move up/down, copy, paste) |
### Components Needed
#### ElementActions.svelte
```typescript
interface Props {
nodeId: string
nodeType: NodeType
position: { x: number; y: number }
onsettings: () => void
onduplicate: () => void
ondelete: () => void
onmoveup: () => void
onmovedown: () => void
}
```
### Behavior
1. Menu appears on element hover (with slight delay)
2. Menu positioned at top-right of element
3. Actions are context-aware (some may be disabled)
4. Menu disappears when mouse leaves element
---
## Feature 3: Drag and Drop System
### Description
Allow elements to be reordered by dragging them to new positions.
### Visual Design
```
Before Drop:
┌─────────────┐
│ Element A │ ← Being dragged (ghost)
└─────────────┘
┌─────────────┐
│ Element B │
└─────────────┘
┌─────────────┐
│ Element C │
└─────────────┘
↓
Drop zone indicator (blue line)
After Drop:
┌─────────────┐
│ Element B │
└─────────────┘
┌─────────────┐
│ Element A │ ← Dropped here
└─────────────┘
┌─────────────┐
│ Element C │
└─────────────┘
```
### Components Needed
#### Draggable.svelte
```typescript
interface Props {
nodeId: string
disabled?: boolean
ondragstart: (nodeId: string, event: DragEvent) => void
ondragend: (nodeId: string, event: DragEvent) => void
}
```
#### DropZone.svelte
```typescript
interface Props {
parentId: string
index: number
acceptedTypes: NodeType[]
ondrop: (draggedId: string, parentId: string, index: number) => void
}
```
### Behavior
1. Click and hold to start drag (with drag handle icon)
2. Element becomes semi-transparent ghost
3. Drop zones appear as blue indicator lines
4. Invalid drop zones shown in red
5. Release to drop at indicated position
6. Escape cancels the drag operation
---
## Feature 4: Visual Feedback System
### Description
Provide clear visual feedback during all interactions.
### Feedback Types
#### Hover State
- Outline brightens
- Action menu appears
- Cursor changes to pointer
#### Selection State
- Solid border (current)
- Resize handles (future)
#### Drag State
- Original element becomes ghost (50% opacity)
- Drag preview follows cursor
- Drop zones highlighted
#### Drop Zone State
- Blue line indicator for valid drops
- Red indicator for invalid drops
- Pulsing animation for active zone
#### Insert Button State
- Fade in on container hover
- Scale up on button hover
- Tooltip showing 'Add [element type]'
---
## Implementation Architecture
### New File Structure
```
src/lib/editor/
├── canvas/
│ ├── Canvas.svelte
│ ├── NodeRenderer.svelte
│ ├── Page.svelte
│ ├── InsertButton.svelte # NEW
│ ├── InsertionPopup.svelte # NEW
│ ├── ElementActions.svelte # NEW
│ ├── DraggableWrapper.svelte # NEW
│ └── DropZone.svelte # NEW
├── toolbar/
│ ├── Toolbar.svelte
│ ├── BlockButton.svelte
│ └── ElementQuickMenu.svelte # NEW
├── stores/
│ ├── drag.ts # NEW - drag state store
│ └── ...
└── Editor.svelte
```
### Store Additions
#### dragStore (new)
```typescript
interface DragState {
isDragging: boolean
draggedNodeId: string | null
draggedNodeType: NodeType | null
dropTargetId: string | null
dropIndex: number | null
isValidDrop: boolean
}
```
### Event Flow Diagram
```mermaid
sequenceDiagram
participant User
participant NodeRenderer
participant ElementActions
participant Editor
participant DocumentStore
User->>NodeRenderer: Hover over element
NodeRenderer->>ElementActions: Show action menu
User->>ElementActions: Click drag handle
ElementActions->>Editor: Start drag
Editor->>DocumentStore: Set drag state
User->>NodeRenderer: Drag over drop zone
NodeRenderer->>Editor: Check valid drop
Editor->>DocumentStore: Update drop target
User->>NodeRenderer: Drop
NodeRenderer->>Editor: Complete drop
Editor->>DocumentStore: Move node
DocumentStore->>NodeRenderer: Re-render
```
---
## Implementation Phases
### Phase 1: Inline Insertion
1. Create InsertButton.svelte component
2. Create InsertionPopup.svelte with element selector
3. Modify NodeRenderer to show insert buttons
4. Wire up insertion logic with correct positioning
### Phase 2: Hover Actions
1. Create ElementActions.svelte component
2. Add hover detection with delay
3. Implement duplicate, delete, settings actions
4. Add move up/down functionality
### Phase 3: Drag and Drop
1. Create drag store for state management
2. Create DraggableWrapper.svelte
3. Create DropZone.svelte
4. Implement drop validation logic
5. Add visual feedback during drag
### Phase 4: Polish
1. Add animations and transitions
2. Implement keyboard shortcuts
3. Add undo/redo support for all operations
4. Mobile touch support (future)
---
## Technical Considerations
### Performance
- Use CSS transforms for drag preview (GPU accelerated)
- Debounce hover events
- Virtualize insertion popups (only one open at a time)
### Accessibility
- Keyboard navigation for action menus
- Focus management during drag
- ARIA labels for all interactive elements
### Browser Compatibility
- Use HTML5 Drag and Drop API
- Fallback for touch devices
- Handle Safari quirks
---
## Files to Modify
### Existing Files
| File | Changes |
|------|---------|
| `src/lib/editor/Editor.svelte` | Add drag state, coordinate drop logic |
| `src/lib/editor/canvas/NodeRenderer.svelte` | Add action menu, insert buttons, drag handlers |
| `src/lib/stores/index.ts` | Export new drag store |
### New Files to Create
| File | Purpose |
|------|---------|
| `src/lib/editor/canvas/InsertButton.svelte` | Inline insertion trigger |
| `src/lib/editor/canvas/InsertionPopup.svelte` | Element type selector |
| `src/lib/editor/canvas/ElementActions.svelte` | Hover action toolbar |
| `src/lib/editor/canvas/DropZone.svelte` | Drop target indicator |
| `src/lib/stores/drag.ts` | Drag state management |
---
## Success Criteria
1. ✅ Users can insert elements at specific positions using inline buttons
2. ✅ Hover menus provide quick access to common actions
3. ✅ Drag and drop works smoothly with visual feedback
4. ✅ All operations respect hierarchy constraints
5. ✅ All operations are undoable
6. ✅ Keyboard users can perform all actions

Powered by TurnKey Linux.