feat: implement professional modal editing forms (Phase 1.2)
MAJOR UX IMPROVEMENT: Replace basic prompt() with professional forms
New Features:
- Professional modal overlays with backdrop and ESC/click-outside cancel
- Dynamic form generation based on content type and HTML element
- Smart field detection: H1-H6→text, P→textarea, A→link with URL
- Mobile-responsive form positioning and widths
- Complete CSS styling with focus states and transitions
- Proper save/cancel event handling
Technical Implementation:
- Created lib/src/ui/form-renderer.js with modern ES6+ modules
- Integrated into core editor.js with form renderer instance
- Support for text, textarea, markdown, and link field types
- XSS protection with HTML escaping
- Responsive design: mobile-first form sizing
- Professional styling matching prototype quality
Before: Basic browser prompt() for all editing
After: Content-aware professional modal forms
This brings the library from proof-of-concept to professional-grade
editing experience, closing the major UX gap with the archived prototype.
Phase 1.2 ✅ COMPLETED - Next: Authentication system (Phase 1.1)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { InsertrFormRenderer } from '../ui/form-renderer.js';
|
||||
|
||||
/**
|
||||
* InsertrEditor - Visual editing functionality
|
||||
*/
|
||||
@@ -6,6 +8,7 @@ export class InsertrEditor {
|
||||
this.core = core;
|
||||
this.options = options;
|
||||
this.isActive = false;
|
||||
this.formRenderer = new InsertrFormRenderer();
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -54,29 +57,64 @@ export class InsertrEditor {
|
||||
}
|
||||
|
||||
openEditor(meta) {
|
||||
const { contentId, contentType, element } = meta;
|
||||
const currentContent = element.textContent.trim();
|
||||
const { element } = meta;
|
||||
const currentContent = this.extractCurrentContent(element);
|
||||
|
||||
// For now, use a simple prompt (will be replaced with proper modal)
|
||||
const newContent = prompt(
|
||||
`Edit ${contentType} content (ID: ${contentId}):`,
|
||||
currentContent
|
||||
// Show professional form instead of prompt
|
||||
this.formRenderer.showEditForm(
|
||||
meta,
|
||||
currentContent,
|
||||
(formData) => this.handleSave(meta, formData),
|
||||
() => this.handleCancel(meta)
|
||||
);
|
||||
}
|
||||
|
||||
extractCurrentContent(element) {
|
||||
// For links, extract both text and URL
|
||||
if (element.tagName.toLowerCase() === 'a') {
|
||||
return {
|
||||
text: element.textContent.trim(),
|
||||
url: element.getAttribute('href') || ''
|
||||
};
|
||||
}
|
||||
|
||||
if (newContent !== null && newContent !== currentContent) {
|
||||
this.updateContent(meta, newContent);
|
||||
// For other elements, just return text content
|
||||
return element.textContent.trim();
|
||||
}
|
||||
|
||||
handleSave(meta, formData) {
|
||||
console.log('💾 Saving content:', meta.contentId, formData);
|
||||
|
||||
// Update element content based on type
|
||||
this.updateElementContent(meta.element, formData);
|
||||
|
||||
// Close form
|
||||
this.formRenderer.closeForm();
|
||||
|
||||
// TODO: Save to backend API
|
||||
console.log(`✅ Content saved:`, meta.contentId, formData);
|
||||
}
|
||||
|
||||
handleCancel(meta) {
|
||||
console.log('❌ Edit cancelled:', meta.contentId);
|
||||
}
|
||||
|
||||
updateElementContent(element, formData) {
|
||||
if (element.tagName.toLowerCase() === 'a') {
|
||||
// Update link element
|
||||
if (formData.text !== undefined) {
|
||||
element.textContent = formData.text;
|
||||
}
|
||||
if (formData.url !== undefined) {
|
||||
element.setAttribute('href', formData.url);
|
||||
}
|
||||
} else {
|
||||
// Update text content
|
||||
element.textContent = formData.text || '';
|
||||
}
|
||||
}
|
||||
|
||||
updateContent(meta, newContent) {
|
||||
const { element } = meta;
|
||||
|
||||
// Update the element content
|
||||
element.textContent = newContent;
|
||||
|
||||
// TODO: Save to backend API
|
||||
console.log(`💾 Content updated:`, meta.contentId, newContent);
|
||||
}
|
||||
// Legacy method - now handled by handleSave and updateElementContent
|
||||
|
||||
addEditorStyles() {
|
||||
const styles = `
|
||||
|
||||
Reference in New Issue
Block a user