- Move scripts/ to lib/scripts/ and convert to ESM modules - Consolidate dependencies: add live-server to lib/package.json - Remove root package.json and node_modules split - Preserve CLI integration via existing rebuild-library.sh - Add development quickstart guide for new unified workflow - Clean up outdated file references and duplicate assets
154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
import { InsertrFormRenderer } from '../ui/form-renderer.js';
|
|
|
|
/**
|
|
* InsertrEditor - Visual editing functionality
|
|
*/
|
|
export class InsertrEditor {
|
|
constructor(core, auth, options = {}) {
|
|
this.core = core;
|
|
this.auth = auth;
|
|
this.options = options;
|
|
this.isActive = false;
|
|
this.formRenderer = new InsertrFormRenderer();
|
|
}
|
|
|
|
start() {
|
|
if (this.isActive) return;
|
|
|
|
console.log('🚀 Starting Insertr Editor');
|
|
this.isActive = true;
|
|
|
|
// Add editor styles
|
|
this.addEditorStyles();
|
|
|
|
// Initialize all enhanced elements
|
|
const elements = this.core.getAllElements();
|
|
console.log(`📝 Found ${elements.length} editable elements`);
|
|
|
|
elements.forEach(meta => this.initializeElement(meta));
|
|
}
|
|
|
|
initializeElement(meta) {
|
|
const { element, contentId, contentType } = meta;
|
|
|
|
// Add visual indicators
|
|
element.style.cursor = 'pointer';
|
|
element.style.position = 'relative';
|
|
|
|
// Add interaction handlers
|
|
this.addHoverEffects(element);
|
|
this.addClickHandler(element, meta);
|
|
}
|
|
|
|
addHoverEffects(element) {
|
|
element.addEventListener('mouseenter', () => {
|
|
element.classList.add('insertr-editing-hover');
|
|
});
|
|
|
|
element.addEventListener('mouseleave', () => {
|
|
element.classList.remove('insertr-editing-hover');
|
|
});
|
|
}
|
|
|
|
addClickHandler(element, meta) {
|
|
element.addEventListener('click', (e) => {
|
|
// Only allow editing if authenticated and in edit mode
|
|
if (!this.auth.isAuthenticated() || !this.auth.isEditMode()) {
|
|
return; // Let normal click behavior happen
|
|
}
|
|
|
|
e.preventDefault();
|
|
this.openEditor(meta);
|
|
});
|
|
}
|
|
|
|
openEditor(meta) {
|
|
const { element } = meta;
|
|
const currentContent = this.extractCurrentContent(element);
|
|
|
|
// 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') || ''
|
|
};
|
|
}
|
|
|
|
// 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 || '';
|
|
}
|
|
}
|
|
|
|
// Legacy method - now handled by handleSave and updateElementContent
|
|
|
|
addEditorStyles() {
|
|
const styles = `
|
|
.insertr-editing-hover {
|
|
outline: 2px dashed #007cba !important;
|
|
outline-offset: 2px !important;
|
|
background-color: rgba(0, 124, 186, 0.05) !important;
|
|
}
|
|
|
|
.insertr:hover::after {
|
|
content: "✏️ " attr(data-content-type);
|
|
position: absolute;
|
|
top: -25px;
|
|
left: 0;
|
|
background: #007cba;
|
|
color: white;
|
|
padding: 2px 6px;
|
|
font-size: 11px;
|
|
border-radius: 3px;
|
|
white-space: nowrap;
|
|
z-index: 1000;
|
|
font-family: monospace;
|
|
}
|
|
`;
|
|
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.type = 'text/css';
|
|
styleSheet.innerHTML = styles;
|
|
document.head.appendChild(styleSheet);
|
|
}
|
|
} |