✓ Data loaded: {pasteDataSummary.format} ({pasteDataSummary.size.toLocaleString()} chars)
) : (
// Expanded State
{error && (
Invalid Data: {error}
)}
Auto-detects format
)
)}
```
### Open Tab (CONSISTENT WITH TABLE EDITOR)
**IMPORTANT:** Use `tool-input` class and auto-load on file selection!
```jsx
{activeTab === 'open' && (
🔒 Privacy: Your data stays in your browser. We don't store or upload anything - just help you open, edit, and export your files locally.
)}
```
### Parse Button Behavior
- **Valid data**: Collapse input, show summary, display editor
- **Invalid data**: Show error, keep input expanded, hide editor
- **Button disabled**: When no data or invalid format
---
## Main Editor Section
### Structure
```jsx
{(activeTab !== 'create' || createNewCompleted) && (
{/* Editor Header */}
Your Editor Name
{/* Optional: Settings or Actions */}
{/* Editor Content */}
{/* Your editor implementation */}
)}
```
### Fullscreen Support (Optional)
If your editor supports fullscreen:
```jsx
const [isFullscreen, setIsFullscreen] = useState(false);
```
---
## Data Loss Prevention (CRITICAL!)
### Confirmation Modal for Tab Changes
**IMPORTANT:** Always confirm before clearing user data when switching input methods!
### When to Show Confirmation
- User has entered/loaded data
- User tries to switch to a different input tab
- User tries to use Create New buttons (Start Empty/Load Sample)
### Implementation Pattern
#### 1. Check if User Has Data
```jsx
const hasUserData = () => {
// Check if there's meaningful data
return Object.keys(editorData).length > 0;
};
const hasModifiedData = () => {
// Check if data has been modified from initial state
// Return false for empty or sample data
// Return true for user-entered data
};
```
#### 2. Handle Tab Change with Confirmation
```jsx
const handleTabChange = (newTab) => {
if (hasModifiedData() && activeTab !== newTab) {
setPendingTabChange(newTab);
setShowInputChangeModal(true);
} else {
setActiveTab(newTab);
}
};
```
#### 3. Confirmation Modal Component
```jsx
const InputChangeConfirmationModal = ({
editorData,
currentMethod,
newMethod,
onConfirm,
onCancel
}) => {
const getMethodName = (method) => {
switch (method) {
case 'create': return 'Create New';
case 'create_empty': return 'Start Empty';
case 'create_sample': return 'Load Sample';
case 'url': return 'URL Import';
case 'paste': return 'Paste Data';
case 'open': return 'File Upload';
default: return method;
}
};
return (
{/* Header - Amber Warning */}
Confirm Action
{newMethod === 'create_empty' || newMethod === 'create_sample'
? `Using ${getMethodName(newMethod)} will clear your current data.`
: `Switching from ${getMethodName(currentMethod)} to ${getMethodName(newMethod)} will clear your current data.`
}
{/* Body - Show Current Data Summary */}
You currently have:
{/* List current data items */}
• [Data summary item 1]
• [Data summary item 2]
• [Data summary item 3]
{/* Blue Tip Box */}
Tip: Consider downloading your current data as JSON before proceeding to save your work.
{/* Footer - Action Buttons */}
);
};
```
#### 4. Usage in Component
```jsx
{/* Confirmation Modal */}
{showInputChangeModal && (
{
clearAllData();
setActiveTab(pendingTabChange);
setShowInputChangeModal(false);
setPendingTabChange(null);
}}
onCancel={() => {
setShowInputChangeModal(false);
setPendingTabChange(null);
}}
/>
)}
```
### Visual Design
- **Header**: Amber background with AlertTriangle icon
- **Body**: White/dark background with data summary
- **Tip Box**: Blue background with save suggestion
- **Footer**: Gray background with Cancel and Warning buttons
- **Warning Button**: Amber color with AlertTriangle icon
### Key Points
1. **Always show** when user has meaningful data
2. **List specific data** user will lose (not generic message)
3. **Suggest saving** before proceeding (blue tip box)
4. **Clear button text** - "Switch & Clear Data" (not ambiguous)
5. **z-50** to appear above everything
6. **Amber theme** for warning (not red, not blue)
---
## State Management
### Required State Variables
```jsx
// Tab management
const [activeTab, setActiveTab] = useState('create');
const [createNewCompleted, setCreateNewCompleted] = useState(false);
// Input data
const [inputText, setInputText] = useState('');
const [url, setUrl] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
// Collapse states
const [pasteCollapsed, setPasteCollapsed] = useState(false);
const [pasteDataSummary, setPasteDataSummary] = useState(null);
const [exportExpanded, setExportExpanded] = useState(false);
const [usageTipsExpanded, setUsageTipsExpanded] = useState(false);
// Confirmation modals
const [showInputChangeModal, setShowInputChangeModal] = useState(false);
const [pendingTabChange, setPendingTabChange] = useState(null);
// Refs
const fileInputRef = useRef(null);
// Your editor-specific state
const [editorData, setEditorData] = useState(null);
```
### Tab Change with Confirmation
```jsx
const handleTabChange = (newTab) => {
if (hasModifiedData() && activeTab !== newTab) {
setPendingTabChange(newTab);
setShowInputChangeModal(true);
} else {
setActiveTab(newTab);
}
};
const confirmInputChange = () => {
clearAllData();
setActiveTab(pendingTabChange);
setShowInputChangeModal(false);
setPendingTabChange(null);
};
```
---
## Error Handling
### Parse Data with Error Handling
```jsx
const handleParseData = () => {
try {
const parsed = parseYourData(inputText);
if (parsed.valid) {
setEditorData(parsed.data);
setError('');
setCreateNewCompleted(true);
setPasteDataSummary({
format: parsed.format,
size: inputText.length,
items: parsed.data.length
});
setPasteCollapsed(true);
} else {
// Show error, keep input expanded
setError(parsed.error || 'Invalid data format');
setPasteCollapsed(false);
}
} catch (err) {
setError(err.message || 'Failed to parse data');
setPasteCollapsed(false);
}
};
```
### Error Display
```jsx
{error && (
{error}
)}
```
---
## Complete Example
See existing editors for complete implementations:
- **Object Editor** (`/src/pages/ObjectEditor.js`) - Best for JSON/structured data
- **Table Editor** (`/src/pages/TableEditor.js`) - Best for tabular data
- **Invoice Editor** (`/src/pages/InvoiceEditor.js`) - Best for form-based editors
---
## Checklist for New Editor Tools
### Input Section
- [ ] All 4 tabs implemented (Create New, URL, Paste, Open)
- [ ] URL tab has inline button (not below)
- [ ] Open tab uses `tool-input` class
- [ ] Open tab auto-loads on file selection
- [ ] Paste tab has parse button on bottom-right
- [ ] Paste tab collapses after successful parse
- [ ] Error handling shows errors and keeps input expanded
### Main Editor
- [ ] Only shows after data is loaded
- [ ] Has proper header with icon
- [ ] Implements your editor functionality
- [ ] Optional: Fullscreen support with proper z-index
### Export Section
- [ ] Collapsible by default
- [ ] Header shows summary info
- [ ] Chevron icon indicates state
- [ ] Hover effect on header
- [ ] Export tabs if multiple formats
### Usage Tips
- [ ] Collapsible by default
- [ ] 💡 emoji in header
- [ ] Comprehensive tips organized by category
- [ ] Includes Input Methods, Editing Features, Export Options, Data Privacy
### State & Behavior
- [ ] Tab change confirmation when data exists
- [ ] Proper error handling
- [ ] Loading states for async operations
- [ ] Dark mode support
### Styling
- [ ] Uses Tailwind CSS classes
- [ ] Consistent with other editors
- [ ] Responsive design
- [ ] Proper spacing and layout
---
## Common Patterns
### Button Styling
```jsx
// Primary action button
className="bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white font-medium px-4 py-2 rounded-md transition-colors flex-shrink-0"
// Secondary button
className="bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300 px-4 py-2 rounded-md transition-colors"
```
### Input Styling
```jsx
// Standard input
className="tool-input w-full"
// Or explicit:
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
```
### Card/Section Styling
```jsx
className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"
```
---
## Import Requirements
### Required Icons (from lucide-react)
```jsx
import {
Plus, // Create New
Globe, // URL
FileText, // Paste
Upload, // Open
Download, // Export
Edit3, // Editor
AlertTriangle, // Errors
ChevronUp, // Collapse indicators
ChevronDown, // Collapse indicators
// Add your specific icons
} from 'lucide-react';
```
### Required Components
```jsx
import ToolLayout from '../components/ToolLayout';
import CodeMirrorEditor from '../components/CodeMirrorEditor';
import CodeEditor from '../components/CodeEditor'; // For read-only code display
```
---
## Best Practices
1. **Consistency First**: Always follow existing patterns before innovating
2. **User Data Safety**: Always confirm before clearing user data
3. **Error Messages**: Be specific and helpful
4. **Loading States**: Show loading indicators for async operations
5. **Accessibility**: Use semantic HTML and proper ARIA labels
6. **Dark Mode**: Test in both light and dark modes
7. **Mobile**: Ensure responsive design works on small screens
8. **Performance**: Lazy load heavy components when possible
---
## Testing Your Editor
1. **Input Methods**: Test all 4 tabs work correctly
2. **Parse Valid Data**: Ensure data loads and displays
3. **Parse Invalid Data**: Ensure errors show and input stays expanded
4. **Tab Switching**: Confirm data loss prevention works
5. **Export**: Test all export formats
6. **Collapse/Expand**: Test all collapsible sections
7. **Dark Mode**: Toggle and verify styling
8. **Mobile**: Test on small screen sizes
9. **Edge Cases**: Empty data, very large data, special characters
---
## Questions or Issues?
Refer to existing editors:
- Object Editor: JSON/PHP serialized data handling
- Table Editor: Tabular data with inline editing
- Invoice Editor: Form-based data entry
Follow these patterns and your new editor will be consistent with the rest of the application!