ngx-xtroedge-cms 1.3.11 → 1.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.global.js +4 -4
- package/dist/index.js +23 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/styles.ts","../src/xtroedge-cms.ts"],"sourcesContent":["export { XtroedgeCMS } from './xtroedge-cms';\r\nexport type {\r\n XtroedgeCmsConfig,\r\n PageTextEntry,\r\n WebPageContent,\r\n EditHistoryEntry,\r\n} from './types';\r\n\r\n// ===== AUTO-INIT =====\r\n// Automatically initializes CMS when the script loads.\r\n// No manual code needed - just install the package.\r\n// To pass config, set window.__XTROEDGE_CMS_CONFIG__ before loading.\r\nimport { XtroedgeCMS } from './xtroedge-cms';\r\n\r\nfunction boot() {\r\n XtroedgeCMS.autoInit();\r\n}\r\n\r\nif (typeof window !== 'undefined') {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', boot);\r\n } else {\r\n // DOM already ready (script loaded async/defer or after DOMContentLoaded)\r\n boot();\r\n }\r\n}\r\n","export const CMS_STYLES = `\r\n/* ===== XTROEDGE CMS ===== */\r\n\r\n/* LOADER */\r\n.lcms-loader-overlay {\r\n position: fixed; inset: 0; z-index: 10003;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.45);\r\n backdrop-filter: blur(12px) saturate(1.4);\r\n -webkit-backdrop-filter: blur(12px) saturate(1.4);\r\n}\r\n.lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }\r\n.lcms-orbit-loader { position: relative; width: 90px; height: 90px; }\r\n.lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }\r\n.lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }\r\n.lcms-orbit-2 { inset: 10px; border-right-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); animation: lcmsSpin 3.2s linear infinite reverse; }\r\n.lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }\r\n.lcms-particle {\r\n position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;\r\n box-shadow: 0 0 12px 3px currentColor;\r\n}\r\n.lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }\r\n.lcms-orbit-2 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }\r\n.lcms-orbit-3 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); top: auto; bottom: -4px; }\r\n.lcms-core-glow {\r\n position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);\r\n border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);\r\n animation: lcmsPulse 2s ease-in-out infinite;\r\n}\r\n.lcms-core {\r\n position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);\r\n border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));\r\n box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);\r\n}\r\n.lcms-loader-text {\r\n font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;\r\n color: rgba(255,255,255,0.5); letter-spacing: 4px; text-transform: uppercase;\r\n animation: lcmsBreath 2.5s ease-in-out infinite;\r\n}\r\n@keyframes lcmsSpin { to { transform: rotate(360deg); } }\r\n@keyframes lcmsPulse { 0%,100% { transform: translate(-50%,-50%) scale(1); opacity: 0.5; } 50% { transform: translate(-50%,-50%) scale(1.8); opacity: 0.2; } }\r\n@keyframes lcmsBreath { 0%,100% { letter-spacing: 4px; opacity: 0.5; } 50% { letter-spacing: 6px; opacity: 0.8; } }\r\n\r\n/* TOAST */\r\n.lcms-toast {\r\n position: fixed; top: 24px; left: 50%; transform: translateX(-50%); z-index: 10004;\r\n padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;\r\n font-family: system-ui, -apple-system, sans-serif; color: white;\r\n display: flex; align-items: center; gap: 8px;\r\n box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);\r\n animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;\r\n}\r\n.lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }\r\n.lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }\r\n@keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }\r\n@keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }\r\n\r\n/* FAB */\r\n.lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }\r\n.lcms-fab-btn {\r\n width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);\r\n background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;\r\n backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);\r\n cursor: grab; display: flex; align-items: center; justify-content: center;\r\n box-shadow: 0 4px 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.3), inset 0 1px 0 rgba(255,255,255,0.15);\r\n transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;\r\n}\r\n.lcms-fab-btn:not(.lcms-fab-active) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); }\r\n.lcms-fab-btn.lcms-fab-active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); box-shadow: 0 4px 24px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), 0 0 16px rgba(var(--lcms-primary-rgb, 0,200,83),0.2), inset 0 1px 0 rgba(255,255,255,0.2); }\r\n.lcms-fab-btn:hover { transform: scale(1.08); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); box-shadow: 0 6px 28px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), inset 0 1px 0 rgba(255,255,255,0.2); }\r\n.lcms-badge {\r\n position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;\r\n font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;\r\n display: flex; align-items: center; justify-content: center; border: 2px solid white;\r\n}\r\n\r\n/* PANEL */\r\n.lcms-panel {\r\n background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);\r\n border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);\r\n color: white; font-family: system-ui, -apple-system, sans-serif;\r\n animation: lcmsPanelIn 0.25s ease; position: absolute;\r\n}\r\n@keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }\r\n\r\n/* SITE IDENTIFIER */\r\n.lcms-site-id {\r\n display: flex; align-items: center; gap: 5px;\r\n font-size: 10px; color: rgba(255,255,255,0.4);\r\n padding: 0 0 8px; margin-bottom: 8px;\r\n border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);\r\n font-family: system-ui, -apple-system, sans-serif;\r\n letter-spacing: 0.3px;\r\n}\r\n.lcms-site-id-icon { font-size: 12px; opacity: 0.7; }\r\n.lcms-site-id-text {\r\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;\r\n font-weight: 500;\r\n}\r\n\r\n/* BRANDING */\r\n.lcms-branding {\r\n display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;\r\n border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;\r\n cursor: pointer; transition: opacity 0.2s; user-select: none;\r\n}\r\n.lcms-branding:hover { opacity: 0.8; }\r\n.lcms-branding-logo {\r\n width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n display: flex; align-items: center; justify-content: center;\r\n}\r\n.lcms-branding-text {\r\n font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;\r\n}\r\n.lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }\r\n\r\n.lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }\r\n.lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }\r\n.lcms-toggle input { display: none; }\r\n.lcms-toggle-slider {\r\n width: 36px; height: 20px; border-radius: 10px; position: relative;\r\n background: rgba(255,255,255,0.15); transition: background 0.25s;\r\n}\r\n.lcms-toggle-slider::after {\r\n content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;\r\n top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;\r\n}\r\n.lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }\r\n.lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }\r\n.lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }\r\n.lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }\r\n.lcms-lang-switch { margin-left: auto; position: relative; }\r\n.lcms-lang-select { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.15); border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.4); border-radius: 6px; color: white; padding: 3px 24px 3px 8px; font-size: 11px; font-weight: 600; cursor: pointer; appearance: none; -webkit-appearance: none; outline: none; transition: all 0.2s; }\r\n.lcms-lang-select:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); }\r\n.lcms-lang-select:focus { border-color: var(--lcms-primary, #00C853); }\r\n.lcms-lang-select option { background: #1a1a2e; color: white; }\r\n.lcms-lang-arrow { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); pointer-events: none; color: rgba(255,255,255,0.6); font-size: 10px; }\r\n.lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }\r\n.lcms-close-btn:hover { color: white; }\r\n.lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }\r\n\r\n.lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }\r\n.lcms-icon-btn {\r\n width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);\r\n background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;\r\n display: flex; align-items: center; justify-content: center; transition: all 0.2s;\r\n}\r\n.lcms-icon-btn:hover:not(:disabled) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }\r\n.lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }\r\n\r\n/* COLOR THEME PICKER */\r\n.lcms-theme-row {\r\n display: flex; align-items: center; gap: 8px; margin-bottom: 12px;\r\n padding: 6px 0;\r\n}\r\n.lcms-theme-label {\r\n font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);\r\n text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;\r\n}\r\n.lcms-theme-colors {\r\n display: flex; align-items: center; gap: 5px; flex-wrap: wrap;\r\n}\r\n.lcms-theme-swatch {\r\n width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;\r\n cursor: pointer; transition: all 0.2s; position: relative;\r\n}\r\n.lcms-theme-swatch:hover { transform: scale(1.15); }\r\n.lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }\r\n.lcms-theme-custom {\r\n width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);\r\n cursor: pointer; overflow: hidden; position: relative;\r\n}\r\n.lcms-theme-custom input {\r\n position: absolute; inset: -4px; width: 28px; height: 28px; border: none;\r\n background: transparent; cursor: pointer; opacity: 0;\r\n}\r\n.lcms-theme-custom-preview {\r\n width: 100%; height: 100%; border-radius: 50%;\r\n background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);\r\n}\r\n\r\n.lcms-history-btn {\r\n width: 100%; padding: 7px 12px; border-radius: 8px;\r\n border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);\r\n color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;\r\n display: flex; align-items: center; justify-content: center; gap: 6px;\r\n transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-history-btn:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.18); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }\r\n.lcms-history-btn.active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: var(--lcms-primary, #00C853); border-style: solid; color: white; }\r\n\r\n.lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }\r\n.lcms-history-title { font-size: 11px; font-weight: 700; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; }\r\n.lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }\r\n.lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }\r\n.lcms-history-list::-webkit-scrollbar { width: 4px; }\r\n.lcms-history-list::-webkit-scrollbar-track { background: transparent; }\r\n.lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }\r\n.lcms-history-item {\r\n width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);\r\n border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;\r\n cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-history-item:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.15); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); }\r\n.lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }\r\n.lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }\r\n.lcms-history-lang { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }\r\n\r\n.lcms-actions { display: flex; flex-direction: column; gap: 6px; }\r\n.lcms-actions button {\r\n width: 100%; padding: 9px 14px; border-radius: 8px; font-size: 12px; font-weight: 600;\r\n cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;\r\n font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }\r\n.lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }\r\n.lcms-btn-save:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }\r\n.lcms-btn-publish { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); color: white; }\r\n.lcms-btn-publish:hover { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); filter: brightness(1.1); }\r\n.lcms-btn-publish:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }\r\n.lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25) !important; }\r\n.lcms-btn-cancel:hover { color: white; border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5) !important; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08); }\r\n.lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }\r\n.lcms-btn-logout { background: rgba(244,67,54,0.12); color: rgba(244,67,54,0.85); border: 1px solid rgba(244,67,54,0.25) !important; margin-top: 4px; }\r\n.lcms-btn-logout:hover { background: rgba(244,67,54,0.2); color: #f44336; border-color: rgba(244,67,54,0.5) !important; }\r\n\r\n.lcms-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }\r\n\r\n/* IMAGE UPLOAD OVERLAY */\r\n.lcms-img-upload-overlay {\r\n position: fixed; inset: 0; z-index: 10005;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);\r\n}\r\n.lcms-img-upload-content {\r\n display: flex; flex-direction: column; align-items: center; gap: 16px;\r\n color: white; font-family: system-ui, -apple-system, sans-serif;\r\n font-size: 13px; font-weight: 600;\r\n}\r\n.lcms-spinner-lg { width: 36px; height: 36px; border: 3px solid rgba(255,255,255,0.2); border-top-color: var(--lcms-primary, #00C853); border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }\r\n\r\n/* LOGIN MODAL */\r\n.lcms-login-overlay {\r\n position: fixed; inset: 0; z-index: 10010;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.75);\r\n backdrop-filter: blur(16px) saturate(1.4);\r\n -webkit-backdrop-filter: blur(16px) saturate(1.4);\r\n font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-login-box {\r\n background: #13151a; border: 1px solid rgba(255,255,255,0.1);\r\n border-radius: 16px; padding: 36px 32px; width: 340px;\r\n box-shadow: 0 24px 60px rgba(0,0,0,0.6);\r\n}\r\n.lcms-login-logo {\r\n display: flex; align-items: center; justify-content: center;\r\n gap: 8px; margin-bottom: 24px;\r\n}\r\n.lcms-login-logo-icon {\r\n width: 32px; height: 32px; border-radius: 8px;\r\n background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n display: flex; align-items: center; justify-content: center;\r\n}\r\n.lcms-login-logo-text { color: white; font-size: 15px; font-weight: 700; letter-spacing: 0.5px; }\r\n.lcms-login-title { color: white; font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 6px; }\r\n.lcms-login-sub { color: rgba(255,255,255,0.4); font-size: 12px; text-align: center; margin-bottom: 24px; }\r\n.lcms-login-field { margin-bottom: 14px; }\r\n.lcms-login-label { display: block; color: rgba(255,255,255,0.6); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 6px; }\r\n.lcms-login-input {\r\n width: 100%; box-sizing: border-box;\r\n background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12);\r\n border-radius: 8px; padding: 10px 12px;\r\n color: white; font-size: 13px; font-family: inherit; outline: none;\r\n transition: border-color 0.2s;\r\n}\r\n.lcms-login-input:focus { border-color: var(--lcms-primary, #00C853); }\r\n.lcms-login-input::placeholder { color: rgba(255,255,255,0.25); }\r\n.lcms-login-btn {\r\n width: 100%; padding: 11px; margin-top: 6px; border: none; border-radius: 8px; cursor: pointer;\r\n background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n color: white; font-size: 13px; font-weight: 700; font-family: inherit;\r\n letter-spacing: 0.3px; transition: filter 0.2s;\r\n}\r\n.lcms-login-btn:hover { filter: brightness(1.1); }\r\n.lcms-login-btn:disabled { opacity: 0.6; cursor: not-allowed; }\r\n.lcms-login-error {\r\n background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.3);\r\n border-radius: 8px; padding: 9px 12px; color: #f87171;\r\n font-size: 12px; text-align: center; margin-top: 12px; display: none;\r\n}\r\n.lcms-login-error.visible { display: block; }\r\n\r\n/* HIDDEN ELEMENTS */\r\n.lcms-hidden { display: none !important; }\r\n`;\r\n","import { CMS_STYLES } from './styles';\r\nimport type {\r\n XtroedgeCmsConfig, PageTextEntry, WebPageContent,\r\n EditHistoryEntry, ManagedElementInfo, ManagedImageInfo\r\n} from './types';\r\n\r\n// ===== SVG Icons =====\r\nconst ICON = {\r\n edit: '<svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>',\r\n close: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>',\r\n undo: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>',\r\n redo: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"23 4 23 10 17 10\"/><path d=\"M20.49 15a9 9 0 1 1-2.13-9.36L23 10\"/></svg>',\r\n history: '<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/></svg>',\r\n save: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z\"/><polyline points=\"17 21 17 13 7 13 7 21\"/><polyline points=\"7 3 7 8 15 8\"/></svg>',\r\n publish: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"17 1 21 5 17 9\"/><path d=\"M3 11V9a4 4 0 0 1 4-4h14\"/></svg>',\r\n image: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>',\r\n check: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6L9 17l-5-5\"/></svg>',\r\n error: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>',\r\n logout: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/><polyline points=\"16 17 21 12 16 7\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/></svg>',\r\n};\r\n\r\n// ===== IndexedDB constants =====\r\nconst DB_NAME = 'xtroedge_cms_history';\r\nconst STORE_NAME = 'history';\r\n\r\n// ===== Default editable tags =====\r\nconst DEFAULT_EDITABLE_TAGS = [\r\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\r\n 'p', 'span', 'b', 'strong', 'i', 'em',\r\n 'a', 'button', 'li', 'label', 'small', 'blockquote', 'td', 'th',\r\n 'div', 'header', 'footer',\r\n];\r\n\r\nexport class XtroedgeCMS {\r\n // ===== Config =====\r\n private config: XtroedgeCmsConfig;\r\n private containerSelector: string;\r\n private editableTags: string[];\r\n private languages: string[];\r\n private defaultLanguage: string;\r\n private highlightColor: string;\r\n private brandingEl: HTMLElement | null = null;\r\n private historyRetentionMs: number;\r\n private siteIdentifier = '';\r\n private siteIdEl: HTMLElement | null = null;\r\n private loginModalEl: HTMLElement | null = null;\r\n private pendingEditMode = false; // edit=true was requested but token missing\r\n\r\n // ===== State =====\r\n private editMode = false;\r\n private currentLang = 'en';\r\n private pageTexts: { [key: string]: PageTextEntry } = {};\r\n private pageImages: { [key: string]: string } = {};\r\n private originalTexts: { [key: string]: PageTextEntry } = {};\r\n private originalImages: { [key: string]: string } = {};\r\n private unsavedChanges = 0;\r\n private isSaving = false;\r\n private isPublishing = false;\r\n private loading = false;\r\n private canUndo = false;\r\n private canRedo = false;\r\n private showHistory = false;\r\n private historyList: EditHistoryEntry[] = [];\r\n private isOpen = false;\r\n private isEditAllowed = false;\r\n private imageUploading = false;\r\n private toastMessage = '';\r\n private toastType: 'success' | 'error' = 'success';\r\n\r\n // ===== Undo/Redo =====\r\n private undoStack: string[] = [];\r\n private redoStack: string[] = [];\r\n private dirtyKeys = new Set<string>();\r\n private dirtyImageKeys = new Set<string>();\r\n private registeredKeys = new Set<string>();\r\n\r\n // ===== DOM =====\r\n private managedElements = new Map<HTMLElement, ManagedElementInfo>();\r\n private managedImages = new Map<HTMLImageElement, ManagedImageInfo>();\r\n private autoDetectedElements = new Set<HTMLElement>();\r\n private observer: MutationObserver | null = null;\r\n private scanTimeout: ReturnType<typeof setTimeout> | null = null;\r\n private activeImageEl: HTMLImageElement | null = null;\r\n private imageCtxMenu: HTMLElement | null = null;\r\n\r\n // ===== Navigation =====\r\n private currentSlug = '';\r\n private currentTitle = '';\r\n private initialized = false;\r\n private origPushState: typeof history.pushState | null = null;\r\n private origReplaceState: typeof history.replaceState | null = null;\r\n\r\n // ===== UI Elements =====\r\n private styleEl: HTMLStyleElement | null = null;\r\n private rootEl: HTMLElement | null = null;\r\n private loaderEl: HTMLElement | null = null;\r\n private toastEl: HTMLElement | null = null;\r\n private fabEl: HTMLElement | null = null;\r\n private fabBtn: HTMLButtonElement | null = null;\r\n private badgeEl: HTMLElement | null = null;\r\n private panelEl: HTMLElement | null = null;\r\n private editToggle: HTMLInputElement | null = null;\r\n private langSwitchEl: HTMLElement | null = null;\r\n private changesInfoEl: HTMLElement | null = null;\r\n private undoBtn: HTMLButtonElement | null = null;\r\n private redoBtn: HTMLButtonElement | null = null;\r\n private historyBtnEl: HTMLButtonElement | null = null;\r\n private historyPanelEl: HTMLElement | null = null;\r\n private historyListEl: HTMLElement | null = null;\r\n private saveBtn: HTMLButtonElement | null = null;\r\n private publishBtn: HTMLButtonElement | null = null;\r\n\r\n private actionsEl: HTMLElement | null = null;\r\n private editModeContent: HTMLElement | null = null;\r\n private fileInput: HTMLInputElement | null = null;\r\n private imgOverlay: HTMLElement | null = null;\r\n\r\n // ===== FAB Drag =====\r\n private posX = 20;\r\n private posY = 20;\r\n private isDragging = false;\r\n private dragStartX = 0;\r\n private dragStartY = 0;\r\n private startPosX = 0;\r\n private startPosY = 0;\r\n private hasMoved = false;\r\n\r\n // ===== Timers =====\r\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n // ===== IndexedDB =====\r\n private db: IDBDatabase | null = null;\r\n\r\n // ===== Bound handlers =====\r\n private boundMouseMove: (e: MouseEvent) => void;\r\n private boundMouseUp: () => void;\r\n private boundTouchMove: (e: TouchEvent) => void;\r\n private boundTouchEnd: () => void;\r\n private boundPopState: () => void;\r\n private boundHashChange: () => void;\r\n\r\n // ===== i18n cache =====\r\n private translationCache = new Map<string, string>();\r\n\r\n constructor(config?: XtroedgeCmsConfig) {\r\n this.config = config || {};\r\n this.containerSelector = this.config.containerSelector || '';\r\n this.editableTags = (this.config.editableTags || DEFAULT_EDITABLE_TAGS).map(t => t.toLowerCase());\r\n this.languages = this.config.languages || ['en'];\r\n this.defaultLanguage = this.config.defaultLanguage || this.languages[0] || 'en';\r\n this.highlightColor = this.config.highlightColor || '#00C853';\r\n this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1000;\r\n this.currentLang = this.defaultLanguage;\r\n this.siteIdentifier = this.resolveSiteIdentifier();\r\n\r\n // Load persisted theme color from localStorage\r\n const savedColor = localStorage.getItem('xtroedge_theme_color');\r\n if (savedColor) this.highlightColor = savedColor;\r\n\r\n // Bind handlers\r\n this.boundMouseMove = (e) => this.onDragMove(e);\r\n this.boundMouseUp = () => this.onDragEnd();\r\n this.boundTouchMove = (e) => this.onTouchMove(e);\r\n this.boundTouchEnd = () => this.onTouchEnd();\r\n this.boundPopState = () => this.handleNavigation();\r\n this.boundHashChange = () => this.handleNavigation();\r\n }\r\n\r\n // ===============================================\r\n // PUBLIC API\r\n // ===============================================\r\n\r\n init(): void {\r\n this.posY = window.innerHeight - 72;\r\n this.injectStyles();\r\n this.applyThemeColor(this.highlightColor);\r\n this.buildUI();\r\n this.interceptNavigation();\r\n\r\n // MutationObserver for auto-scanning\r\n this.observer = new MutationObserver(() => {\r\n // Re-append CMS UI if removed by framework hydration (Next.js, React, etc.)\r\n if (this.rootEl && !document.contains(this.rootEl)) {\r\n document.body.appendChild(this.rootEl);\r\n }\r\n if (this.styleEl && !document.contains(this.styleEl)) {\r\n document.head.appendChild(this.styleEl);\r\n }\r\n if (this.scanTimeout) clearTimeout(this.scanTimeout);\r\n this.scanTimeout = setTimeout(() => this.autoDetectAndScan(), 150);\r\n });\r\n this.observer.observe(document.body, { childList: true, subtree: true });\r\n\r\n // Listen for navigation events\r\n window.addEventListener('popstate', this.boundPopState);\r\n window.addEventListener('hashchange', this.boundHashChange);\r\n\r\n // Initial navigation\r\n this.handleNavigation();\r\n }\r\n\r\n destroy(): void {\r\n this.cleanupManagedElements();\r\n\r\n // Remove UI\r\n this.styleEl?.remove();\r\n this.rootEl?.remove();\r\n\r\n // Remove listeners\r\n window.removeEventListener('popstate', this.boundPopState);\r\n window.removeEventListener('hashchange', this.boundHashChange);\r\n document.removeEventListener('mousemove', this.boundMouseMove);\r\n document.removeEventListener('mouseup', this.boundMouseUp);\r\n document.removeEventListener('touchmove', this.boundTouchMove);\r\n document.removeEventListener('touchend', this.boundTouchEnd);\r\n\r\n // Restore navigation\r\n if (this.origPushState) history.pushState = this.origPushState;\r\n if (this.origReplaceState) history.replaceState = this.origReplaceState;\r\n\r\n // Disconnect observer\r\n this.observer?.disconnect();\r\n if (this.scanTimeout) clearTimeout(this.scanTimeout);\r\n if (this.toastTimer) clearTimeout(this.toastTimer);\r\n\r\n this.db?.close();\r\n }\r\n\r\n // ===============================================\r\n // STYLES INJECTION\r\n // ===============================================\r\n\r\n private injectStyles(): void {\r\n if (document.getElementById('xtroedge-cms-styles')) return;\r\n this.styleEl = document.createElement('style');\r\n this.styleEl.id = 'xtroedge-cms-styles';\r\n this.styleEl.textContent = CMS_STYLES;\r\n document.head.appendChild(this.styleEl);\r\n }\r\n\r\n // ===============================================\r\n // NAVIGATION INTERCEPTION\r\n // ===============================================\r\n\r\n private interceptNavigation(): void {\r\n this.origPushState = history.pushState.bind(history);\r\n this.origReplaceState = history.replaceState.bind(history);\r\n const self = this;\r\n history.pushState = function (...args) {\r\n self.origPushState!(...args);\r\n setTimeout(() => self.handleNavigation(), 0);\r\n };\r\n history.replaceState = function (...args) {\r\n self.origReplaceState!(...args);\r\n setTimeout(() => self.handleNavigation(), 0);\r\n };\r\n }\r\n\r\n private handleNavigation(): void {\r\n const url = window.location.href;\r\n const pathname = window.location.pathname || '/';\r\n const hash = window.location.hash || '';\r\n\r\n // Support hash routing: #/page?edit=true\r\n let path: string;\r\n let searchStr: string;\r\n if (hash.startsWith('#/') || hash.startsWith('#!')) {\r\n const hashPath = hash.replace(/^#[!/]*/, '');\r\n const qIdx = hashPath.indexOf('?');\r\n path = qIdx >= 0 ? hashPath.substring(0, qIdx) : hashPath;\r\n searchStr = qIdx >= 0 ? hashPath.substring(qIdx) : '';\r\n } else {\r\n path = pathname.replace(/^\\//, '') || 'home';\r\n searchStr = window.location.search;\r\n }\r\n\r\n const slug = '/' + (path.replace(/^\\//, '') || 'home');\r\n const params = new URLSearchParams(searchStr);\r\n const editViaParam = params.get('edit') === 'true';\r\n\r\n this.isEditAllowed = editViaParam || sessionStorage.getItem('builder_edit_mode') === 'true';\r\n\r\n const slugChanged = slug !== this.currentSlug;\r\n if (slugChanged) {\r\n this.cleanupManagedElements();\r\n this.currentSlug = slug;\r\n this.currentTitle = (path.replace(/^\\//, '') || 'home').replace(/-/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase()) + ' Page';\r\n this.resetAll();\r\n }\r\n\r\n // Restore edit mode — check builder_token first\r\n const editFromSession = sessionStorage.getItem('builder_edit_mode') === 'true';\r\n const wantsEdit = editViaParam || editFromSession;\r\n\r\n if (wantsEdit) {\r\n const token = localStorage.getItem('builder_token');\r\n if (!token) {\r\n // No token → show login modal, do NOT enable edit mode yet\r\n if (!this.pendingEditMode) {\r\n this.pendingEditMode = true;\r\n this.currentLang = this.detectCurrentLanguage();\r\n this.setLoading(true);\r\n setTimeout(() => {\r\n this.loadTranslationsAndInit(false);\r\n this.showLoginModal();\r\n }, 300);\r\n }\r\n return;\r\n }\r\n this.editMode = true;\r\n }\r\n\r\n // Skip reload if same slug and already initialized\r\n if (!slugChanged && this.initialized) {\r\n this.updateUI();\r\n return;\r\n }\r\n\r\n this.currentLang = this.detectCurrentLanguage();\r\n\r\n // Show loader\r\n this.setLoading(true);\r\n\r\n // Auto-detect after DOM settles, then load content\r\n const loadDraft = wantsEdit;\r\n setTimeout(() => {\r\n this.initialized = true;\r\n this.loadTranslationsAndInit(loadDraft);\r\n }, 300);\r\n }\r\n\r\n // ===============================================\r\n // BUILD UI\r\n // ===============================================\r\n\r\n private buildUI(): void {\r\n this.rootEl = document.createElement('div');\r\n this.rootEl.id = 'xtroedge-cms-root';\r\n\r\n // Loader\r\n this.loaderEl = this.createElement('div', 'lcms-loader-overlay lcms-hidden');\r\n this.loaderEl.innerHTML = `<div class=\"lcms-loader-content\">\r\n <div class=\"lcms-orbit-loader\">\r\n <div class=\"lcms-orbit lcms-orbit-1\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-orbit lcms-orbit-2\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-orbit lcms-orbit-3\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-core-glow\"></div>\r\n <div class=\"lcms-core\"></div>\r\n </div>\r\n <span class=\"lcms-loader-text\">Loading</span>\r\n </div>`;\r\n this.rootEl.appendChild(this.loaderEl);\r\n\r\n // Toast\r\n this.toastEl = this.createElement('div', 'lcms-toast lcms-hidden');\r\n this.rootEl.appendChild(this.toastEl);\r\n\r\n // FAB\r\n this.fabEl = this.createElement('div', 'lcms-fab');\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n this.fabEl.addEventListener('mousedown', (e) => this.onDragStart(e));\r\n this.fabEl.addEventListener('touchstart', (e) => this.onTouchStart(e), { passive: true });\r\n\r\n // FAB button\r\n this.fabBtn = document.createElement('button');\r\n this.fabBtn.className = 'lcms-fab-btn';\r\n this.fabBtn.innerHTML = ICON.edit;\r\n this.fabBtn.addEventListener('click', (e) => this.onFabClick(e));\r\n this.badgeEl = this.createElement('span', 'lcms-badge lcms-hidden');\r\n this.fabBtn.appendChild(this.badgeEl);\r\n this.fabEl.appendChild(this.fabBtn);\r\n\r\n // Panel\r\n this.panelEl = this.createElement('div', 'lcms-panel lcms-hidden');\r\n this.buildPanel();\r\n this.fabEl.appendChild(this.panelEl);\r\n\r\n this.rootEl.appendChild(this.fabEl);\r\n\r\n // Hidden file input\r\n this.fileInput = document.createElement('input');\r\n this.fileInput.type = 'file';\r\n this.fileInput.accept = 'image/*';\r\n this.fileInput.style.display = 'none';\r\n this.fileInput.addEventListener('change', (e) => this.onImageFileSelected(e));\r\n this.rootEl.appendChild(this.fileInput);\r\n\r\n // Image upload overlay\r\n this.imgOverlay = this.createElement('div', 'lcms-img-upload-overlay lcms-hidden');\r\n this.imgOverlay.innerHTML = `<div class=\"lcms-img-upload-content\"><div class=\"lcms-spinner-lg\"></div><span>Uploading image...</span></div>`;\r\n this.rootEl.appendChild(this.imgOverlay);\r\n\r\n document.body.appendChild(this.rootEl);\r\n }\r\n\r\n private buildPanel(): void {\r\n if (!this.panelEl) return;\r\n\r\n // Header\r\n const header = this.createElement('div', 'lcms-panel-header');\r\n\r\n // Edit toggle\r\n const toggleLabel = this.createElement('label', 'lcms-toggle');\r\n toggleLabel.addEventListener('click', (e) => e.stopPropagation());\r\n this.editToggle = document.createElement('input');\r\n this.editToggle.type = 'checkbox';\r\n this.editToggle.checked = this.editMode;\r\n this.editToggle.addEventListener('change', (e) => this.toggleEditMode(e));\r\n const slider = this.createElement('span', 'lcms-toggle-slider');\r\n const labelText = this.createElement('span', 'lcms-toggle-label');\r\n labelText.textContent = 'Edit';\r\n toggleLabel.appendChild(this.editToggle);\r\n toggleLabel.appendChild(slider);\r\n toggleLabel.appendChild(labelText);\r\n header.appendChild(toggleLabel);\r\n\r\n // Language switch\r\n this.langSwitchEl = this.createElement('div', 'lcms-lang-switch lcms-hidden');\r\n this.buildLangButtons();\r\n header.appendChild(this.langSwitchEl);\r\n\r\n // Close button\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'lcms-close-btn';\r\n closeBtn.innerHTML = ICON.close;\r\n closeBtn.addEventListener('click', (e) => { e.stopPropagation(); this.togglePanel(); });\r\n header.appendChild(closeBtn);\r\n\r\n this.panelEl.appendChild(header);\r\n\r\n // Site identifier\r\n this.siteIdEl = this.createElement('div', 'lcms-site-id');\r\n const isDomain = this.siteIdentifier.includes('.');\r\n this.siteIdEl.innerHTML = `<span class=\"lcms-site-id-icon\">${isDomain ? '\\u{1F310}' : '\\u{1F511}'}</span><span class=\"lcms-site-id-text\">${isDomain ? this.siteIdentifier : this.siteIdentifier.substring(0, 8)}</span>`;\r\n this.panelEl.appendChild(this.siteIdEl);\r\n\r\n // Edit mode content (hidden when edit mode off)\r\n this.editModeContent = this.createElement('div', 'lcms-hidden');\r\n\r\n // Changes info\r\n this.changesInfoEl = this.createElement('div', 'lcms-changes-info lcms-hidden');\r\n this.editModeContent.appendChild(this.changesInfoEl);\r\n\r\n // Undo/Redo row\r\n const undoRow = this.createElement('div', 'lcms-undo-row');\r\n this.undoBtn = document.createElement('button');\r\n this.undoBtn.className = 'lcms-icon-btn';\r\n this.undoBtn.innerHTML = ICON.undo;\r\n this.undoBtn.disabled = true;\r\n this.undoBtn.addEventListener('click', (e) => { e.stopPropagation(); this.onUndo(); });\r\n this.redoBtn = document.createElement('button');\r\n this.redoBtn.className = 'lcms-icon-btn';\r\n this.redoBtn.innerHTML = ICON.redo;\r\n this.redoBtn.disabled = true;\r\n this.redoBtn.addEventListener('click', (e) => { e.stopPropagation(); this.onRedo(); });\r\n undoRow.appendChild(this.undoBtn);\r\n undoRow.appendChild(this.redoBtn);\r\n this.editModeContent.appendChild(undoRow);\r\n\r\n // Color theme picker\r\n const themeRow = this.createElement('div', 'lcms-theme-row');\r\n const themeLabel = this.createElement('span', 'lcms-theme-label');\r\n themeLabel.textContent = 'Theme';\r\n themeRow.appendChild(themeLabel);\r\n const themeColors = this.createElement('div', 'lcms-theme-colors');\r\n const presetColors = ['#00C853', '#6722FB', '#2196F3', '#FF5722', '#E91E63', '#FFD600'];\r\n for (const color of presetColors) {\r\n const swatch = this.createElement('div', 'lcms-theme-swatch');\r\n swatch.style.background = color;\r\n swatch.dataset.color = color;\r\n if (color === this.highlightColor) swatch.classList.add('active');\r\n swatch.addEventListener('click', (e) => { e.stopPropagation(); this.applyThemeColor(color); });\r\n themeColors.appendChild(swatch);\r\n }\r\n // Custom color input\r\n const customSwatch = this.createElement('div', 'lcms-theme-custom');\r\n const customPreview = this.createElement('div', 'lcms-theme-custom-preview');\r\n const customInput = document.createElement('input');\r\n customInput.type = 'color';\r\n customInput.value = this.highlightColor;\r\n customInput.addEventListener('input', (e) => { e.stopPropagation(); this.applyThemeColor((e.target as HTMLInputElement).value); });\r\n customSwatch.appendChild(customPreview);\r\n customSwatch.appendChild(customInput);\r\n themeColors.appendChild(customSwatch);\r\n themeRow.appendChild(themeColors);\r\n this.editModeContent.appendChild(themeRow);\r\n\r\n // History button\r\n this.historyBtnEl = document.createElement('button');\r\n this.historyBtnEl.className = 'lcms-history-btn';\r\n this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;\r\n this.historyBtnEl.addEventListener('click', (e) => { e.stopPropagation(); this.toggleHistory(); });\r\n this.editModeContent.appendChild(this.historyBtnEl);\r\n\r\n // History panel\r\n this.historyPanelEl = this.createElement('div', 'lcms-history-panel lcms-hidden');\r\n const historyTitle = this.createElement('div', 'lcms-history-title');\r\n historyTitle.textContent = 'Edit History';\r\n this.historyPanelEl.appendChild(historyTitle);\r\n this.historyListEl = this.createElement('div', 'lcms-history-list');\r\n this.historyPanelEl.appendChild(this.historyListEl);\r\n this.editModeContent.appendChild(this.historyPanelEl);\r\n\r\n // Actions\r\n this.actionsEl = this.createElement('div', 'lcms-actions');\r\n this.saveBtn = document.createElement('button');\r\n this.saveBtn.className = 'lcms-btn-save';\r\n this.saveBtn.innerHTML = `${ICON.save} Save Draft`;\r\n this.saveBtn.addEventListener('click', (e) => { e.stopPropagation(); this.saveChanges(); });\r\n this.publishBtn = document.createElement('button');\r\n this.publishBtn.className = 'lcms-btn-publish';\r\n this.publishBtn.innerHTML = `${ICON.publish} Publish`;\r\n this.publishBtn.addEventListener('click', (e) => { e.stopPropagation(); this.publishChanges(); });\r\n const logoutBtn = document.createElement('button');\r\n logoutBtn.className = 'lcms-btn-logout';\r\n logoutBtn.innerHTML = `${ICON.logout} Logout`;\r\n logoutBtn.addEventListener('click', (e) => { e.stopPropagation(); this.logout(); });\r\n this.actionsEl.appendChild(this.saveBtn);\r\n this.actionsEl.appendChild(this.publishBtn);\r\n this.actionsEl.appendChild(logoutBtn);\r\n this.editModeContent.appendChild(this.actionsEl);\r\n\r\n this.panelEl.appendChild(this.editModeContent);\r\n\r\n // Branding\r\n this.brandingEl = this.createElement('div', 'lcms-branding');\r\n this.brandingEl.innerHTML = `<div class=\"lcms-branding-logo\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6L9 17l-5-5\"/></svg></div><div class=\"lcms-branding-text\">Powered by <span>XtroEdge</span></div>`;\r\n this.brandingEl.addEventListener('click', (e) => { e.stopPropagation(); window.open('https://xtro.vercel.app/', '_blank'); });\r\n this.panelEl.appendChild(this.brandingEl);\r\n }\r\n\r\n private buildLangButtons(): void {\r\n if (!this.langSwitchEl) return;\r\n this.langSwitchEl.innerHTML = '';\r\n const select = document.createElement('select');\r\n select.className = 'lcms-lang-select';\r\n for (const lang of this.languages) {\r\n const opt = document.createElement('option');\r\n opt.value = lang;\r\n opt.textContent = lang.toUpperCase();\r\n if (lang === this.currentLang) opt.selected = true;\r\n select.appendChild(opt);\r\n }\r\n select.addEventListener('change', (e) => { e.stopPropagation(); this.switchLang((e.target as HTMLSelectElement).value); });\r\n this.langSwitchEl.appendChild(select);\r\n const arrow = document.createElement('span');\r\n arrow.className = 'lcms-lang-arrow';\r\n arrow.textContent = '\\u25BC';\r\n this.langSwitchEl.appendChild(arrow);\r\n }\r\n\r\n // ===============================================\r\n // UI UPDATE\r\n // ===============================================\r\n\r\n private updateUI(): void {\r\n // FAB visibility\r\n if (this.fabEl) {\r\n this.fabEl.style.display = this.isEditAllowed ? '' : 'none';\r\n }\r\n\r\n // FAB button vs panel\r\n if (this.fabBtn) {\r\n this.fabBtn.style.display = this.isOpen ? 'none' : '';\r\n this.fabBtn.classList.toggle('lcms-fab-active', this.editMode);\r\n }\r\n if (this.panelEl) {\r\n this.panelEl.classList.toggle('lcms-hidden', !this.isOpen);\r\n // Position panel\r\n if (this.isOpen) {\r\n const openUp = this.posY > window.innerHeight / 2;\r\n const openLeft = this.posX > window.innerWidth / 2;\r\n this.panelEl.style.bottom = openUp ? '0' : '';\r\n this.panelEl.style.top = openUp ? '' : '0';\r\n this.panelEl.style.right = openLeft ? '0' : '';\r\n this.panelEl.style.left = openLeft ? '' : '0';\r\n }\r\n }\r\n\r\n // Badge\r\n if (this.badgeEl) {\r\n this.badgeEl.classList.toggle('lcms-hidden', this.unsavedChanges === 0);\r\n this.badgeEl.textContent = String(this.unsavedChanges);\r\n }\r\n\r\n // Edit toggle\r\n if (this.editToggle) this.editToggle.checked = this.editMode;\r\n\r\n // Lang switch\r\n if (this.langSwitchEl) {\r\n this.langSwitchEl.classList.toggle('lcms-hidden', !this.editMode || this.languages.length <= 1);\r\n const sel = this.langSwitchEl.querySelector('.lcms-lang-select') as HTMLSelectElement | null;\r\n if (sel) sel.value = this.currentLang;\r\n }\r\n\r\n // Edit mode content\r\n if (this.editModeContent) {\r\n this.editModeContent.classList.toggle('lcms-hidden', !this.editMode);\r\n }\r\n\r\n // Changes info\r\n if (this.changesInfoEl) {\r\n this.changesInfoEl.classList.toggle('lcms-hidden', this.unsavedChanges === 0);\r\n this.changesInfoEl.textContent = `${this.unsavedChanges} unsaved change${this.unsavedChanges > 1 ? 's' : ''}`;\r\n }\r\n\r\n // Undo/Redo\r\n if (this.undoBtn) this.undoBtn.disabled = !this.canUndo;\r\n if (this.redoBtn) this.redoBtn.disabled = !this.canRedo;\r\n\r\n // History button\r\n if (this.historyBtnEl) this.historyBtnEl.classList.toggle('active', this.showHistory);\r\n if (this.historyPanelEl) this.historyPanelEl.classList.toggle('lcms-hidden', !this.showHistory);\r\n\r\n // Save/Publish buttons\r\n if (this.saveBtn) {\r\n this.saveBtn.disabled = this.isSaving || this.isPublishing || this.unsavedChanges === 0;\r\n this.saveBtn.innerHTML = this.isSaving ? '<span class=\"lcms-spinner\"></span> Saving...' : `${ICON.save} Save Draft`;\r\n }\r\n if (this.publishBtn) {\r\n this.publishBtn.disabled = this.isSaving || this.isPublishing;\r\n this.publishBtn.innerHTML = this.isPublishing ? '<span class=\"lcms-spinner\"></span> Publishing...' : `${ICON.publish} Publish`;\r\n }\r\n\r\n // Loader\r\n if (this.loaderEl) this.loaderEl.classList.toggle('lcms-hidden', !this.loading);\r\n\r\n // Image overlay\r\n if (this.imgOverlay) this.imgOverlay.classList.toggle('lcms-hidden', !this.imageUploading);\r\n }\r\n\r\n // ===============================================\r\n // DOM SCANNING\r\n // ===============================================\r\n\r\n private autoDetectAndScan(): void {\r\n this.autoDetectElements();\r\n this.scanDOM();\r\n this.scanImages();\r\n }\r\n\r\n private resolveContainer(): Element {\r\n if (this.containerSelector) {\r\n return document.querySelector(this.containerSelector) || document.body;\r\n }\r\n return document.body;\r\n }\r\n\r\n private autoDetectElements(): void {\r\n const container = this.resolveContainer();\r\n if (!container) return;\r\n\r\n // Clean up stale auto-detected elements\r\n for (const el of this.autoDetectedElements) {\r\n if (!document.contains(el)) this.autoDetectedElements.delete(el);\r\n }\r\n\r\n // Detect section slug based on ancestor tag name\r\n // Tags ending with '-header' or being <header> → /header\r\n // Tags ending with '-footer' or being <footer> → /footer\r\n const getSectionSlug = (el: HTMLElement): string => {\r\n let parent: HTMLElement | null = el.parentElement;\r\n while (parent && parent !== document.body) {\r\n const tag = parent.tagName.toLowerCase();\r\n if (tag === 'header' || tag.endsWith('-header')) return '/header';\r\n if (tag === 'footer' || tag.endsWith('-footer')) return '/footer';\r\n parent = parent.parentElement;\r\n }\r\n return this.currentSlug;\r\n };\r\n\r\n // Section-aware tag counters to avoid key collisions across sections\r\n const tagCounters: { [section: string]: { [tag: string]: number } } = {};\r\n\r\n const assignKey = (el: HTMLElement, sectionSlug: string) => {\r\n const sectionKey = sectionSlug === '/header' ? 'header'\r\n : sectionSlug === '/footer' ? 'footer' : 'page';\r\n if (!tagCounters[sectionKey]) tagCounters[sectionKey] = {};\r\n const tag = el.tagName.toLowerCase();\r\n if (!tagCounters[sectionKey][tag]) tagCounters[sectionKey][tag] = 0;\r\n const prefix = sectionKey !== 'page' ? `${sectionKey}_` : '';\r\n const key = `${prefix}xcms_${tag}_${tagCounters[sectionKey][tag]}`;\r\n tagCounters[sectionKey][tag]++;\r\n el.setAttribute('data-cms', key);\r\n el.setAttribute('data-cms-section', sectionSlug); // used during save/load\r\n this.autoDetectedElements.add(el);\r\n };\r\n\r\n // Scan standard editable tags (h1, p, div, etc.)\r\n const selector = this.editableTags.join(',');\r\n const elements = container.querySelectorAll<HTMLElement>(selector);\r\n elements.forEach(el => {\r\n if (el.hasAttribute('data-cms')) return;\r\n if (el.closest('#xtroedge-cms-root, script, style, noscript')) return;\r\n if (el.children.length > 3) return;\r\n const text = this.getDirectTextContent(el).trim();\r\n if (text.length < 2) return;\r\n assignKey(el, getSectionSlug(el));\r\n });\r\n\r\n // Scan [data-editable] elements — works with ANY tag (app-header, app-footer, custom components)\r\n // No children/text restrictions since user explicitly marked them\r\n const dataEditables = container.querySelectorAll<HTMLElement>('[data-editable]');\r\n dataEditables.forEach(el => {\r\n if (el.hasAttribute('data-cms')) return;\r\n if (el.closest('#xtroedge-cms-root, script, style, noscript')) return;\r\n assignKey(el, getSectionSlug(el));\r\n });\r\n }\r\n\r\n private scanDOM(): void {\r\n const elements = document.querySelectorAll<HTMLElement>('[data-cms]');\r\n elements.forEach(el => {\r\n if (el.closest('#xtroedge-cms-root')) return;\r\n const key = el.getAttribute('data-cms')!;\r\n this.registeredKeys.add(key);\r\n if (!this.managedElements.has(el)) {\r\n this.attachElement(el, key);\r\n }\r\n });\r\n // Cleanup removed elements\r\n for (const [el] of this.managedElements) {\r\n if (!document.contains(el)) this.detachElement(el);\r\n }\r\n }\r\n\r\n private scanImages(): void {\r\n const container = this.resolveContainer();\r\n if (!container) return;\r\n const currentImages = { ...this.pageImages };\r\n let hasNew = false;\r\n const images = container.querySelectorAll<HTMLImageElement>('img');\r\n images.forEach(img => {\r\n if (img.closest('#xtroedge-cms-root')) return;\r\n if (this.managedImages.has(img)) return;\r\n const src = img.getAttribute('src') || '';\r\n if (!src || src.startsWith('data:')) return;\r\n this.attachImage(img, src);\r\n if (!currentImages[src]) {\r\n currentImages[src] = src;\r\n hasNew = true;\r\n }\r\n });\r\n if (hasNew) {\r\n this.pageImages = currentImages;\r\n this.originalImages = JSON.parse(JSON.stringify(currentImages));\r\n }\r\n for (const [img] of this.managedImages) {\r\n if (!document.contains(img)) this.detachImage(img);\r\n }\r\n }\r\n\r\n private getDirectTextContent(el: HTMLElement): string {\r\n let text = '';\r\n for (let i = 0; i < el.childNodes.length; i++) {\r\n if (el.childNodes[i].nodeType === Node.TEXT_NODE) {\r\n text += el.childNodes[i].textContent || '';\r\n }\r\n }\r\n return text;\r\n }\r\n\r\n // ===============================================\r\n // ELEMENT EDITING\r\n // ===============================================\r\n\r\n private attachElement(el: HTMLElement, key: string): void {\r\n const blurHandler = () => {\r\n const text = el.textContent?.trim() || '';\r\n const currentVal = this.getPageText(key);\r\n if (text !== currentVal) this.onTextChanged(key, text);\r\n };\r\n const keydownHandler = (e: KeyboardEvent) => {\r\n if (e.key === 'Enter') { e.preventDefault(); el.blur(); }\r\n };\r\n const inputHandler = () => {\r\n const text = el.textContent?.trim() || '';\r\n const currentVal = this.getPageText(key);\r\n if (text !== currentVal) this.onTextChanged(key, text);\r\n };\r\n // Prevent click navigation (for <a routerLink> and href links) in edit mode\r\n const clickHandler = (e: Event) => {\r\n const isLink = el.tagName === 'A' || (e.target as HTMLElement).closest('a');\r\n if (isLink) {\r\n e.preventDefault();\r\n e.stopPropagation(); // Stop Angular routerLink from navigating\r\n el.focus(); // Manually focus so contenteditable caret works\r\n }\r\n };\r\n const sectionSlug = el.getAttribute('data-cms-section') || this.currentSlug;\r\n this.managedElements.set(el, { key, sectionSlug, blurHandler, keydownHandler, inputHandler, clickHandler });\r\n if (this.editMode) this.enableElementEdit(el, key, blurHandler, keydownHandler, inputHandler, clickHandler);\r\n }\r\n\r\n private detachElement(el: HTMLElement): void {\r\n const info = this.managedElements.get(el);\r\n if (info) {\r\n el.removeEventListener('blur', info.blurHandler);\r\n el.removeEventListener('keydown', info.keydownHandler as EventListener);\r\n el.removeEventListener('input', info.inputHandler);\r\n el.removeEventListener('click', info.clickHandler, true);\r\n el.removeAttribute('contenteditable');\r\n this.managedElements.delete(el);\r\n }\r\n }\r\n\r\n private enableElementEdit(el: HTMLElement, _key: string, blurH: (e: Event) => void, keyH: (e: KeyboardEvent) => void, inputH: (e: Event) => void, clickH: (e: Event) => void): void {\r\n const val = this.getPageText(_key);\r\n if (val) el.textContent = val;\r\n el.setAttribute('contenteditable', 'true');\r\n el.style.outline = `2px dashed ${this.highlightColor}`;\r\n el.style.outlineOffset = '-2px';\r\n el.style.cursor = 'text';\r\n el.style.transition = 'background 0.2s';\r\n el.style.minWidth = '20px';\r\n el.addEventListener('blur', blurH);\r\n el.addEventListener('keydown', keyH as EventListener);\r\n el.addEventListener('input', inputH);\r\n el.addEventListener('click', clickH, true); // capture phase — prevents Angular routerLink navigation\r\n }\r\n\r\n private disableElementEdit(el: HTMLElement, _key: string, blurH: (e: Event) => void, keyH: (e: KeyboardEvent) => void, inputH: (e: Event) => void, clickH: (e: Event) => void): void {\r\n el.removeAttribute('contenteditable');\r\n el.style.outline = '';\r\n el.style.outline = '';\r\n el.style.outlineOffset = '';\r\n el.style.cursor = '';\r\n el.style.transition = '';\r\n el.style.minWidth = '';\r\n const val = this.getPageText(_key);\r\n if (val) el.textContent = val;\r\n el.removeEventListener('blur', blurH);\r\n el.removeEventListener('keydown', keyH as EventListener);\r\n el.removeEventListener('input', inputH);\r\n el.removeEventListener('click', clickH, true);\r\n }\r\n\r\n private applyEditMode(editMode: boolean): void {\r\n for (const [el, info] of this.managedElements) {\r\n if (editMode) this.enableElementEdit(el, info.key, info.blurHandler, info.keydownHandler, info.inputHandler, info.clickHandler);\r\n else this.disableElementEdit(el, info.key, info.blurHandler, info.keydownHandler, info.inputHandler, info.clickHandler);\r\n }\r\n this.applyImageEditMode(editMode);\r\n }\r\n\r\n private updateElementTexts(): void {\r\n this.observer?.disconnect();\r\n for (const [el, info] of this.managedElements) {\r\n if (document.activeElement === el) continue;\r\n const val = this.getPageText(info.key);\r\n if (val && el.textContent !== val) el.textContent = val;\r\n }\r\n this.observer?.observe(document.body, { childList: true, subtree: true });\r\n }\r\n\r\n private cleanupManagedElements(): void {\r\n for (const [el] of this.managedElements) this.detachElement(el);\r\n this.managedElements.clear();\r\n for (const el of this.autoDetectedElements) el.removeAttribute('data-cms');\r\n this.autoDetectedElements.clear();\r\n this.cleanupManagedImages();\r\n }\r\n\r\n // ===============================================\r\n // IMAGE MANAGEMENT\r\n // ===============================================\r\n\r\n private attachImage(img: HTMLImageElement, key: string): void {\r\n const ctxHandler = (e: MouseEvent) => {\r\n if (!this.editMode) return;\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.showImageContextMenu(e.clientX, e.clientY, img);\r\n };\r\n this.managedImages.set(img, { key, ctxHandler });\r\n if (this.editMode) this.enableImageEdit(img, ctxHandler);\r\n }\r\n\r\n private detachImage(img: HTMLImageElement): void {\r\n const info = this.managedImages.get(img);\r\n if (info) {\r\n img.removeEventListener('contextmenu', info.ctxHandler);\r\n img.style.outline = '';\r\n img.style.cursor = '';\r\n this.managedImages.delete(img);\r\n }\r\n }\r\n\r\n private cleanupManagedImages(): void {\r\n for (const [img] of this.managedImages) this.detachImage(img);\r\n this.managedImages.clear();\r\n this.dismissImageCtxMenu();\r\n }\r\n\r\n private applyImageEditMode(editMode: boolean): void {\r\n for (const [img, info] of this.managedImages) {\r\n if (editMode) this.enableImageEdit(img, info.ctxHandler);\r\n else this.disableImageEdit(img, info.ctxHandler);\r\n }\r\n if (!editMode) this.dismissImageCtxMenu();\r\n }\r\n\r\n private enableImageEdit(img: HTMLImageElement, ctxHandler: (e: MouseEvent) => void): void {\r\n if (!img.dataset.origTitle) img.dataset.origTitle = img.title || '';\r\n img.title = 'Right-click to change image';\r\n img.style.outline = `2px dashed ${this.highlightColor}`;\r\n img.style.cursor = 'context-menu';\r\n img.addEventListener('contextmenu', ctxHandler);\r\n }\r\n\r\n private disableImageEdit(img: HTMLImageElement, ctxHandler: (e: MouseEvent) => void): void {\r\n img.title = img.dataset.origTitle || '';\r\n delete img.dataset.origTitle;\r\n img.style.outline = '';\r\n img.style.cursor = '';\r\n img.removeEventListener('contextmenu', ctxHandler);\r\n }\r\n\r\n private showImageContextMenu(x: number, y: number, img: HTMLImageElement): void {\r\n this.dismissImageCtxMenu();\r\n const menu = document.createElement('div');\r\n Object.assign(menu.style, {\r\n position: 'fixed', zIndex: '10005', minWidth: '160px',\r\n background: 'rgba(30,15,60,0.85)', backdropFilter: 'blur(16px)', webkitBackdropFilter: 'blur(16px)',\r\n border: '1px solid rgba(139,92,246,0.3)', borderRadius: '10px', padding: '4px',\r\n boxShadow: '0 8px 32px rgba(0,0,0,0.4)', fontFamily: 'system-ui, -apple-system, sans-serif',\r\n left: Math.min(x, window.innerWidth - 180) + 'px',\r\n top: Math.min(y, window.innerHeight - 50) + 'px',\r\n });\r\n const btn = document.createElement('button');\r\n Object.assign(btn.style, {\r\n width: '100%', padding: '8px 12px', border: 'none', borderRadius: '7px',\r\n background: 'transparent', color: 'white', fontSize: '12px', fontWeight: '500',\r\n cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '8px',\r\n });\r\n btn.innerHTML = `${ICON.image} Upload Image`;\r\n btn.addEventListener('mouseenter', () => btn.style.background = 'rgba(103,34,251,0.3)');\r\n btn.addEventListener('mouseleave', () => btn.style.background = 'transparent');\r\n btn.addEventListener('click', () => {\r\n this.activeImageEl = img;\r\n if (this.fileInput) { this.fileInput.value = ''; this.fileInput.click(); }\r\n this.dismissImageCtxMenu();\r\n });\r\n menu.appendChild(btn);\r\n document.body.appendChild(menu);\r\n this.imageCtxMenu = menu;\r\n\r\n const closeHandler = (e: MouseEvent) => {\r\n if (!menu.contains(e.target as Node)) {\r\n this.dismissImageCtxMenu();\r\n document.removeEventListener('mousedown', closeHandler);\r\n }\r\n };\r\n setTimeout(() => document.addEventListener('mousedown', closeHandler), 0);\r\n }\r\n\r\n private dismissImageCtxMenu(): void {\r\n if (this.imageCtxMenu) {\r\n this.imageCtxMenu.remove();\r\n this.imageCtxMenu = null;\r\n }\r\n }\r\n\r\n private onImageFileSelected(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n const file = input.files?.[0];\r\n if (!file || !this.activeImageEl) return;\r\n\r\n this.imageUploading = true;\r\n this.updateUI();\r\n\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n const dataUrl = reader.result as string;\r\n this.uploadImageToApi(dataUrl);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n\r\n private async uploadImageToApi(dataUrl: string): Promise<void> {\r\n try {\r\n const res = await this.apiFetch(`${this.config.apiBase}/web/upload-image`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ url: dataUrl }),\r\n });\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n const data = await res.json();\r\n const baseUrl = this.config.imageBaseUrl || (this.config.apiBase ? new URL(this.config.apiBase).origin : '');\r\n const fullUrl = baseUrl + data.path;\r\n if (this.activeImageEl) {\r\n const key = this.managedImages.get(this.activeImageEl)?.key || '';\r\n this.activeImageEl.src = fullUrl;\r\n this.onImageChanged(key, fullUrl);\r\n }\r\n this.imageUploading = false;\r\n this.activeImageEl = null;\r\n this.updateUI();\r\n this.showToast('Image updated!', 'success');\r\n } catch (err) {\r\n this.imageUploading = false;\r\n this.activeImageEl = null;\r\n this.updateUI();\r\n this.showToast('Image upload failed.', 'error');\r\n this.config.onError?.('upload-image', err);\r\n }\r\n }\r\n\r\n private applyPageImages(): void {\r\n for (const [img, info] of this.managedImages) {\r\n const url = this.pageImages[info.key];\r\n if (url && img.src !== url) img.src = url;\r\n }\r\n }\r\n\r\n // ===============================================\r\n // TEXT STATE\r\n // ===============================================\r\n\r\n private getPageText(key: string): string {\r\n return this.pageTexts[key]?.[this.currentLang] || '';\r\n }\r\n\r\n private onTextChanged(key: string, newValue: string): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.redoStack = [];\r\n this.canUndo = true;\r\n this.canRedo = false;\r\n\r\n if (!this.pageTexts[key]) this.pageTexts[key] = {};\r\n this.pageTexts[key] = { ...this.pageTexts[key], [this.currentLang]: newValue };\r\n this.dirtyKeys.add(key);\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n this.pushHistory(key, this.currentLang);\r\n this.updateUI();\r\n }\r\n\r\n private onImageChanged(key: string, url: string): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.redoStack = [];\r\n this.canUndo = true;\r\n this.canRedo = false;\r\n\r\n this.pageImages = { ...this.pageImages, [key]: url };\r\n this.dirtyImageKeys.add(key);\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n this.pushHistory(key, 'img');\r\n this.updateUI();\r\n }\r\n\r\n private createSnapshot(): string {\r\n return JSON.stringify({ texts: this.pageTexts, images: this.pageImages });\r\n }\r\n\r\n private applySnapshot(raw: string): void {\r\n const data = JSON.parse(raw);\r\n if (data.texts) {\r\n this.pageTexts = data.texts;\r\n if (data.images) this.pageImages = data.images;\r\n } else {\r\n this.pageTexts = data;\r\n }\r\n }\r\n\r\n // ===============================================\r\n // UNDO / REDO\r\n // ===============================================\r\n\r\n private onUndo(): void {\r\n if (this.undoStack.length === 0) return;\r\n this.redoStack.push(this.createSnapshot());\r\n this.applySnapshot(this.undoStack.pop()!);\r\n this.canUndo = this.undoStack.length > 0;\r\n this.canRedo = true;\r\n this.recalcDirtyKeys();\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private onRedo(): void {\r\n if (this.redoStack.length === 0) return;\r\n this.undoStack.push(this.createSnapshot());\r\n this.applySnapshot(this.redoStack.pop()!);\r\n this.canUndo = true;\r\n this.canRedo = this.redoStack.length > 0;\r\n this.recalcDirtyKeys();\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private recalcDirtyKeys(): void {\r\n this.dirtyKeys.clear();\r\n for (const key of this.registeredKeys) {\r\n if (JSON.stringify(this.pageTexts[key]) !== JSON.stringify(this.originalTexts[key])) {\r\n this.dirtyKeys.add(key);\r\n }\r\n }\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n }\r\n\r\n private resetAll(): void {\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.undoStack = [];\r\n this.redoStack = [];\r\n this.canUndo = false;\r\n this.canRedo = false;\r\n this.updateUI();\r\n }\r\n\r\n private resetAfterSave(): void {\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n }\r\n\r\n private cancelEditing(): void {\r\n this.pageTexts = JSON.parse(JSON.stringify(this.originalTexts));\r\n this.pageImages = JSON.parse(JSON.stringify(this.originalImages));\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private logout(): void {\r\n localStorage.removeItem('builder_token');\r\n sessionStorage.removeItem('builder_edit_mode');\r\n this.editMode = false;\r\n this.isEditAllowed = false;\r\n this.applyEditMode(false);\r\n this.isOpen = false;\r\n this.updateUI();\r\n this.showToast('Logged out', 'success');\r\n }\r\n\r\n // ===============================================\r\n // API\r\n // ===============================================\r\n\r\n private async loadTranslationsAndInit(loadDraft: boolean): Promise<void> {\r\n if (this.config.i18nBasePath) {\r\n try {\r\n const lang = this.currentLang;\r\n const res = await fetch(`${this.config.i18nBasePath}/${lang}.json`);\r\n if (res.ok) {\r\n const translations = await res.json();\r\n this.translationCache.clear();\r\n this.flattenTranslations(translations, '', this.getPageSection());\r\n }\r\n } catch { /* ignore */ }\r\n }\r\n\r\n this.autoDetectAndScan();\r\n if (this.editMode) this.applyEditMode(true);\r\n if (this.config.apiBase) {\r\n if (loadDraft) this.loadPageContent('draft');\r\n else this.loadPublishedContent();\r\n } else {\r\n this.buildDefaultTexts();\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.setLoading(false);\r\n }\r\n this.updateUI();\r\n }\r\n\r\n private flattenTranslations(obj: any, prefix: string, pageSection: string): void {\r\n for (const k of Object.keys(obj)) {\r\n const fullKey = prefix ? `${prefix}.${k}` : k;\r\n if (typeof obj[k] === 'string') {\r\n const text = obj[k].trim();\r\n if (text.length >= 2) {\r\n const existing = this.translationCache.get(text);\r\n if (!existing || fullKey.toUpperCase().startsWith(pageSection)) {\r\n this.translationCache.set(text, fullKey);\r\n }\r\n }\r\n } else if (typeof obj[k] === 'object' && obj[k] !== null && !Array.isArray(obj[k])) {\r\n this.flattenTranslations(obj[k], fullKey, pageSection);\r\n }\r\n }\r\n }\r\n\r\n private getPageSection(): string {\r\n return this.currentSlug.replace(/^\\//, '').replace(/-/g, '_').toUpperCase();\r\n }\r\n\r\n // Authenticated fetch — adds Authorization header from builder_token\r\n private apiFetch(url: string, opts?: RequestInit): Promise<Response> {\r\n const token = localStorage.getItem('builder_token') || '';\r\n const headers: Record<string, string> = { ...(opts?.headers as Record<string, string> || {}) };\r\n if (token) headers['Authorization'] = `Bearer ${token}`;\r\n return fetch(url, { ...opts, headers });\r\n }\r\n\r\n // Fetch texts for a single slug and merge into pageTexts\r\n private async fetchSection(slug: string, status: 'draft' | 'published'): Promise<WebPageContent | null> {\r\n try {\r\n const res = await this.apiFetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(slug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);\r\n if (!res.ok) return null;\r\n return await res.json();\r\n } catch { return null; }\r\n }\r\n\r\n private async loadPageContent(status: 'draft' | 'published'): Promise<void> {\r\n this.setLoading(true);\r\n this.cleanOldHistory();\r\n\r\n try {\r\n // Load all sections in parallel: current page + header + footer (3 calls total)\r\n const [pageSec, headerSec, footerSec] = await Promise.all([\r\n this.fetchSection(this.currentSlug, status),\r\n this.fetchSection('/header', status),\r\n this.fetchSection('/footer', status),\r\n ]);\r\n\r\n const getTexts = (sec: WebPageContent | null) => sec?.content?.texts || sec?.published_content?.texts || null;\r\n const pageTexts = getTexts(pageSec);\r\n const headerTexts = getTexts(headerSec);\r\n const footerTexts = getTexts(footerSec);\r\n\r\n if (pageTexts || headerTexts || footerTexts) {\r\n this.pageTexts = { ...(pageTexts || {}), ...(headerTexts || {}), ...(footerTexts || {}) };\r\n } else {\r\n this.buildDefaultTexts();\r\n }\r\n\r\n // Extract images from the page response (no extra API call)\r\n const images = pageSec?.content?.images || pageSec?.published_content?.images;\r\n if (images) {\r\n this.pageImages = JSON.parse(JSON.stringify(images));\r\n this.applyPageImages();\r\n }\r\n\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.resetAll();\r\n this.updateElementTexts();\r\n } catch {\r\n this.buildDefaultTexts();\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.resetAll();\r\n } finally {\r\n this.setLoading(false);\r\n }\r\n }\r\n\r\n private async loadPublishedContent(): Promise<void> {\r\n this.setLoading(true);\r\n\r\n try {\r\n // Load all sections in parallel (3 calls total)\r\n const [pageSec, headerSec, footerSec] = await Promise.all([\r\n this.fetchSection(this.currentSlug, 'published'),\r\n this.fetchSection('/header', 'published'),\r\n this.fetchSection('/footer', 'published'),\r\n ]);\r\n\r\n const getTexts = (sec: WebPageContent | null) => sec?.published_content?.texts || null;\r\n const merged = { ...(getTexts(pageSec) || {}), ...(getTexts(headerSec) || {}), ...(getTexts(footerSec) || {}) };\r\n if (Object.keys(merged).length > 0) {\r\n this.pageTexts = JSON.parse(JSON.stringify(merged));\r\n this.updateElementTexts();\r\n }\r\n\r\n // Extract images from page response (no extra API call)\r\n const images = pageSec?.published_content?.images;\r\n if (images && Object.keys(images).length > 0) {\r\n this.pageImages = JSON.parse(JSON.stringify(images));\r\n this.applyPageImages();\r\n }\r\n } catch { /* ignore - use current DOM text */ }\r\n finally { this.setLoading(false); }\r\n }\r\n\r\n private buildDefaultTexts(): void {\r\n const texts: { [key: string]: PageTextEntry } = {};\r\n for (const key of this.registeredKeys) {\r\n const el = document.querySelector(`[data-cms=\"${key}\"]`);\r\n const val = el?.textContent?.trim() || '';\r\n texts[key] = { [this.currentLang]: val };\r\n }\r\n this.pageTexts = texts;\r\n\r\n // Load other languages from i18n files if available\r\n if (this.config.i18nBasePath) {\r\n const otherLangs = this.languages.filter(l => l !== this.currentLang);\r\n for (const lang of otherLangs) {\r\n fetch(`${this.config.i18nBasePath}/${lang}.json`)\r\n .then(r => r.json())\r\n .then(translations => {\r\n const updated = { ...this.pageTexts };\r\n for (const key of this.registeredKeys) {\r\n // Try to resolve key path in translations\r\n const parts = key.split('.');\r\n let val: any = translations;\r\n for (const part of parts) { val = val?.[part]; }\r\n if (val && typeof val === 'string') {\r\n updated[key] = { ...updated[key], [lang]: val };\r\n }\r\n }\r\n this.pageTexts = updated;\r\n this.originalTexts = JSON.parse(JSON.stringify(updated));\r\n this.updateElementTexts();\r\n })\r\n .catch(() => { /* ignore */ });\r\n }\r\n }\r\n }\r\n\r\n // Group pageTexts by section slug based on managedElements info\r\n private groupTextsBySection(): { [sectionSlug: string]: { [key: string]: PageTextEntry } } {\r\n const sections: { [sectionSlug: string]: { [key: string]: PageTextEntry } } = {};\r\n for (const [, info] of this.managedElements) {\r\n const slug = info.sectionSlug;\r\n if (!sections[slug]) sections[slug] = {};\r\n if (this.pageTexts[info.key] !== undefined) {\r\n sections[slug][info.key] = this.pageTexts[info.key];\r\n }\r\n }\r\n return sections;\r\n }\r\n\r\n private async saveChanges(): Promise<void> {\r\n if (!this.config.apiBase) {\r\n this.showToast('No API configured. Set apiBase to enable save.', 'error');\r\n return;\r\n }\r\n this.isSaving = true;\r\n this.updateUI();\r\n\r\n try {\r\n const sections = this.groupTextsBySection();\r\n const requests = Object.entries(sections).map(([slug, texts]) =>\r\n this.apiFetch(`${this.config.apiBase}/web_page/save`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n slug,\r\n title: slug === this.currentSlug ? this.currentTitle : slug.replace('/', ''),\r\n site_identifier: this.siteIdentifier,\r\n content: { texts, ...(slug === this.currentSlug ? { images: this.pageImages } : {}) }\r\n }),\r\n })\r\n );\r\n const results = await Promise.all(requests);\r\n if (results.some(r => !r.ok)) throw new Error('One or more sections failed to save');\r\n this.isSaving = false;\r\n this.resetAfterSave();\r\n this.updateUI();\r\n this.showToast('Draft saved successfully!', 'success');\r\n this.config.onSaved?.();\r\n } catch (err) {\r\n this.isSaving = false;\r\n this.updateUI();\r\n this.showToast('Save failed. Please try again.', 'error');\r\n this.config.onError?.('save', err);\r\n }\r\n }\r\n\r\n private async publishChanges(): Promise<void> {\r\n if (!this.config.apiBase) {\r\n this.showToast('No API configured. Set apiBase to enable publish.', 'error');\r\n return;\r\n }\r\n this.isPublishing = true;\r\n this.updateUI();\r\n\r\n try {\r\n const sections = this.groupTextsBySection();\r\n const requests = Object.entries(sections).map(([slug, texts]) =>\r\n this.apiFetch(`${this.config.apiBase}/web_page/publish`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n slug,\r\n title: slug === this.currentSlug ? this.currentTitle : slug.replace('/', ''),\r\n site_identifier: this.siteIdentifier,\r\n published_content: { texts, ...(slug === this.currentSlug ? { images: this.pageImages } : {}) }\r\n }),\r\n })\r\n );\r\n const results = await Promise.all(requests);\r\n if (results.some(r => !r.ok)) throw new Error('One or more sections failed to publish');\r\n this.isPublishing = false;\r\n this.resetAfterSave();\r\n this.updateUI();\r\n this.showToast('Published successfully!', 'success');\r\n this.config.onPublished?.();\r\n } catch (err) {\r\n this.isPublishing = false;\r\n this.updateUI();\r\n this.showToast('Publish failed. Please try again.', 'error');\r\n this.config.onError?.('publish', err);\r\n }\r\n }\r\n\r\n // ===============================================\r\n // HISTORY (IndexedDB)\r\n // ===============================================\r\n\r\n private async toggleHistory(): Promise<void> {\r\n this.showHistory = !this.showHistory;\r\n if (this.showHistory) await this.loadHistory();\r\n this.updateUI();\r\n }\r\n\r\n private async loadHistory(): Promise<void> {\r\n try {\r\n const db = await this.openDB();\r\n const entries = await new Promise<EditHistoryEntry[]>((resolve, reject) => {\r\n const tx = db.transaction(STORE_NAME, 'readonly');\r\n const store = tx.objectStore(STORE_NAME);\r\n const index = store.index('slug');\r\n const req = index.getAll(this.currentSlug);\r\n req.onsuccess = () => resolve((req.result as EditHistoryEntry[]).sort((a, b) => b.timestamp - a.timestamp).slice(0, 30));\r\n req.onerror = () => reject(req.error);\r\n });\r\n this.historyList = entries;\r\n this.renderHistoryList();\r\n } catch { /* ignore */ }\r\n }\r\n\r\n private renderHistoryList(): void {\r\n if (!this.historyListEl) return;\r\n this.historyListEl.innerHTML = '';\r\n if (this.historyList.length === 0) {\r\n const empty = this.createElement('div', 'lcms-history-empty');\r\n empty.textContent = 'No history yet';\r\n this.historyListEl.appendChild(empty);\r\n return;\r\n }\r\n for (const entry of this.historyList) {\r\n const item = document.createElement('button');\r\n item.className = 'lcms-history-item';\r\n const labelEl = this.createElement('div', 'lcms-history-label');\r\n labelEl.textContent = entry.label;\r\n const metaEl = this.createElement('div', 'lcms-history-meta');\r\n const langEl = this.createElement('span', 'lcms-history-lang');\r\n langEl.textContent = entry.lang.toUpperCase();\r\n const dateText = document.createTextNode(' ' + this.formatDate(entry.timestamp));\r\n metaEl.appendChild(langEl);\r\n metaEl.appendChild(dateText);\r\n item.appendChild(labelEl);\r\n item.appendChild(metaEl);\r\n item.addEventListener('click', (e) => { e.stopPropagation(); this.restoreHistory(entry); });\r\n this.historyListEl.appendChild(item);\r\n }\r\n }\r\n\r\n private restoreHistory(entry: EditHistoryEntry): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.canUndo = true;\r\n this.applySnapshot(entry.snapshot);\r\n this.recalcDirtyKeys();\r\n this.showHistory = false;\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n this.showToast('Restored from history', 'success');\r\n }\r\n\r\n private pushHistory(key: string, lang: string): void {\r\n const isImage = lang === 'img';\r\n const shortKey = isImage ? key.split('/').pop() || 'image' : (key.split('_').pop() || key);\r\n const label = isImage ? `Changed ${shortKey}` : `Edited ${shortKey}`;\r\n this.openDB().then(db => {\r\n const tx = db.transaction(STORE_NAME, 'readwrite');\r\n tx.objectStore(STORE_NAME).add({\r\n slug: this.currentSlug, timestamp: Date.now(),\r\n label, lang,\r\n snapshot: JSON.stringify({ texts: this.pageTexts, images: this.pageImages })\r\n });\r\n }).catch(() => { /* ignore */ });\r\n }\r\n\r\n private async cleanOldHistory(): Promise<void> {\r\n try {\r\n const db = await this.openDB();\r\n const cutoff = Date.now() - this.historyRetentionMs;\r\n const tx = db.transaction(STORE_NAME, 'readwrite');\r\n const index = tx.objectStore(STORE_NAME).index('timestamp');\r\n const req = index.openCursor(IDBKeyRange.upperBound(cutoff));\r\n req.onsuccess = () => { const c = req.result; if (c) { c.delete(); c.continue(); } };\r\n } catch { /* ignore */ }\r\n }\r\n\r\n private openDB(): Promise<IDBDatabase> {\r\n if (this.db) return Promise.resolve(this.db);\r\n return new Promise((resolve, reject) => {\r\n const req = indexedDB.open(DB_NAME, 1);\r\n req.onupgradeneeded = () => {\r\n const db = req.result;\r\n if (!db.objectStoreNames.contains(STORE_NAME)) {\r\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });\r\n store.createIndex('slug', 'slug', { unique: false });\r\n store.createIndex('timestamp', 'timestamp', { unique: false });\r\n }\r\n };\r\n req.onsuccess = () => { this.db = req.result; resolve(this.db); };\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n // ===============================================\r\n // TOAST\r\n // ===============================================\r\n\r\n private showToast(message: string, type: 'success' | 'error'): void {\r\n if (!this.toastEl) return;\r\n this.toastMessage = message;\r\n this.toastType = type;\r\n\r\n const icon = type === 'success' ? ICON.check : ICON.error;\r\n this.toastEl.className = `lcms-toast lcms-toast-${type}`;\r\n this.toastEl.innerHTML = `${icon} ${message}`;\r\n\r\n if (this.toastTimer) clearTimeout(this.toastTimer);\r\n this.toastTimer = setTimeout(() => {\r\n if (this.toastEl) this.toastEl.classList.add('lcms-hidden');\r\n }, 3000);\r\n }\r\n\r\n // ===============================================\r\n // FAB & PANEL\r\n // ===============================================\r\n\r\n private onFabClick(e: Event): void {\r\n e.stopPropagation();\r\n if (this.hasMoved) return;\r\n this.isOpen = !this.isOpen;\r\n this.updateUI();\r\n }\r\n\r\n private togglePanel(): void {\r\n if (!this.hasMoved) {\r\n this.isOpen = !this.isOpen;\r\n this.updateUI();\r\n }\r\n }\r\n\r\n private toggleEditMode(e: Event): void {\r\n e.stopPropagation();\r\n const checked = (e.target as HTMLInputElement).checked;\r\n if (checked) {\r\n sessionStorage.setItem('builder_edit_mode', 'true');\r\n this.editMode = true;\r\n this.currentLang = this.detectCurrentLanguage();\r\n this.applyEditMode(true);\r\n this.loadPageContent('draft');\r\n } else {\r\n sessionStorage.removeItem('builder_edit_mode');\r\n this.editMode = false;\r\n this.applyEditMode(false);\r\n }\r\n this.updateUI();\r\n this.config.onEditModeChanged?.(this.editMode);\r\n }\r\n\r\n private switchLang(lang: string): void {\r\n this.currentLang = lang;\r\n\r\n // 1. Persist language so framework picks it up after reload\r\n localStorage.setItem('selectedLanguage', lang);\r\n document.documentElement.setAttribute('lang', lang);\r\n document.documentElement.setAttribute('dir', lang === 'ar' ? 'rtl' : 'ltr');\r\n\r\n // 2. Notify (fires before reload so any sync listener can catch it)\r\n this.config.onLangChanged?.(lang);\r\n window.dispatchEvent(new CustomEvent('cms:langChanged', { detail: { lang } }));\r\n\r\n // 3. Reload so the framework re-initializes with the new language\r\n window.location.reload();\r\n }\r\n\r\n // ===============================================\r\n // FAB DRAG\r\n // ===============================================\r\n\r\n private onDragStart(e: MouseEvent): void {\r\n if ((e.target as HTMLElement).closest('button:not(.lcms-fab-btn)') || (e.target as HTMLElement).closest('.lcms-panel')) return;\r\n this.isDragging = true;\r\n this.hasMoved = false;\r\n this.dragStartX = e.clientX;\r\n this.dragStartY = e.clientY;\r\n this.startPosX = this.posX;\r\n this.startPosY = this.posY;\r\n document.addEventListener('mousemove', this.boundMouseMove);\r\n document.addEventListener('mouseup', this.boundMouseUp);\r\n }\r\n\r\n private onDragMove(e: MouseEvent): void {\r\n if (!this.isDragging || !this.fabEl) return;\r\n const dx = e.clientX - this.dragStartX, dy = e.clientY - this.dragStartY;\r\n if (Math.abs(dx) > 3 || Math.abs(dy) > 3) this.hasMoved = true;\r\n this.posX = Math.max(0, Math.min(window.innerWidth - 60, this.startPosX + dx));\r\n this.posY = Math.max(0, Math.min(window.innerHeight - 60, this.startPosY + dy));\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n }\r\n\r\n private onDragEnd(): void {\r\n this.isDragging = false;\r\n document.removeEventListener('mousemove', this.boundMouseMove);\r\n document.removeEventListener('mouseup', this.boundMouseUp);\r\n }\r\n\r\n private onTouchStart(e: TouchEvent): void {\r\n if ((e.target as HTMLElement).closest('button:not(.lcms-fab-btn)') || (e.target as HTMLElement).closest('.lcms-panel')) return;\r\n const t = e.touches[0];\r\n this.isDragging = true;\r\n this.hasMoved = false;\r\n this.dragStartX = t.clientX;\r\n this.dragStartY = t.clientY;\r\n this.startPosX = this.posX;\r\n this.startPosY = this.posY;\r\n document.addEventListener('touchmove', this.boundTouchMove, { passive: false });\r\n document.addEventListener('touchend', this.boundTouchEnd);\r\n }\r\n\r\n private onTouchMove(e: TouchEvent): void {\r\n if (!this.isDragging || !this.fabEl) return;\r\n e.preventDefault();\r\n const t = e.touches[0];\r\n const dx = t.clientX - this.dragStartX, dy = t.clientY - this.dragStartY;\r\n if (Math.abs(dx) > 3 || Math.abs(dy) > 3) this.hasMoved = true;\r\n this.posX = Math.max(0, Math.min(window.innerWidth - 60, this.startPosX + dx));\r\n this.posY = Math.max(0, Math.min(window.innerHeight - 60, this.startPosY + dy));\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n }\r\n\r\n private onTouchEnd(): void {\r\n this.isDragging = false;\r\n document.removeEventListener('touchmove', this.boundTouchMove);\r\n document.removeEventListener('touchend', this.boundTouchEnd);\r\n }\r\n\r\n // ===============================================\r\n // HELPERS\r\n // ===============================================\r\n\r\n private setLoading(val: boolean): void {\r\n this.loading = val;\r\n this.updateUI();\r\n }\r\n\r\n private detectCurrentLanguage(): string {\r\n const htmlLang = document.documentElement.getAttribute('lang');\r\n if (htmlLang && this.languages.includes(htmlLang)) return htmlLang;\r\n const stored = localStorage.getItem('selectedLanguage');\r\n if (stored && this.languages.includes(stored)) return stored;\r\n return this.defaultLanguage;\r\n }\r\n\r\n private createElement(tag: string, className: string): HTMLElement {\r\n const el = document.createElement(tag);\r\n el.className = className;\r\n return el;\r\n }\r\n\r\n private formatDate(timestamp: number): string {\r\n const d = new Date(timestamp);\r\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\r\n const h = d.getHours();\r\n const m = d.getMinutes().toString().padStart(2, '0');\r\n const ampm = h >= 12 ? 'PM' : 'AM';\r\n const h12 = h % 12 || 12;\r\n return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;\r\n }\r\n\r\n // ===============================================\r\n // LOGIN MODAL\r\n // ===============================================\r\n\r\n private showLoginModal(): void {\r\n if (this.loginModalEl) return;\r\n\r\n const overlay = document.createElement('div');\r\n overlay.className = 'lcms-login-overlay';\r\n overlay.id = 'lcms-login-modal';\r\n\r\n overlay.innerHTML = `\r\n <div class=\"lcms-login-box\">\r\n <div class=\"lcms-login-logo\">\r\n <div class=\"lcms-login-logo-icon\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </div>\r\n <span class=\"lcms-login-logo-text\">XtroEdge CMS</span>\r\n </div>\r\n <div class=\"lcms-login-title\">Builder Login</div>\r\n <div class=\"lcms-login-sub\">Sign in to access edit mode</div>\r\n <div class=\"lcms-login-field\">\r\n <label class=\"lcms-login-label\">Username</label>\r\n <input class=\"lcms-login-input\" id=\"lcms-login-email\" type=\"text\" placeholder=\"Enter your username\" autocomplete=\"username\" />\r\n </div>\r\n <div class=\"lcms-login-field\">\r\n <label class=\"lcms-login-label\">Password</label>\r\n <input class=\"lcms-login-input\" id=\"lcms-login-password\" type=\"password\" placeholder=\"Enter your password\" autocomplete=\"current-password\" />\r\n </div>\r\n <button class=\"lcms-login-btn\" id=\"lcms-login-btn\">Sign In</button>\r\n <div class=\"lcms-login-error\" id=\"lcms-login-error\"></div>\r\n </div>\r\n `;\r\n\r\n document.body.appendChild(overlay);\r\n this.loginModalEl = overlay;\r\n\r\n const btn = overlay.querySelector('#lcms-login-btn') as HTMLButtonElement;\r\n const emailInput = overlay.querySelector('#lcms-login-email') as HTMLInputElement;\r\n const passInput = overlay.querySelector('#lcms-login-password') as HTMLInputElement;\r\n\r\n const doLogin = () => this.attemptLogin(emailInput.value.trim(), passInput.value);\r\n btn.addEventListener('click', doLogin);\r\n passInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') doLogin(); });\r\n\r\n // Focus email field\r\n setTimeout(() => emailInput.focus(), 50);\r\n }\r\n\r\n private hideLoginModal(): void {\r\n this.loginModalEl?.remove();\r\n this.loginModalEl = null;\r\n }\r\n\r\n private async attemptLogin(email: string, password: string): Promise<void> {\r\n const btn = document.getElementById('lcms-login-btn') as HTMLButtonElement;\r\n const errorEl = document.getElementById('lcms-login-error') as HTMLElement;\r\n\r\n if (!email || !password) {\r\n errorEl.textContent = 'Please enter your username and password.';\r\n errorEl.classList.add('visible');\r\n return;\r\n }\r\n\r\n btn.disabled = true;\r\n btn.textContent = 'Signing in...';\r\n errorEl.classList.remove('visible');\r\n\r\n try {\r\n const loginUrl = this.config.loginUrl || `${this.config.apiBase}/auth/login`;\r\n const res = await fetch(loginUrl, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ username: email, password }),\r\n });\r\n\r\n // Try to parse body regardless of status (API may return error details in body)\r\n let data: any = null;\r\n try { data = await res.json(); } catch { /* ignore parse error */ }\r\n\r\n if (!res.ok) {\r\n // Show API error message if available (e.g. Xano: { message: \"Invalid credentials.\" })\r\n const apiMsg = data?.message || data?.error || null;\r\n throw new Error(apiMsg || `HTTP ${res.status}`);\r\n }\r\n\r\n // Store token — support common response shapes: { token }, { authToken }, { data: { token } }\r\n const token = data?.token || data?.authToken || data?.auth_token || data?.data?.token;\r\n if (!token) throw new Error('Login successful but no token returned.');\r\n\r\n localStorage.setItem('builder_token', token);\r\n this.hideLoginModal();\r\n\r\n // Now enable edit mode\r\n this.editMode = true;\r\n this.pendingEditMode = false;\r\n sessionStorage.setItem('builder_edit_mode', 'true');\r\n this.applyEditMode(true);\r\n this.updateUI();\r\n this.loadPageContent('draft');\r\n } catch (err: any) {\r\n btn.disabled = false;\r\n btn.textContent = 'Sign In';\r\n errorEl.textContent = err?.message || 'Login failed. Please try again.';\r\n errorEl.classList.add('visible');\r\n }\r\n }\r\n\r\n // ===============================================\r\n // SITE IDENTIFIER\r\n // ===============================================\r\n\r\n private resolveSiteIdentifier(): string {\r\n const hostname = window.location.hostname;\r\n if (hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.startsWith('192.168.')) {\r\n return hostname;\r\n }\r\n let id = localStorage.getItem('xtroedge_site_id');\r\n if (!id) {\r\n id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\r\n const r = Math.random() * 16 | 0;\r\n return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);\r\n });\r\n localStorage.setItem('xtroedge_site_id', id);\r\n }\r\n return id;\r\n }\r\n\r\n // ===============================================\r\n // THEME COLOR\r\n // ===============================================\r\n\r\n private hexToRgb(hex: string): string {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (!result) return '0,200,83';\r\n return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;\r\n }\r\n\r\n private getDarkerColor(hex: string): string {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (!result) return '#2E7D32';\r\n const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));\r\n const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));\r\n const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));\r\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\r\n }\r\n\r\n private applyThemeColor(color: string): void {\r\n this.highlightColor = color;\r\n document.documentElement.style.setProperty('--lcms-primary', color);\r\n document.documentElement.style.setProperty('--lcms-primary-rgb', this.hexToRgb(color));\r\n document.documentElement.style.setProperty('--lcms-primary-dark', this.getDarkerColor(color));\r\n\r\n // Re-apply highlight to managed elements\r\n if (this.editMode) {\r\n for (const [el] of this.managedElements) {\r\n el.style.outline = `2px dashed ${color}`;\r\n }\r\n for (const [img] of this.managedImages) {\r\n img.style.outline = `2px dashed ${color}`;\r\n }\r\n }\r\n\r\n // Update swatch active states\r\n const swatches = this.panelEl?.querySelectorAll('.lcms-theme-swatch');\r\n swatches?.forEach(s => {\r\n (s as HTMLElement).classList.toggle('active', (s as HTMLElement).dataset.color === color);\r\n });\r\n\r\n // Persist to localStorage\r\n localStorage.setItem('xtroedge_theme_color', color);\r\n }\r\n\r\n // ===============================================\r\n // STATIC CONVENIENCE\r\n // ===============================================\r\n\r\n /** Quick init - create and start CMS in one call */\r\n static create(config?: XtroedgeCmsConfig): XtroedgeCMS {\r\n const cms = new XtroedgeCMS(config);\r\n cms.init();\r\n return cms;\r\n }\r\n\r\n /** Auto-init: called automatically when package is loaded. No user code needed. */\r\n static autoInit(): void {\r\n // Prevent double init\r\n if ((window as any).__xtroedge_cms_instance__) return;\r\n\r\n const userConfig: XtroedgeCmsConfig = (window as any).__XTROEDGE_CMS_CONFIG__ || {};\r\n const cms = XtroedgeCMS.create(userConfig);\r\n (window as any).__xtroedge_cms_instance__ = cms;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/styles.ts","../src/xtroedge-cms.ts"],"sourcesContent":["export { XtroedgeCMS } from './xtroedge-cms';\r\nexport type {\r\n XtroedgeCmsConfig,\r\n PageTextEntry,\r\n WebPageContent,\r\n EditHistoryEntry,\r\n} from './types';\r\n\r\n// ===== AUTO-INIT =====\r\n// Automatically initializes CMS when the script loads.\r\n// No manual code needed - just install the package.\r\n// To pass config, set window.__XTROEDGE_CMS_CONFIG__ before loading.\r\nimport { XtroedgeCMS } from './xtroedge-cms';\r\n\r\nfunction boot() {\r\n XtroedgeCMS.autoInit();\r\n}\r\n\r\nif (typeof window !== 'undefined') {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', boot);\r\n } else {\r\n // DOM already ready (script loaded async/defer or after DOMContentLoaded)\r\n boot();\r\n }\r\n}\r\n","export const CMS_STYLES = `\r\n/* ===== XTROEDGE CMS ===== */\r\n\r\n/* LOADER */\r\n.lcms-loader-overlay {\r\n position: fixed; inset: 0; z-index: 10003;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.45);\r\n backdrop-filter: blur(12px) saturate(1.4);\r\n -webkit-backdrop-filter: blur(12px) saturate(1.4);\r\n}\r\n.lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }\r\n.lcms-orbit-loader { position: relative; width: 90px; height: 90px; }\r\n.lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }\r\n.lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }\r\n.lcms-orbit-2 { inset: 10px; border-right-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); animation: lcmsSpin 3.2s linear infinite reverse; }\r\n.lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }\r\n.lcms-particle {\r\n position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;\r\n box-shadow: 0 0 12px 3px currentColor;\r\n}\r\n.lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }\r\n.lcms-orbit-2 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.8); top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }\r\n.lcms-orbit-3 .lcms-particle { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); color: rgba(var(--lcms-primary-rgb, 0,200,83),0.6); top: auto; bottom: -4px; }\r\n.lcms-core-glow {\r\n position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);\r\n border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);\r\n animation: lcmsPulse 2s ease-in-out infinite;\r\n}\r\n.lcms-core {\r\n position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);\r\n border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));\r\n box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);\r\n}\r\n.lcms-loader-text {\r\n font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;\r\n color: rgba(255,255,255,0.5); letter-spacing: 4px; text-transform: uppercase;\r\n animation: lcmsBreath 2.5s ease-in-out infinite;\r\n}\r\n@keyframes lcmsSpin { to { transform: rotate(360deg); } }\r\n@keyframes lcmsPulse { 0%,100% { transform: translate(-50%,-50%) scale(1); opacity: 0.5; } 50% { transform: translate(-50%,-50%) scale(1.8); opacity: 0.2; } }\r\n@keyframes lcmsBreath { 0%,100% { letter-spacing: 4px; opacity: 0.5; } 50% { letter-spacing: 6px; opacity: 0.8; } }\r\n\r\n/* TOAST */\r\n.lcms-toast {\r\n position: fixed; top: 24px; left: 50%; transform: translateX(-50%); z-index: 10004;\r\n padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;\r\n font-family: system-ui, -apple-system, sans-serif; color: white;\r\n display: flex; align-items: center; gap: 8px;\r\n box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);\r\n animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;\r\n}\r\n.lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }\r\n.lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }\r\n@keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }\r\n@keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }\r\n\r\n/* FAB */\r\n.lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }\r\n.lcms-fab-btn {\r\n width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);\r\n background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;\r\n backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);\r\n cursor: grab; display: flex; align-items: center; justify-content: center;\r\n box-shadow: 0 4px 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.3), inset 0 1px 0 rgba(255,255,255,0.15);\r\n transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;\r\n}\r\n.lcms-fab-btn:not(.lcms-fab-active) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); }\r\n.lcms-fab-btn.lcms-fab-active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.4); box-shadow: 0 4px 24px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), 0 0 16px rgba(var(--lcms-primary-rgb, 0,200,83),0.2), inset 0 1px 0 rgba(255,255,255,0.2); }\r\n.lcms-fab-btn:hover { transform: scale(1.08); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); box-shadow: 0 6px 28px rgba(var(--lcms-primary-rgb, 0,200,83),0.4), inset 0 1px 0 rgba(255,255,255,0.2); }\r\n.lcms-badge {\r\n position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;\r\n font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;\r\n display: flex; align-items: center; justify-content: center; border: 2px solid white;\r\n}\r\n\r\n/* PANEL */\r\n.lcms-panel {\r\n background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);\r\n border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);\r\n color: white; font-family: system-ui, -apple-system, sans-serif;\r\n animation: lcmsPanelIn 0.25s ease; position: absolute;\r\n}\r\n@keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }\r\n\r\n/* SITE IDENTIFIER */\r\n.lcms-site-id {\r\n display: flex; align-items: center; gap: 5px;\r\n font-size: 10px; color: rgba(255,255,255,0.4);\r\n padding: 0 0 8px; margin-bottom: 8px;\r\n border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);\r\n font-family: system-ui, -apple-system, sans-serif;\r\n letter-spacing: 0.3px;\r\n}\r\n.lcms-site-id-icon { font-size: 12px; opacity: 0.7; }\r\n.lcms-site-id-text {\r\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;\r\n font-weight: 500;\r\n}\r\n\r\n/* BRANDING */\r\n.lcms-branding {\r\n display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;\r\n border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;\r\n cursor: pointer; transition: opacity 0.2s; user-select: none;\r\n}\r\n.lcms-branding:hover { opacity: 0.8; }\r\n.lcms-branding-logo {\r\n width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n display: flex; align-items: center; justify-content: center;\r\n}\r\n.lcms-branding-text {\r\n font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;\r\n}\r\n.lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }\r\n\r\n.lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }\r\n.lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }\r\n.lcms-toggle input { display: none; }\r\n.lcms-toggle-slider {\r\n width: 36px; height: 20px; border-radius: 10px; position: relative;\r\n background: rgba(255,255,255,0.15); transition: background 0.25s;\r\n}\r\n.lcms-toggle-slider::after {\r\n content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;\r\n top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;\r\n}\r\n.lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }\r\n.lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }\r\n.lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }\r\n.lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }\r\n.lcms-lang-switch { margin-left: auto; position: relative; }\r\n.lcms-lang-select { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.15); border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.4); border-radius: 6px; color: white; padding: 3px 24px 3px 8px; font-size: 11px; font-weight: 600; cursor: pointer; appearance: none; -webkit-appearance: none; outline: none; transition: all 0.2s; }\r\n.lcms-lang-select:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); }\r\n.lcms-lang-select:focus { border-color: var(--lcms-primary, #00C853); }\r\n.lcms-lang-select option { background: #1a1a2e; color: white; }\r\n.lcms-lang-arrow { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); pointer-events: none; color: rgba(255,255,255,0.6); font-size: 10px; }\r\n.lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }\r\n.lcms-close-btn:hover { color: white; }\r\n.lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }\r\n\r\n.lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }\r\n.lcms-icon-btn {\r\n width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);\r\n background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;\r\n display: flex; align-items: center; justify-content: center; transition: all 0.2s;\r\n}\r\n.lcms-icon-btn:hover:not(:disabled) { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }\r\n.lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }\r\n\r\n/* COLOR THEME PICKER */\r\n.lcms-theme-row {\r\n display: flex; align-items: center; gap: 8px; margin-bottom: 12px;\r\n padding: 6px 0;\r\n}\r\n.lcms-theme-label {\r\n font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);\r\n text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;\r\n}\r\n.lcms-theme-colors {\r\n display: flex; align-items: center; gap: 5px; flex-wrap: wrap;\r\n}\r\n.lcms-theme-swatch {\r\n width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;\r\n cursor: pointer; transition: all 0.2s; position: relative;\r\n}\r\n.lcms-theme-swatch:hover { transform: scale(1.15); }\r\n.lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }\r\n.lcms-theme-custom {\r\n width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);\r\n cursor: pointer; overflow: hidden; position: relative;\r\n}\r\n.lcms-theme-custom input {\r\n position: absolute; inset: -4px; width: 28px; height: 28px; border: none;\r\n background: transparent; cursor: pointer; opacity: 0;\r\n}\r\n.lcms-theme-custom-preview {\r\n width: 100%; height: 100%; border-radius: 50%;\r\n background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);\r\n}\r\n\r\n.lcms-history-btn {\r\n width: 100%; padding: 7px 12px; border-radius: 8px;\r\n border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);\r\n color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;\r\n display: flex; align-items: center; justify-content: center; gap: 6px;\r\n transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-history-btn:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.18); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); color: white; }\r\n.lcms-history-btn.active { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-color: var(--lcms-primary, #00C853); border-style: solid; color: white; }\r\n\r\n.lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }\r\n.lcms-history-title { font-size: 11px; font-weight: 700; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; }\r\n.lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }\r\n.lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }\r\n.lcms-history-list::-webkit-scrollbar { width: 4px; }\r\n.lcms-history-list::-webkit-scrollbar-track { background: transparent; }\r\n.lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }\r\n.lcms-history-item {\r\n width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);\r\n border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;\r\n cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-history-item:hover { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.15); border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); }\r\n.lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }\r\n.lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }\r\n.lcms-history-lang { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }\r\n\r\n.lcms-actions { display: flex; flex-direction: column; gap: 6px; }\r\n.lcms-actions button {\r\n width: 100%; padding: 9px 14px; border-radius: 8px; font-size: 12px; font-weight: 600;\r\n cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;\r\n font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }\r\n.lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }\r\n.lcms-btn-save:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }\r\n.lcms-btn-publish { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); color: white; }\r\n.lcms-btn-publish:hover { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); filter: brightness(1.1); }\r\n.lcms-btn-publish:disabled { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; filter: none; }\r\n.lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25) !important; }\r\n.lcms-btn-cancel:hover { color: white; border-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5) !important; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08); }\r\n.lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }\r\n.lcms-btn-logout { background: rgba(244,67,54,0.12); color: rgba(244,67,54,0.85); border: 1px solid rgba(244,67,54,0.25) !important; margin-top: 4px; }\r\n.lcms-btn-logout:hover { background: rgba(244,67,54,0.2); color: #f44336; border-color: rgba(244,67,54,0.5) !important; }\r\n\r\n.lcms-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }\r\n\r\n/* IMAGE UPLOAD OVERLAY */\r\n.lcms-img-upload-overlay {\r\n position: fixed; inset: 0; z-index: 10005;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);\r\n}\r\n.lcms-img-upload-content {\r\n display: flex; flex-direction: column; align-items: center; gap: 16px;\r\n color: white; font-family: system-ui, -apple-system, sans-serif;\r\n font-size: 13px; font-weight: 600;\r\n}\r\n.lcms-spinner-lg { width: 36px; height: 36px; border: 3px solid rgba(255,255,255,0.2); border-top-color: var(--lcms-primary, #00C853); border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }\r\n\r\n/* LOGIN MODAL */\r\n.lcms-login-overlay {\r\n position: fixed; inset: 0; z-index: 10010;\r\n display: flex; align-items: center; justify-content: center;\r\n background: rgba(8, 8, 15, 0.75);\r\n backdrop-filter: blur(16px) saturate(1.4);\r\n -webkit-backdrop-filter: blur(16px) saturate(1.4);\r\n font-family: system-ui, -apple-system, sans-serif;\r\n}\r\n.lcms-login-box {\r\n background: #13151a; border: 1px solid rgba(255,255,255,0.1);\r\n border-radius: 16px; padding: 36px 32px; width: 340px;\r\n box-shadow: 0 24px 60px rgba(0,0,0,0.6);\r\n}\r\n.lcms-login-logo {\r\n display: flex; align-items: center; justify-content: center;\r\n gap: 8px; margin-bottom: 24px;\r\n}\r\n.lcms-login-logo-icon {\r\n width: 32px; height: 32px; border-radius: 8px;\r\n background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n display: flex; align-items: center; justify-content: center;\r\n}\r\n.lcms-login-logo-text { color: white; font-size: 15px; font-weight: 700; letter-spacing: 0.5px; }\r\n.lcms-login-title { color: white; font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 6px; }\r\n.lcms-login-sub { color: rgba(255,255,255,0.4); font-size: 12px; text-align: center; margin-bottom: 24px; }\r\n.lcms-login-field { margin-bottom: 14px; }\r\n.lcms-login-label { display: block; color: rgba(255,255,255,0.6); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 6px; }\r\n.lcms-login-input {\r\n width: 100%; box-sizing: border-box;\r\n background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12);\r\n border-radius: 8px; padding: 10px 12px;\r\n color: white; font-size: 13px; font-family: inherit; outline: none;\r\n transition: border-color 0.2s;\r\n}\r\n.lcms-login-input:focus { border-color: var(--lcms-primary, #00C853); }\r\n.lcms-login-input::placeholder { color: rgba(255,255,255,0.25); }\r\n.lcms-login-btn {\r\n width: 100%; padding: 11px; margin-top: 6px; border: none; border-radius: 8px; cursor: pointer;\r\n background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));\r\n color: white; font-size: 13px; font-weight: 700; font-family: inherit;\r\n letter-spacing: 0.3px; transition: filter 0.2s;\r\n}\r\n.lcms-login-btn:hover { filter: brightness(1.1); }\r\n.lcms-login-btn:disabled { opacity: 0.6; cursor: not-allowed; }\r\n.lcms-login-error {\r\n background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.3);\r\n border-radius: 8px; padding: 9px 12px; color: #f87171;\r\n font-size: 12px; text-align: center; margin-top: 12px; display: none;\r\n}\r\n.lcms-login-error.visible { display: block; }\r\n\r\n/* HIDDEN ELEMENTS */\r\n.lcms-hidden { display: none !important; }\r\n`;\r\n","import { CMS_STYLES } from './styles';\r\nimport type {\r\n XtroedgeCmsConfig, PageTextEntry, WebPageContent,\r\n EditHistoryEntry, ManagedElementInfo, ManagedImageInfo\r\n} from './types';\r\n\r\n// ===== SVG Icons =====\r\nconst ICON = {\r\n edit: '<svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>',\r\n close: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>',\r\n undo: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>',\r\n redo: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"23 4 23 10 17 10\"/><path d=\"M20.49 15a9 9 0 1 1-2.13-9.36L23 10\"/></svg>',\r\n history: '<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/></svg>',\r\n save: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z\"/><polyline points=\"17 21 17 13 7 13 7 21\"/><polyline points=\"7 3 7 8 15 8\"/></svg>',\r\n publish: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"17 1 21 5 17 9\"/><path d=\"M3 11V9a4 4 0 0 1 4-4h14\"/></svg>',\r\n image: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>',\r\n check: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6L9 17l-5-5\"/></svg>',\r\n error: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/></svg>',\r\n logout: '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/><polyline points=\"16 17 21 12 16 7\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/></svg>',\r\n};\r\n\r\n// ===== IndexedDB constants =====\r\nconst DB_NAME = 'xtroedge_cms_history';\r\nconst STORE_NAME = 'history';\r\n\r\n// ===== Default editable tags =====\r\nconst DEFAULT_EDITABLE_TAGS = [\r\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\r\n 'p', 'span', 'b', 'strong', 'i', 'em',\r\n 'a', 'button', 'li', 'label', 'small', 'blockquote', 'td', 'th',\r\n 'div', 'header', 'footer',\r\n];\r\n\r\nexport class XtroedgeCMS {\r\n // ===== Config =====\r\n private config: XtroedgeCmsConfig;\r\n private containerSelector: string;\r\n private editableTags: string[];\r\n private languages: string[];\r\n private defaultLanguage: string;\r\n private highlightColor: string;\r\n private brandingEl: HTMLElement | null = null;\r\n private historyRetentionMs: number;\r\n private siteIdentifier = '';\r\n private siteIdEl: HTMLElement | null = null;\r\n private loginModalEl: HTMLElement | null = null;\r\n private pendingEditMode = false; // edit=true was requested but token missing\r\n\r\n // ===== State =====\r\n private editMode = false;\r\n private currentLang = 'en';\r\n private pageTexts: { [key: string]: PageTextEntry } = {};\r\n private pageImages: { [key: string]: string } = {};\r\n private originalTexts: { [key: string]: PageTextEntry } = {};\r\n private originalImages: { [key: string]: string } = {};\r\n private unsavedChanges = 0;\r\n private isSaving = false;\r\n private isPublishing = false;\r\n private loading = false;\r\n private canUndo = false;\r\n private canRedo = false;\r\n private showHistory = false;\r\n private historyList: EditHistoryEntry[] = [];\r\n private isOpen = false;\r\n private isEditAllowed = false;\r\n private imageUploading = false;\r\n private toastMessage = '';\r\n private toastType: 'success' | 'error' = 'success';\r\n\r\n // ===== Undo/Redo =====\r\n private undoStack: string[] = [];\r\n private redoStack: string[] = [];\r\n private dirtyKeys = new Set<string>();\r\n private dirtyImageKeys = new Set<string>();\r\n private registeredKeys = new Set<string>();\r\n\r\n // ===== DOM =====\r\n private managedElements = new Map<HTMLElement, ManagedElementInfo>();\r\n private managedImages = new Map<HTMLImageElement, ManagedImageInfo>();\r\n private autoDetectedElements = new Set<HTMLElement>();\r\n private observer: MutationObserver | null = null;\r\n private scanTimeout: ReturnType<typeof setTimeout> | null = null;\r\n private activeImageEl: HTMLImageElement | null = null;\r\n private imageCtxMenu: HTMLElement | null = null;\r\n\r\n // ===== Navigation =====\r\n private currentSlug = '';\r\n private currentTitle = '';\r\n private initialized = false;\r\n private origPushState: typeof history.pushState | null = null;\r\n private origReplaceState: typeof history.replaceState | null = null;\r\n\r\n // ===== UI Elements =====\r\n private styleEl: HTMLStyleElement | null = null;\r\n private rootEl: HTMLElement | null = null;\r\n private loaderEl: HTMLElement | null = null;\r\n private toastEl: HTMLElement | null = null;\r\n private fabEl: HTMLElement | null = null;\r\n private fabBtn: HTMLButtonElement | null = null;\r\n private badgeEl: HTMLElement | null = null;\r\n private panelEl: HTMLElement | null = null;\r\n private editToggle: HTMLInputElement | null = null;\r\n private langSwitchEl: HTMLElement | null = null;\r\n private changesInfoEl: HTMLElement | null = null;\r\n private undoBtn: HTMLButtonElement | null = null;\r\n private redoBtn: HTMLButtonElement | null = null;\r\n private historyBtnEl: HTMLButtonElement | null = null;\r\n private historyPanelEl: HTMLElement | null = null;\r\n private historyListEl: HTMLElement | null = null;\r\n private saveBtn: HTMLButtonElement | null = null;\r\n private publishBtn: HTMLButtonElement | null = null;\r\n\r\n private actionsEl: HTMLElement | null = null;\r\n private editModeContent: HTMLElement | null = null;\r\n private fileInput: HTMLInputElement | null = null;\r\n private imgOverlay: HTMLElement | null = null;\r\n\r\n // ===== FAB Drag =====\r\n private posX = 20;\r\n private posY = 20;\r\n private isDragging = false;\r\n private dragStartX = 0;\r\n private dragStartY = 0;\r\n private startPosX = 0;\r\n private startPosY = 0;\r\n private hasMoved = false;\r\n\r\n // ===== Timers =====\r\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n // ===== IndexedDB =====\r\n private db: IDBDatabase | null = null;\r\n\r\n // ===== Bound handlers =====\r\n private boundMouseMove: (e: MouseEvent) => void;\r\n private boundMouseUp: () => void;\r\n private boundTouchMove: (e: TouchEvent) => void;\r\n private boundTouchEnd: () => void;\r\n private boundPopState: () => void;\r\n private boundHashChange: () => void;\r\n\r\n // ===== i18n cache =====\r\n private translationCache = new Map<string, string>();\r\n\r\n constructor(config?: XtroedgeCmsConfig) {\r\n this.config = config || {};\r\n this.containerSelector = this.config.containerSelector || '';\r\n this.editableTags = (this.config.editableTags || DEFAULT_EDITABLE_TAGS).map(t => t.toLowerCase());\r\n this.languages = this.config.languages || ['en'];\r\n this.defaultLanguage = this.config.defaultLanguage || this.languages[0] || 'en';\r\n this.highlightColor = this.config.highlightColor || '#00C853';\r\n this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1000;\r\n this.currentLang = this.defaultLanguage;\r\n this.siteIdentifier = this.resolveSiteIdentifier();\r\n\r\n // Load persisted theme color from localStorage\r\n const savedColor = localStorage.getItem('xtroedge_theme_color');\r\n if (savedColor) this.highlightColor = savedColor;\r\n\r\n // Bind handlers\r\n this.boundMouseMove = (e) => this.onDragMove(e);\r\n this.boundMouseUp = () => this.onDragEnd();\r\n this.boundTouchMove = (e) => this.onTouchMove(e);\r\n this.boundTouchEnd = () => this.onTouchEnd();\r\n this.boundPopState = () => this.handleNavigation();\r\n this.boundHashChange = () => this.handleNavigation();\r\n }\r\n\r\n // ===============================================\r\n // PUBLIC API\r\n // ===============================================\r\n\r\n init(): void {\r\n this.posY = window.innerHeight - 72;\r\n this.injectStyles();\r\n this.applyThemeColor(this.highlightColor);\r\n this.buildUI();\r\n this.interceptNavigation();\r\n\r\n // MutationObserver for auto-scanning\r\n this.observer = new MutationObserver(() => {\r\n // Re-append CMS UI if removed by framework hydration (Next.js, React, etc.)\r\n if (this.rootEl && !document.contains(this.rootEl)) {\r\n document.body.appendChild(this.rootEl);\r\n }\r\n if (this.styleEl && !document.contains(this.styleEl)) {\r\n document.head.appendChild(this.styleEl);\r\n }\r\n if (this.scanTimeout) clearTimeout(this.scanTimeout);\r\n this.scanTimeout = setTimeout(() => this.autoDetectAndScan(), 150);\r\n });\r\n this.observer.observe(document.body, { childList: true, subtree: true });\r\n\r\n // Listen for navigation events\r\n window.addEventListener('popstate', this.boundPopState);\r\n window.addEventListener('hashchange', this.boundHashChange);\r\n\r\n // Initial navigation\r\n this.handleNavigation();\r\n }\r\n\r\n destroy(): void {\r\n this.cleanupManagedElements();\r\n\r\n // Remove UI\r\n this.styleEl?.remove();\r\n this.rootEl?.remove();\r\n\r\n // Remove listeners\r\n window.removeEventListener('popstate', this.boundPopState);\r\n window.removeEventListener('hashchange', this.boundHashChange);\r\n document.removeEventListener('mousemove', this.boundMouseMove);\r\n document.removeEventListener('mouseup', this.boundMouseUp);\r\n document.removeEventListener('touchmove', this.boundTouchMove);\r\n document.removeEventListener('touchend', this.boundTouchEnd);\r\n\r\n // Restore navigation\r\n if (this.origPushState) history.pushState = this.origPushState;\r\n if (this.origReplaceState) history.replaceState = this.origReplaceState;\r\n\r\n // Disconnect observer\r\n this.observer?.disconnect();\r\n if (this.scanTimeout) clearTimeout(this.scanTimeout);\r\n if (this.toastTimer) clearTimeout(this.toastTimer);\r\n\r\n this.db?.close();\r\n }\r\n\r\n // ===============================================\r\n // STYLES INJECTION\r\n // ===============================================\r\n\r\n private injectStyles(): void {\r\n if (document.getElementById('xtroedge-cms-styles')) return;\r\n this.styleEl = document.createElement('style');\r\n this.styleEl.id = 'xtroedge-cms-styles';\r\n this.styleEl.textContent = CMS_STYLES;\r\n document.head.appendChild(this.styleEl);\r\n }\r\n\r\n // ===============================================\r\n // NAVIGATION INTERCEPTION\r\n // ===============================================\r\n\r\n private interceptNavigation(): void {\r\n this.origPushState = history.pushState.bind(history);\r\n this.origReplaceState = history.replaceState.bind(history);\r\n const self = this;\r\n history.pushState = function (...args) {\r\n self.origPushState!(...args);\r\n setTimeout(() => self.handleNavigation(), 0);\r\n };\r\n history.replaceState = function (...args) {\r\n self.origReplaceState!(...args);\r\n setTimeout(() => self.handleNavigation(), 0);\r\n };\r\n }\r\n\r\n private handleNavigation(): void {\r\n const url = window.location.href;\r\n const pathname = window.location.pathname || '/';\r\n const hash = window.location.hash || '';\r\n\r\n // Support hash routing: #/page?edit=true\r\n let path: string;\r\n let searchStr: string;\r\n if (hash.startsWith('#/') || hash.startsWith('#!')) {\r\n const hashPath = hash.replace(/^#[!/]*/, '');\r\n const qIdx = hashPath.indexOf('?');\r\n path = qIdx >= 0 ? hashPath.substring(0, qIdx) : hashPath;\r\n searchStr = qIdx >= 0 ? hashPath.substring(qIdx) : '';\r\n } else {\r\n path = pathname.replace(/^\\//, '') || 'home';\r\n searchStr = window.location.search;\r\n }\r\n\r\n const slug = '/' + (path.replace(/^\\//, '') || 'home');\r\n const params = new URLSearchParams(searchStr);\r\n const editViaParam = params.get('edit') === 'true';\r\n\r\n this.isEditAllowed = editViaParam || sessionStorage.getItem('builder_edit_mode') === 'true';\r\n\r\n const slugChanged = slug !== this.currentSlug;\r\n if (slugChanged) {\r\n this.cleanupManagedElements();\r\n this.currentSlug = slug;\r\n this.currentTitle = (path.replace(/^\\//, '') || 'home').replace(/-/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase()) + ' Page';\r\n this.resetAll();\r\n }\r\n\r\n // Restore edit mode — check builder_token first\r\n const editFromSession = sessionStorage.getItem('builder_edit_mode') === 'true';\r\n const wantsEdit = editViaParam || editFromSession;\r\n\r\n if (wantsEdit) {\r\n const token = localStorage.getItem('builder_token');\r\n if (!token) {\r\n // No token → show login modal, do NOT enable edit mode yet\r\n if (!this.pendingEditMode) {\r\n this.pendingEditMode = true;\r\n this.currentLang = this.detectCurrentLanguage();\r\n this.setLoading(true);\r\n setTimeout(() => {\r\n this.loadTranslationsAndInit(false);\r\n this.showLoginModal();\r\n }, 300);\r\n }\r\n return;\r\n }\r\n this.editMode = true;\r\n }\r\n\r\n // Skip reload if same slug and already initialized\r\n if (!slugChanged && this.initialized) {\r\n this.updateUI();\r\n return;\r\n }\r\n\r\n this.currentLang = this.detectCurrentLanguage();\r\n\r\n // Show loader\r\n this.setLoading(true);\r\n\r\n // Auto-detect after DOM settles, then load content\r\n this.initialized = true;\r\n const loadDraft = wantsEdit;\r\n setTimeout(() => {\r\n this.loadTranslationsAndInit(loadDraft);\r\n }, 300);\r\n }\r\n\r\n // ===============================================\r\n // BUILD UI\r\n // ===============================================\r\n\r\n private buildUI(): void {\r\n this.rootEl = document.createElement('div');\r\n this.rootEl.id = 'xtroedge-cms-root';\r\n\r\n // Loader\r\n this.loaderEl = this.createElement('div', 'lcms-loader-overlay lcms-hidden');\r\n this.loaderEl.innerHTML = `<div class=\"lcms-loader-content\">\r\n <div class=\"lcms-orbit-loader\">\r\n <div class=\"lcms-orbit lcms-orbit-1\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-orbit lcms-orbit-2\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-orbit lcms-orbit-3\"><span class=\"lcms-particle\"></span></div>\r\n <div class=\"lcms-core-glow\"></div>\r\n <div class=\"lcms-core\"></div>\r\n </div>\r\n <span class=\"lcms-loader-text\">Loading</span>\r\n </div>`;\r\n this.rootEl.appendChild(this.loaderEl);\r\n\r\n // Toast\r\n this.toastEl = this.createElement('div', 'lcms-toast lcms-hidden');\r\n this.rootEl.appendChild(this.toastEl);\r\n\r\n // FAB\r\n this.fabEl = this.createElement('div', 'lcms-fab');\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n this.fabEl.addEventListener('mousedown', (e) => this.onDragStart(e));\r\n this.fabEl.addEventListener('touchstart', (e) => this.onTouchStart(e), { passive: true });\r\n\r\n // FAB button\r\n this.fabBtn = document.createElement('button');\r\n this.fabBtn.className = 'lcms-fab-btn';\r\n this.fabBtn.innerHTML = ICON.edit;\r\n this.fabBtn.addEventListener('click', (e) => this.onFabClick(e));\r\n this.badgeEl = this.createElement('span', 'lcms-badge lcms-hidden');\r\n this.fabBtn.appendChild(this.badgeEl);\r\n this.fabEl.appendChild(this.fabBtn);\r\n\r\n // Panel\r\n this.panelEl = this.createElement('div', 'lcms-panel lcms-hidden');\r\n this.buildPanel();\r\n this.fabEl.appendChild(this.panelEl);\r\n\r\n this.rootEl.appendChild(this.fabEl);\r\n\r\n // Hidden file input\r\n this.fileInput = document.createElement('input');\r\n this.fileInput.type = 'file';\r\n this.fileInput.accept = 'image/*';\r\n this.fileInput.style.display = 'none';\r\n this.fileInput.addEventListener('change', (e) => this.onImageFileSelected(e));\r\n this.rootEl.appendChild(this.fileInput);\r\n\r\n // Image upload overlay\r\n this.imgOverlay = this.createElement('div', 'lcms-img-upload-overlay lcms-hidden');\r\n this.imgOverlay.innerHTML = `<div class=\"lcms-img-upload-content\"><div class=\"lcms-spinner-lg\"></div><span>Uploading image...</span></div>`;\r\n this.rootEl.appendChild(this.imgOverlay);\r\n\r\n document.body.appendChild(this.rootEl);\r\n }\r\n\r\n private buildPanel(): void {\r\n if (!this.panelEl) return;\r\n\r\n // Header\r\n const header = this.createElement('div', 'lcms-panel-header');\r\n\r\n // Edit toggle\r\n const toggleLabel = this.createElement('label', 'lcms-toggle');\r\n toggleLabel.addEventListener('click', (e) => e.stopPropagation());\r\n this.editToggle = document.createElement('input');\r\n this.editToggle.type = 'checkbox';\r\n this.editToggle.checked = this.editMode;\r\n this.editToggle.addEventListener('change', (e) => this.toggleEditMode(e));\r\n const slider = this.createElement('span', 'lcms-toggle-slider');\r\n const labelText = this.createElement('span', 'lcms-toggle-label');\r\n labelText.textContent = 'Edit';\r\n toggleLabel.appendChild(this.editToggle);\r\n toggleLabel.appendChild(slider);\r\n toggleLabel.appendChild(labelText);\r\n header.appendChild(toggleLabel);\r\n\r\n // Language switch\r\n this.langSwitchEl = this.createElement('div', 'lcms-lang-switch lcms-hidden');\r\n this.buildLangButtons();\r\n header.appendChild(this.langSwitchEl);\r\n\r\n // Close button\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'lcms-close-btn';\r\n closeBtn.innerHTML = ICON.close;\r\n closeBtn.addEventListener('click', (e) => { e.stopPropagation(); this.togglePanel(); });\r\n header.appendChild(closeBtn);\r\n\r\n this.panelEl.appendChild(header);\r\n\r\n // Site identifier\r\n this.siteIdEl = this.createElement('div', 'lcms-site-id');\r\n const isDomain = this.siteIdentifier.includes('.');\r\n this.siteIdEl.innerHTML = `<span class=\"lcms-site-id-icon\">${isDomain ? '\\u{1F310}' : '\\u{1F511}'}</span><span class=\"lcms-site-id-text\">${isDomain ? this.siteIdentifier : this.siteIdentifier.substring(0, 8)}</span>`;\r\n this.panelEl.appendChild(this.siteIdEl);\r\n\r\n // Edit mode content (hidden when edit mode off)\r\n this.editModeContent = this.createElement('div', 'lcms-hidden');\r\n\r\n // Changes info\r\n this.changesInfoEl = this.createElement('div', 'lcms-changes-info lcms-hidden');\r\n this.editModeContent.appendChild(this.changesInfoEl);\r\n\r\n // Undo/Redo row\r\n const undoRow = this.createElement('div', 'lcms-undo-row');\r\n this.undoBtn = document.createElement('button');\r\n this.undoBtn.className = 'lcms-icon-btn';\r\n this.undoBtn.innerHTML = ICON.undo;\r\n this.undoBtn.disabled = true;\r\n this.undoBtn.addEventListener('click', (e) => { e.stopPropagation(); this.onUndo(); });\r\n this.redoBtn = document.createElement('button');\r\n this.redoBtn.className = 'lcms-icon-btn';\r\n this.redoBtn.innerHTML = ICON.redo;\r\n this.redoBtn.disabled = true;\r\n this.redoBtn.addEventListener('click', (e) => { e.stopPropagation(); this.onRedo(); });\r\n undoRow.appendChild(this.undoBtn);\r\n undoRow.appendChild(this.redoBtn);\r\n this.editModeContent.appendChild(undoRow);\r\n\r\n // Color theme picker\r\n const themeRow = this.createElement('div', 'lcms-theme-row');\r\n const themeLabel = this.createElement('span', 'lcms-theme-label');\r\n themeLabel.textContent = 'Theme';\r\n themeRow.appendChild(themeLabel);\r\n const themeColors = this.createElement('div', 'lcms-theme-colors');\r\n const presetColors = ['#00C853', '#6722FB', '#2196F3', '#FF5722', '#E91E63', '#FFD600'];\r\n for (const color of presetColors) {\r\n const swatch = this.createElement('div', 'lcms-theme-swatch');\r\n swatch.style.background = color;\r\n swatch.dataset.color = color;\r\n if (color === this.highlightColor) swatch.classList.add('active');\r\n swatch.addEventListener('click', (e) => { e.stopPropagation(); this.applyThemeColor(color); });\r\n themeColors.appendChild(swatch);\r\n }\r\n // Custom color input\r\n const customSwatch = this.createElement('div', 'lcms-theme-custom');\r\n const customPreview = this.createElement('div', 'lcms-theme-custom-preview');\r\n const customInput = document.createElement('input');\r\n customInput.type = 'color';\r\n customInput.value = this.highlightColor;\r\n customInput.addEventListener('input', (e) => { e.stopPropagation(); this.applyThemeColor((e.target as HTMLInputElement).value); });\r\n customSwatch.appendChild(customPreview);\r\n customSwatch.appendChild(customInput);\r\n themeColors.appendChild(customSwatch);\r\n themeRow.appendChild(themeColors);\r\n this.editModeContent.appendChild(themeRow);\r\n\r\n // History button\r\n this.historyBtnEl = document.createElement('button');\r\n this.historyBtnEl.className = 'lcms-history-btn';\r\n this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;\r\n this.historyBtnEl.addEventListener('click', (e) => { e.stopPropagation(); this.toggleHistory(); });\r\n this.editModeContent.appendChild(this.historyBtnEl);\r\n\r\n // History panel\r\n this.historyPanelEl = this.createElement('div', 'lcms-history-panel lcms-hidden');\r\n const historyTitle = this.createElement('div', 'lcms-history-title');\r\n historyTitle.textContent = 'Edit History';\r\n this.historyPanelEl.appendChild(historyTitle);\r\n this.historyListEl = this.createElement('div', 'lcms-history-list');\r\n this.historyPanelEl.appendChild(this.historyListEl);\r\n this.editModeContent.appendChild(this.historyPanelEl);\r\n\r\n // Actions\r\n this.actionsEl = this.createElement('div', 'lcms-actions');\r\n this.saveBtn = document.createElement('button');\r\n this.saveBtn.className = 'lcms-btn-save';\r\n this.saveBtn.innerHTML = `${ICON.save} Save Draft`;\r\n this.saveBtn.addEventListener('click', (e) => { e.stopPropagation(); this.saveChanges(); });\r\n this.publishBtn = document.createElement('button');\r\n this.publishBtn.className = 'lcms-btn-publish';\r\n this.publishBtn.innerHTML = `${ICON.publish} Publish`;\r\n this.publishBtn.addEventListener('click', (e) => { e.stopPropagation(); this.publishChanges(); });\r\n const logoutBtn = document.createElement('button');\r\n logoutBtn.className = 'lcms-btn-logout';\r\n logoutBtn.innerHTML = `${ICON.logout} Logout`;\r\n logoutBtn.addEventListener('click', (e) => { e.stopPropagation(); this.logout(); });\r\n this.actionsEl.appendChild(this.saveBtn);\r\n this.actionsEl.appendChild(this.publishBtn);\r\n this.actionsEl.appendChild(logoutBtn);\r\n this.editModeContent.appendChild(this.actionsEl);\r\n\r\n this.panelEl.appendChild(this.editModeContent);\r\n\r\n // Branding\r\n this.brandingEl = this.createElement('div', 'lcms-branding');\r\n this.brandingEl.innerHTML = `<div class=\"lcms-branding-logo\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6L9 17l-5-5\"/></svg></div><div class=\"lcms-branding-text\">Powered by <span>XtroEdge</span></div>`;\r\n this.brandingEl.addEventListener('click', (e) => { e.stopPropagation(); window.open('https://xtro.vercel.app/', '_blank'); });\r\n this.panelEl.appendChild(this.brandingEl);\r\n }\r\n\r\n private buildLangButtons(): void {\r\n if (!this.langSwitchEl) return;\r\n this.langSwitchEl.innerHTML = '';\r\n const select = document.createElement('select');\r\n select.className = 'lcms-lang-select';\r\n for (const lang of this.languages) {\r\n const opt = document.createElement('option');\r\n opt.value = lang;\r\n opt.textContent = lang.toUpperCase();\r\n if (lang === this.currentLang) opt.selected = true;\r\n select.appendChild(opt);\r\n }\r\n select.addEventListener('change', (e) => { e.stopPropagation(); this.switchLang((e.target as HTMLSelectElement).value); });\r\n this.langSwitchEl.appendChild(select);\r\n const arrow = document.createElement('span');\r\n arrow.className = 'lcms-lang-arrow';\r\n arrow.textContent = '\\u25BC';\r\n this.langSwitchEl.appendChild(arrow);\r\n }\r\n\r\n // ===============================================\r\n // UI UPDATE\r\n // ===============================================\r\n\r\n private updateUI(): void {\r\n // FAB visibility\r\n if (this.fabEl) {\r\n this.fabEl.style.display = this.isEditAllowed ? '' : 'none';\r\n }\r\n\r\n // FAB button vs panel\r\n if (this.fabBtn) {\r\n this.fabBtn.style.display = this.isOpen ? 'none' : '';\r\n this.fabBtn.classList.toggle('lcms-fab-active', this.editMode);\r\n }\r\n if (this.panelEl) {\r\n this.panelEl.classList.toggle('lcms-hidden', !this.isOpen);\r\n // Position panel\r\n if (this.isOpen) {\r\n const openUp = this.posY > window.innerHeight / 2;\r\n const openLeft = this.posX > window.innerWidth / 2;\r\n this.panelEl.style.bottom = openUp ? '0' : '';\r\n this.panelEl.style.top = openUp ? '' : '0';\r\n this.panelEl.style.right = openLeft ? '0' : '';\r\n this.panelEl.style.left = openLeft ? '' : '0';\r\n }\r\n }\r\n\r\n // Badge\r\n if (this.badgeEl) {\r\n this.badgeEl.classList.toggle('lcms-hidden', this.unsavedChanges === 0);\r\n this.badgeEl.textContent = String(this.unsavedChanges);\r\n }\r\n\r\n // Edit toggle\r\n if (this.editToggle) this.editToggle.checked = this.editMode;\r\n\r\n // Lang switch\r\n if (this.langSwitchEl) {\r\n this.langSwitchEl.classList.toggle('lcms-hidden', !this.editMode || this.languages.length <= 1);\r\n const sel = this.langSwitchEl.querySelector('.lcms-lang-select') as HTMLSelectElement | null;\r\n if (sel) sel.value = this.currentLang;\r\n }\r\n\r\n // Edit mode content\r\n if (this.editModeContent) {\r\n this.editModeContent.classList.toggle('lcms-hidden', !this.editMode);\r\n }\r\n\r\n // Changes info\r\n if (this.changesInfoEl) {\r\n this.changesInfoEl.classList.toggle('lcms-hidden', this.unsavedChanges === 0);\r\n this.changesInfoEl.textContent = `${this.unsavedChanges} unsaved change${this.unsavedChanges > 1 ? 's' : ''}`;\r\n }\r\n\r\n // Undo/Redo\r\n if (this.undoBtn) this.undoBtn.disabled = !this.canUndo;\r\n if (this.redoBtn) this.redoBtn.disabled = !this.canRedo;\r\n\r\n // History button\r\n if (this.historyBtnEl) this.historyBtnEl.classList.toggle('active', this.showHistory);\r\n if (this.historyPanelEl) this.historyPanelEl.classList.toggle('lcms-hidden', !this.showHistory);\r\n\r\n // Save/Publish buttons\r\n if (this.saveBtn) {\r\n this.saveBtn.disabled = this.isSaving || this.isPublishing || this.unsavedChanges === 0;\r\n this.saveBtn.innerHTML = this.isSaving ? '<span class=\"lcms-spinner\"></span> Saving...' : `${ICON.save} Save Draft`;\r\n }\r\n if (this.publishBtn) {\r\n this.publishBtn.disabled = this.isSaving || this.isPublishing;\r\n this.publishBtn.innerHTML = this.isPublishing ? '<span class=\"lcms-spinner\"></span> Publishing...' : `${ICON.publish} Publish`;\r\n }\r\n\r\n // Loader\r\n if (this.loaderEl) this.loaderEl.classList.toggle('lcms-hidden', !this.loading);\r\n\r\n // Image overlay\r\n if (this.imgOverlay) this.imgOverlay.classList.toggle('lcms-hidden', !this.imageUploading);\r\n }\r\n\r\n // ===============================================\r\n // DOM SCANNING\r\n // ===============================================\r\n\r\n private autoDetectAndScan(): void {\r\n this.autoDetectElements();\r\n this.scanDOM();\r\n this.scanImages();\r\n }\r\n\r\n private resolveContainer(): Element {\r\n if (this.containerSelector) {\r\n return document.querySelector(this.containerSelector) || document.body;\r\n }\r\n return document.body;\r\n }\r\n\r\n private autoDetectElements(): void {\r\n const container = this.resolveContainer();\r\n if (!container) return;\r\n\r\n // Clean up stale auto-detected elements\r\n for (const el of this.autoDetectedElements) {\r\n if (!document.contains(el)) this.autoDetectedElements.delete(el);\r\n }\r\n\r\n // Detect section slug based on ancestor tag name\r\n // Tags ending with '-header' or being <header> → /header\r\n // Tags ending with '-footer' or being <footer> → /footer\r\n const getSectionSlug = (el: HTMLElement): string => {\r\n let parent: HTMLElement | null = el.parentElement;\r\n while (parent && parent !== document.body) {\r\n const tag = parent.tagName.toLowerCase();\r\n if (tag === 'header' || tag.endsWith('-header')) return '/header';\r\n if (tag === 'footer' || tag.endsWith('-footer')) return '/footer';\r\n parent = parent.parentElement;\r\n }\r\n return this.currentSlug;\r\n };\r\n\r\n // Section-aware tag counters to avoid key collisions across sections\r\n const tagCounters: { [section: string]: { [tag: string]: number } } = {};\r\n\r\n const assignKey = (el: HTMLElement, sectionSlug: string) => {\r\n const sectionKey = sectionSlug === '/header' ? 'header'\r\n : sectionSlug === '/footer' ? 'footer' : 'page';\r\n if (!tagCounters[sectionKey]) tagCounters[sectionKey] = {};\r\n const tag = el.tagName.toLowerCase();\r\n if (!tagCounters[sectionKey][tag]) tagCounters[sectionKey][tag] = 0;\r\n const prefix = sectionKey !== 'page' ? `${sectionKey}_` : '';\r\n const key = `${prefix}xcms_${tag}_${tagCounters[sectionKey][tag]}`;\r\n tagCounters[sectionKey][tag]++;\r\n el.setAttribute('data-cms', key);\r\n el.setAttribute('data-cms-section', sectionSlug); // used during save/load\r\n this.autoDetectedElements.add(el);\r\n };\r\n\r\n // Scan standard editable tags (h1, p, div, etc.)\r\n const selector = this.editableTags.join(',');\r\n const elements = container.querySelectorAll<HTMLElement>(selector);\r\n elements.forEach(el => {\r\n if (el.hasAttribute('data-cms')) return;\r\n if (el.closest('#xtroedge-cms-root, script, style, noscript')) return;\r\n if (el.children.length > 3) return;\r\n const text = this.getDirectTextContent(el).trim();\r\n if (text.length < 2) return;\r\n assignKey(el, getSectionSlug(el));\r\n });\r\n\r\n // Scan [data-editable] elements — works with ANY tag (app-header, app-footer, custom components)\r\n // No children/text restrictions since user explicitly marked them\r\n const dataEditables = container.querySelectorAll<HTMLElement>('[data-editable]');\r\n dataEditables.forEach(el => {\r\n if (el.hasAttribute('data-cms')) return;\r\n if (el.closest('#xtroedge-cms-root, script, style, noscript')) return;\r\n assignKey(el, getSectionSlug(el));\r\n });\r\n }\r\n\r\n private scanDOM(): void {\r\n const elements = document.querySelectorAll<HTMLElement>('[data-cms]');\r\n elements.forEach(el => {\r\n if (el.closest('#xtroedge-cms-root')) return;\r\n const key = el.getAttribute('data-cms')!;\r\n this.registeredKeys.add(key);\r\n if (!this.managedElements.has(el)) {\r\n this.attachElement(el, key);\r\n }\r\n });\r\n // Cleanup removed elements\r\n for (const [el] of this.managedElements) {\r\n if (!document.contains(el)) this.detachElement(el);\r\n }\r\n }\r\n\r\n private scanImages(): void {\r\n const container = this.resolveContainer();\r\n if (!container) return;\r\n const currentImages = { ...this.pageImages };\r\n let hasNew = false;\r\n const images = container.querySelectorAll<HTMLImageElement>('img');\r\n images.forEach(img => {\r\n if (img.closest('#xtroedge-cms-root')) return;\r\n if (this.managedImages.has(img)) return;\r\n const src = img.getAttribute('src') || '';\r\n if (!src || src.startsWith('data:')) return;\r\n this.attachImage(img, src);\r\n if (!currentImages[src]) {\r\n currentImages[src] = src;\r\n hasNew = true;\r\n }\r\n });\r\n if (hasNew) {\r\n this.pageImages = currentImages;\r\n this.originalImages = JSON.parse(JSON.stringify(currentImages));\r\n }\r\n for (const [img] of this.managedImages) {\r\n if (!document.contains(img)) this.detachImage(img);\r\n }\r\n }\r\n\r\n private getDirectTextContent(el: HTMLElement): string {\r\n let text = '';\r\n for (let i = 0; i < el.childNodes.length; i++) {\r\n if (el.childNodes[i].nodeType === Node.TEXT_NODE) {\r\n text += el.childNodes[i].textContent || '';\r\n }\r\n }\r\n return text;\r\n }\r\n\r\n // ===============================================\r\n // ELEMENT EDITING\r\n // ===============================================\r\n\r\n private attachElement(el: HTMLElement, key: string): void {\r\n const blurHandler = () => {\r\n const text = el.textContent?.trim() || '';\r\n const currentVal = this.getPageText(key);\r\n if (text !== currentVal) this.onTextChanged(key, text);\r\n };\r\n const keydownHandler = (e: KeyboardEvent) => {\r\n if (e.key === 'Enter') { e.preventDefault(); el.blur(); }\r\n };\r\n const inputHandler = () => {\r\n const text = el.textContent?.trim() || '';\r\n const currentVal = this.getPageText(key);\r\n if (text !== currentVal) this.onTextChanged(key, text);\r\n };\r\n // Prevent click navigation (for <a routerLink> and href links) in edit mode\r\n const clickHandler = (e: Event) => {\r\n const isLink = el.tagName === 'A' || (e.target as HTMLElement).closest('a');\r\n if (isLink) {\r\n e.preventDefault();\r\n e.stopPropagation(); // Stop Angular routerLink from navigating\r\n el.focus(); // Manually focus so contenteditable caret works\r\n }\r\n };\r\n const sectionSlug = el.getAttribute('data-cms-section') || this.currentSlug;\r\n this.managedElements.set(el, { key, sectionSlug, blurHandler, keydownHandler, inputHandler, clickHandler });\r\n if (this.editMode) this.enableElementEdit(el, key, blurHandler, keydownHandler, inputHandler, clickHandler);\r\n }\r\n\r\n private detachElement(el: HTMLElement): void {\r\n const info = this.managedElements.get(el);\r\n if (info) {\r\n el.removeEventListener('blur', info.blurHandler);\r\n el.removeEventListener('keydown', info.keydownHandler as EventListener);\r\n el.removeEventListener('input', info.inputHandler);\r\n el.removeEventListener('click', info.clickHandler, true);\r\n el.removeAttribute('contenteditable');\r\n this.managedElements.delete(el);\r\n }\r\n }\r\n\r\n private enableElementEdit(el: HTMLElement, _key: string, blurH: (e: Event) => void, keyH: (e: KeyboardEvent) => void, inputH: (e: Event) => void, clickH: (e: Event) => void): void {\r\n const val = this.getPageText(_key);\r\n if (val) el.textContent = val;\r\n el.setAttribute('contenteditable', 'true');\r\n el.style.outline = `2px dashed ${this.highlightColor}`;\r\n el.style.outlineOffset = '-2px';\r\n el.style.cursor = 'text';\r\n el.style.transition = 'background 0.2s';\r\n el.style.minWidth = '20px';\r\n el.addEventListener('blur', blurH);\r\n el.addEventListener('keydown', keyH as EventListener);\r\n el.addEventListener('input', inputH);\r\n el.addEventListener('click', clickH, true); // capture phase — prevents Angular routerLink navigation\r\n }\r\n\r\n private disableElementEdit(el: HTMLElement, _key: string, blurH: (e: Event) => void, keyH: (e: KeyboardEvent) => void, inputH: (e: Event) => void, clickH: (e: Event) => void): void {\r\n el.removeAttribute('contenteditable');\r\n el.style.outline = '';\r\n el.style.outline = '';\r\n el.style.outlineOffset = '';\r\n el.style.cursor = '';\r\n el.style.transition = '';\r\n el.style.minWidth = '';\r\n const val = this.getPageText(_key);\r\n if (val) el.textContent = val;\r\n el.removeEventListener('blur', blurH);\r\n el.removeEventListener('keydown', keyH as EventListener);\r\n el.removeEventListener('input', inputH);\r\n el.removeEventListener('click', clickH, true);\r\n }\r\n\r\n private applyEditMode(editMode: boolean): void {\r\n for (const [el, info] of this.managedElements) {\r\n if (editMode) this.enableElementEdit(el, info.key, info.blurHandler, info.keydownHandler, info.inputHandler, info.clickHandler);\r\n else this.disableElementEdit(el, info.key, info.blurHandler, info.keydownHandler, info.inputHandler, info.clickHandler);\r\n }\r\n this.applyImageEditMode(editMode);\r\n }\r\n\r\n private updateElementTexts(): void {\r\n this.observer?.disconnect();\r\n for (const [el, info] of this.managedElements) {\r\n if (document.activeElement === el) continue;\r\n const val = this.getPageText(info.key);\r\n if (val && el.textContent !== val) el.textContent = val;\r\n }\r\n this.observer?.observe(document.body, { childList: true, subtree: true });\r\n }\r\n\r\n private cleanupManagedElements(): void {\r\n for (const [el] of this.managedElements) this.detachElement(el);\r\n this.managedElements.clear();\r\n for (const el of this.autoDetectedElements) el.removeAttribute('data-cms');\r\n this.autoDetectedElements.clear();\r\n this.cleanupManagedImages();\r\n }\r\n\r\n // ===============================================\r\n // IMAGE MANAGEMENT\r\n // ===============================================\r\n\r\n private attachImage(img: HTMLImageElement, key: string): void {\r\n const ctxHandler = (e: MouseEvent) => {\r\n if (!this.editMode) return;\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.showImageContextMenu(e.clientX, e.clientY, img);\r\n };\r\n this.managedImages.set(img, { key, ctxHandler });\r\n if (this.editMode) this.enableImageEdit(img, ctxHandler);\r\n }\r\n\r\n private detachImage(img: HTMLImageElement): void {\r\n const info = this.managedImages.get(img);\r\n if (info) {\r\n img.removeEventListener('contextmenu', info.ctxHandler);\r\n img.style.outline = '';\r\n img.style.cursor = '';\r\n this.managedImages.delete(img);\r\n }\r\n }\r\n\r\n private cleanupManagedImages(): void {\r\n for (const [img] of this.managedImages) this.detachImage(img);\r\n this.managedImages.clear();\r\n this.dismissImageCtxMenu();\r\n }\r\n\r\n private applyImageEditMode(editMode: boolean): void {\r\n for (const [img, info] of this.managedImages) {\r\n if (editMode) this.enableImageEdit(img, info.ctxHandler);\r\n else this.disableImageEdit(img, info.ctxHandler);\r\n }\r\n if (!editMode) this.dismissImageCtxMenu();\r\n }\r\n\r\n private enableImageEdit(img: HTMLImageElement, ctxHandler: (e: MouseEvent) => void): void {\r\n if (!img.dataset.origTitle) img.dataset.origTitle = img.title || '';\r\n img.title = 'Right-click to change image';\r\n img.style.outline = `2px dashed ${this.highlightColor}`;\r\n img.style.cursor = 'context-menu';\r\n img.addEventListener('contextmenu', ctxHandler);\r\n }\r\n\r\n private disableImageEdit(img: HTMLImageElement, ctxHandler: (e: MouseEvent) => void): void {\r\n img.title = img.dataset.origTitle || '';\r\n delete img.dataset.origTitle;\r\n img.style.outline = '';\r\n img.style.cursor = '';\r\n img.removeEventListener('contextmenu', ctxHandler);\r\n }\r\n\r\n private showImageContextMenu(x: number, y: number, img: HTMLImageElement): void {\r\n this.dismissImageCtxMenu();\r\n const menu = document.createElement('div');\r\n Object.assign(menu.style, {\r\n position: 'fixed', zIndex: '10005', minWidth: '160px',\r\n background: 'rgba(30,15,60,0.85)', backdropFilter: 'blur(16px)', webkitBackdropFilter: 'blur(16px)',\r\n border: '1px solid rgba(139,92,246,0.3)', borderRadius: '10px', padding: '4px',\r\n boxShadow: '0 8px 32px rgba(0,0,0,0.4)', fontFamily: 'system-ui, -apple-system, sans-serif',\r\n left: Math.min(x, window.innerWidth - 180) + 'px',\r\n top: Math.min(y, window.innerHeight - 50) + 'px',\r\n });\r\n const btn = document.createElement('button');\r\n Object.assign(btn.style, {\r\n width: '100%', padding: '8px 12px', border: 'none', borderRadius: '7px',\r\n background: 'transparent', color: 'white', fontSize: '12px', fontWeight: '500',\r\n cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '8px',\r\n });\r\n btn.innerHTML = `${ICON.image} Upload Image`;\r\n btn.addEventListener('mouseenter', () => btn.style.background = 'rgba(103,34,251,0.3)');\r\n btn.addEventListener('mouseleave', () => btn.style.background = 'transparent');\r\n btn.addEventListener('click', () => {\r\n this.activeImageEl = img;\r\n if (this.fileInput) { this.fileInput.value = ''; this.fileInput.click(); }\r\n this.dismissImageCtxMenu();\r\n });\r\n menu.appendChild(btn);\r\n document.body.appendChild(menu);\r\n this.imageCtxMenu = menu;\r\n\r\n const closeHandler = (e: MouseEvent) => {\r\n if (!menu.contains(e.target as Node)) {\r\n this.dismissImageCtxMenu();\r\n document.removeEventListener('mousedown', closeHandler);\r\n }\r\n };\r\n setTimeout(() => document.addEventListener('mousedown', closeHandler), 0);\r\n }\r\n\r\n private dismissImageCtxMenu(): void {\r\n if (this.imageCtxMenu) {\r\n this.imageCtxMenu.remove();\r\n this.imageCtxMenu = null;\r\n }\r\n }\r\n\r\n private onImageFileSelected(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n const file = input.files?.[0];\r\n if (!file || !this.activeImageEl) return;\r\n\r\n this.imageUploading = true;\r\n this.updateUI();\r\n\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n const dataUrl = reader.result as string;\r\n this.uploadImageToApi(dataUrl);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n\r\n private async uploadImageToApi(dataUrl: string): Promise<void> {\r\n try {\r\n const res = await this.apiFetch(`${this.config.apiBase}/web/upload-image`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ url: dataUrl }),\r\n });\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n const data = await res.json();\r\n const baseUrl = this.config.imageBaseUrl || (this.config.apiBase ? new URL(this.config.apiBase).origin : '');\r\n const fullUrl = baseUrl + data.path;\r\n if (this.activeImageEl) {\r\n const key = this.managedImages.get(this.activeImageEl)?.key || '';\r\n this.activeImageEl.src = fullUrl;\r\n this.onImageChanged(key, fullUrl);\r\n }\r\n this.imageUploading = false;\r\n this.activeImageEl = null;\r\n this.updateUI();\r\n this.showToast('Image updated!', 'success');\r\n } catch (err) {\r\n this.imageUploading = false;\r\n this.activeImageEl = null;\r\n this.updateUI();\r\n this.showToast('Image upload failed.', 'error');\r\n this.config.onError?.('upload-image', err);\r\n }\r\n }\r\n\r\n private applyPageImages(): void {\r\n for (const [img, info] of this.managedImages) {\r\n const url = this.pageImages[info.key];\r\n if (url && img.src !== url) img.src = url;\r\n }\r\n }\r\n\r\n // ===============================================\r\n // TEXT STATE\r\n // ===============================================\r\n\r\n private getPageText(key: string): string {\r\n return this.pageTexts[key]?.[this.currentLang] || '';\r\n }\r\n\r\n private onTextChanged(key: string, newValue: string): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.redoStack = [];\r\n this.canUndo = true;\r\n this.canRedo = false;\r\n\r\n if (!this.pageTexts[key]) this.pageTexts[key] = {};\r\n this.pageTexts[key] = { ...this.pageTexts[key], [this.currentLang]: newValue };\r\n this.dirtyKeys.add(key);\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n this.pushHistory(key, this.currentLang);\r\n this.updateUI();\r\n }\r\n\r\n private onImageChanged(key: string, url: string): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.redoStack = [];\r\n this.canUndo = true;\r\n this.canRedo = false;\r\n\r\n this.pageImages = { ...this.pageImages, [key]: url };\r\n this.dirtyImageKeys.add(key);\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n this.pushHistory(key, 'img');\r\n this.updateUI();\r\n }\r\n\r\n private createSnapshot(): string {\r\n return JSON.stringify({ texts: this.pageTexts, images: this.pageImages });\r\n }\r\n\r\n private applySnapshot(raw: string): void {\r\n const data = JSON.parse(raw);\r\n if (data.texts) {\r\n this.pageTexts = data.texts;\r\n if (data.images) this.pageImages = data.images;\r\n } else {\r\n this.pageTexts = data;\r\n }\r\n }\r\n\r\n // ===============================================\r\n // UNDO / REDO\r\n // ===============================================\r\n\r\n private onUndo(): void {\r\n if (this.undoStack.length === 0) return;\r\n this.redoStack.push(this.createSnapshot());\r\n this.applySnapshot(this.undoStack.pop()!);\r\n this.canUndo = this.undoStack.length > 0;\r\n this.canRedo = true;\r\n this.recalcDirtyKeys();\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private onRedo(): void {\r\n if (this.redoStack.length === 0) return;\r\n this.undoStack.push(this.createSnapshot());\r\n this.applySnapshot(this.redoStack.pop()!);\r\n this.canUndo = true;\r\n this.canRedo = this.redoStack.length > 0;\r\n this.recalcDirtyKeys();\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private recalcDirtyKeys(): void {\r\n this.dirtyKeys.clear();\r\n for (const key of this.registeredKeys) {\r\n if (JSON.stringify(this.pageTexts[key]) !== JSON.stringify(this.originalTexts[key])) {\r\n this.dirtyKeys.add(key);\r\n }\r\n }\r\n this.unsavedChanges = this.dirtyKeys.size + this.dirtyImageKeys.size;\r\n }\r\n\r\n private resetAll(): void {\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.undoStack = [];\r\n this.redoStack = [];\r\n this.canUndo = false;\r\n this.canRedo = false;\r\n this.updateUI();\r\n }\r\n\r\n private resetAfterSave(): void {\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n }\r\n\r\n private cancelEditing(): void {\r\n this.pageTexts = JSON.parse(JSON.stringify(this.originalTexts));\r\n this.pageImages = JSON.parse(JSON.stringify(this.originalImages));\r\n this.dirtyKeys.clear();\r\n this.dirtyImageKeys.clear();\r\n this.unsavedChanges = 0;\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n }\r\n\r\n private logout(): void {\r\n localStorage.removeItem('builder_token');\r\n sessionStorage.removeItem('builder_edit_mode');\r\n this.editMode = false;\r\n this.isEditAllowed = false;\r\n this.applyEditMode(false);\r\n this.isOpen = false;\r\n this.updateUI();\r\n this.showToast('Logged out', 'success');\r\n }\r\n\r\n // ===============================================\r\n // API\r\n // ===============================================\r\n\r\n private async loadTranslationsAndInit(loadDraft: boolean): Promise<void> {\r\n if (this.config.i18nBasePath) {\r\n try {\r\n const lang = this.currentLang;\r\n const res = await fetch(`${this.config.i18nBasePath}/${lang}.json`);\r\n if (res.ok) {\r\n const translations = await res.json();\r\n this.translationCache.clear();\r\n this.flattenTranslations(translations, '', this.getPageSection());\r\n }\r\n } catch { /* ignore */ }\r\n }\r\n\r\n this.autoDetectAndScan();\r\n if (this.editMode) this.applyEditMode(true);\r\n if (this.config.apiBase) {\r\n if (loadDraft) this.loadPageContent('draft');\r\n else this.loadPublishedContent();\r\n } else {\r\n this.buildDefaultTexts();\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.setLoading(false);\r\n }\r\n this.updateUI();\r\n }\r\n\r\n private flattenTranslations(obj: any, prefix: string, pageSection: string): void {\r\n for (const k of Object.keys(obj)) {\r\n const fullKey = prefix ? `${prefix}.${k}` : k;\r\n if (typeof obj[k] === 'string') {\r\n const text = obj[k].trim();\r\n if (text.length >= 2) {\r\n const existing = this.translationCache.get(text);\r\n if (!existing || fullKey.toUpperCase().startsWith(pageSection)) {\r\n this.translationCache.set(text, fullKey);\r\n }\r\n }\r\n } else if (typeof obj[k] === 'object' && obj[k] !== null && !Array.isArray(obj[k])) {\r\n this.flattenTranslations(obj[k], fullKey, pageSection);\r\n }\r\n }\r\n }\r\n\r\n private getPageSection(): string {\r\n return this.currentSlug.replace(/^\\//, '').replace(/-/g, '_').toUpperCase();\r\n }\r\n\r\n // Authenticated fetch — adds Authorization header from builder_token\r\n private apiFetch(url: string, opts?: RequestInit): Promise<Response> {\r\n const token = localStorage.getItem('builder_token') || '';\r\n const headers: Record<string, string> = { ...(opts?.headers as Record<string, string> || {}) };\r\n if (token) headers['Authorization'] = `Bearer ${token}`;\r\n return fetch(url, { ...opts, headers });\r\n }\r\n\r\n // Fetch texts for a single slug and merge into pageTexts\r\n private async fetchSection(slug: string, status: 'draft' | 'published'): Promise<WebPageContent | null> {\r\n try {\r\n const res = await this.apiFetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(slug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);\r\n if (!res.ok) return null;\r\n return await res.json();\r\n } catch { return null; }\r\n }\r\n\r\n private hasSection(type: 'header' | 'footer'): boolean {\r\n if (type === 'header') return !!(document.querySelector('header') || document.querySelector('[class*=\"-header\"]') || document.querySelector('[tagName$=\"-header\"]'));\r\n return !!(document.querySelector('footer') || document.querySelector('[class*=\"-footer\"]') || document.querySelector('[tagName$=\"-footer\"]'));\r\n }\r\n\r\n private async loadPageContent(status: 'draft' | 'published'): Promise<void> {\r\n this.setLoading(true);\r\n this.cleanOldHistory();\r\n\r\n try {\r\n // Only fetch sections that exist in the DOM\r\n const requests: Promise<WebPageContent | null>[] = [this.fetchSection(this.currentSlug, status)];\r\n const hasHeader = this.hasSection('header');\r\n const hasFooter = this.hasSection('footer');\r\n if (hasHeader) requests.push(this.fetchSection('/header', status));\r\n if (hasFooter) requests.push(this.fetchSection('/footer', status));\r\n\r\n const results = await Promise.all(requests);\r\n const pageSec = results[0];\r\n const headerSec = hasHeader ? results[1] : null;\r\n const footerSec = hasFooter ? results[hasHeader ? 2 : 1] : null;\r\n\r\n const getTexts = (sec: WebPageContent | null) => sec?.content?.texts || sec?.published_content?.texts || null;\r\n const pageTexts = getTexts(pageSec);\r\n const headerTexts = getTexts(headerSec);\r\n const footerTexts = getTexts(footerSec);\r\n\r\n if (pageTexts || headerTexts || footerTexts) {\r\n this.pageTexts = { ...(pageTexts || {}), ...(headerTexts || {}), ...(footerTexts || {}) };\r\n } else {\r\n this.buildDefaultTexts();\r\n }\r\n\r\n // Extract images from the page response (no extra API call)\r\n const images = pageSec?.content?.images || pageSec?.published_content?.images;\r\n if (images) {\r\n this.pageImages = JSON.parse(JSON.stringify(images));\r\n this.applyPageImages();\r\n }\r\n\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.resetAll();\r\n this.updateElementTexts();\r\n } catch {\r\n this.buildDefaultTexts();\r\n this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));\r\n this.originalImages = JSON.parse(JSON.stringify(this.pageImages));\r\n this.resetAll();\r\n } finally {\r\n this.setLoading(false);\r\n }\r\n }\r\n\r\n private async loadPublishedContent(): Promise<void> {\r\n this.setLoading(true);\r\n\r\n try {\r\n // Only fetch sections that exist in the DOM\r\n const requests: Promise<WebPageContent | null>[] = [this.fetchSection(this.currentSlug, 'published')];\r\n const hasHeader = this.hasSection('header');\r\n const hasFooter = this.hasSection('footer');\r\n if (hasHeader) requests.push(this.fetchSection('/header', 'published'));\r\n if (hasFooter) requests.push(this.fetchSection('/footer', 'published'));\r\n\r\n const results = await Promise.all(requests);\r\n const pageSec = results[0];\r\n const headerSec = hasHeader ? results[1] : null;\r\n const footerSec = hasFooter ? results[hasHeader ? 2 : 1] : null;\r\n\r\n const getTexts = (sec: WebPageContent | null) => sec?.published_content?.texts || null;\r\n const merged = { ...(getTexts(pageSec) || {}), ...(getTexts(headerSec) || {}), ...(getTexts(footerSec) || {}) };\r\n if (Object.keys(merged).length > 0) {\r\n this.pageTexts = JSON.parse(JSON.stringify(merged));\r\n this.updateElementTexts();\r\n }\r\n\r\n // Extract images from page response (no extra API call)\r\n const images = pageSec?.published_content?.images;\r\n if (images && Object.keys(images).length > 0) {\r\n this.pageImages = JSON.parse(JSON.stringify(images));\r\n this.applyPageImages();\r\n }\r\n } catch { /* ignore - use current DOM text */ }\r\n finally { this.setLoading(false); }\r\n }\r\n\r\n private buildDefaultTexts(): void {\r\n const texts: { [key: string]: PageTextEntry } = {};\r\n for (const key of this.registeredKeys) {\r\n const el = document.querySelector(`[data-cms=\"${key}\"]`);\r\n const val = el?.textContent?.trim() || '';\r\n texts[key] = { [this.currentLang]: val };\r\n }\r\n this.pageTexts = texts;\r\n\r\n // Load other languages from i18n files if available\r\n if (this.config.i18nBasePath) {\r\n const otherLangs = this.languages.filter(l => l !== this.currentLang);\r\n for (const lang of otherLangs) {\r\n fetch(`${this.config.i18nBasePath}/${lang}.json`)\r\n .then(r => r.json())\r\n .then(translations => {\r\n const updated = { ...this.pageTexts };\r\n for (const key of this.registeredKeys) {\r\n // Try to resolve key path in translations\r\n const parts = key.split('.');\r\n let val: any = translations;\r\n for (const part of parts) { val = val?.[part]; }\r\n if (val && typeof val === 'string') {\r\n updated[key] = { ...updated[key], [lang]: val };\r\n }\r\n }\r\n this.pageTexts = updated;\r\n this.originalTexts = JSON.parse(JSON.stringify(updated));\r\n this.updateElementTexts();\r\n })\r\n .catch(() => { /* ignore */ });\r\n }\r\n }\r\n }\r\n\r\n // Group pageTexts by section slug based on managedElements info\r\n private groupTextsBySection(): { [sectionSlug: string]: { [key: string]: PageTextEntry } } {\r\n const sections: { [sectionSlug: string]: { [key: string]: PageTextEntry } } = {};\r\n for (const [, info] of this.managedElements) {\r\n const slug = info.sectionSlug;\r\n if (!sections[slug]) sections[slug] = {};\r\n if (this.pageTexts[info.key] !== undefined) {\r\n sections[slug][info.key] = this.pageTexts[info.key];\r\n }\r\n }\r\n return sections;\r\n }\r\n\r\n private async saveChanges(): Promise<void> {\r\n if (!this.config.apiBase) {\r\n this.showToast('No API configured. Set apiBase to enable save.', 'error');\r\n return;\r\n }\r\n this.isSaving = true;\r\n this.updateUI();\r\n\r\n try {\r\n const sections = this.groupTextsBySection();\r\n const requests = Object.entries(sections).map(([slug, texts]) =>\r\n this.apiFetch(`${this.config.apiBase}/web_page/save`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n slug,\r\n title: slug === this.currentSlug ? this.currentTitle : slug.replace('/', ''),\r\n site_identifier: this.siteIdentifier,\r\n content: { texts, ...(slug === this.currentSlug ? { images: this.pageImages } : {}) }\r\n }),\r\n })\r\n );\r\n const results = await Promise.all(requests);\r\n if (results.some(r => !r.ok)) throw new Error('One or more sections failed to save');\r\n this.isSaving = false;\r\n this.resetAfterSave();\r\n this.updateUI();\r\n this.showToast('Draft saved successfully!', 'success');\r\n this.config.onSaved?.();\r\n } catch (err) {\r\n this.isSaving = false;\r\n this.updateUI();\r\n this.showToast('Save failed. Please try again.', 'error');\r\n this.config.onError?.('save', err);\r\n }\r\n }\r\n\r\n private async publishChanges(): Promise<void> {\r\n if (!this.config.apiBase) {\r\n this.showToast('No API configured. Set apiBase to enable publish.', 'error');\r\n return;\r\n }\r\n this.isPublishing = true;\r\n this.updateUI();\r\n\r\n try {\r\n const sections = this.groupTextsBySection();\r\n const requests = Object.entries(sections).map(([slug, texts]) =>\r\n this.apiFetch(`${this.config.apiBase}/web_page/publish`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n slug,\r\n title: slug === this.currentSlug ? this.currentTitle : slug.replace('/', ''),\r\n site_identifier: this.siteIdentifier,\r\n published_content: { texts, ...(slug === this.currentSlug ? { images: this.pageImages } : {}) }\r\n }),\r\n })\r\n );\r\n const results = await Promise.all(requests);\r\n if (results.some(r => !r.ok)) throw new Error('One or more sections failed to publish');\r\n this.isPublishing = false;\r\n this.resetAfterSave();\r\n this.updateUI();\r\n this.showToast('Published successfully!', 'success');\r\n this.config.onPublished?.();\r\n } catch (err) {\r\n this.isPublishing = false;\r\n this.updateUI();\r\n this.showToast('Publish failed. Please try again.', 'error');\r\n this.config.onError?.('publish', err);\r\n }\r\n }\r\n\r\n // ===============================================\r\n // HISTORY (IndexedDB)\r\n // ===============================================\r\n\r\n private async toggleHistory(): Promise<void> {\r\n this.showHistory = !this.showHistory;\r\n if (this.showHistory) await this.loadHistory();\r\n this.updateUI();\r\n }\r\n\r\n private async loadHistory(): Promise<void> {\r\n try {\r\n const db = await this.openDB();\r\n const entries = await new Promise<EditHistoryEntry[]>((resolve, reject) => {\r\n const tx = db.transaction(STORE_NAME, 'readonly');\r\n const store = tx.objectStore(STORE_NAME);\r\n const index = store.index('slug');\r\n const req = index.getAll(this.currentSlug);\r\n req.onsuccess = () => resolve((req.result as EditHistoryEntry[]).sort((a, b) => b.timestamp - a.timestamp).slice(0, 30));\r\n req.onerror = () => reject(req.error);\r\n });\r\n this.historyList = entries;\r\n this.renderHistoryList();\r\n } catch { /* ignore */ }\r\n }\r\n\r\n private renderHistoryList(): void {\r\n if (!this.historyListEl) return;\r\n this.historyListEl.innerHTML = '';\r\n if (this.historyList.length === 0) {\r\n const empty = this.createElement('div', 'lcms-history-empty');\r\n empty.textContent = 'No history yet';\r\n this.historyListEl.appendChild(empty);\r\n return;\r\n }\r\n for (const entry of this.historyList) {\r\n const item = document.createElement('button');\r\n item.className = 'lcms-history-item';\r\n const labelEl = this.createElement('div', 'lcms-history-label');\r\n labelEl.textContent = entry.label;\r\n const metaEl = this.createElement('div', 'lcms-history-meta');\r\n const langEl = this.createElement('span', 'lcms-history-lang');\r\n langEl.textContent = entry.lang.toUpperCase();\r\n const dateText = document.createTextNode(' ' + this.formatDate(entry.timestamp));\r\n metaEl.appendChild(langEl);\r\n metaEl.appendChild(dateText);\r\n item.appendChild(labelEl);\r\n item.appendChild(metaEl);\r\n item.addEventListener('click', (e) => { e.stopPropagation(); this.restoreHistory(entry); });\r\n this.historyListEl.appendChild(item);\r\n }\r\n }\r\n\r\n private restoreHistory(entry: EditHistoryEntry): void {\r\n this.undoStack.push(this.createSnapshot());\r\n this.canUndo = true;\r\n this.applySnapshot(entry.snapshot);\r\n this.recalcDirtyKeys();\r\n this.showHistory = false;\r\n this.updateElementTexts();\r\n this.applyPageImages();\r\n this.updateUI();\r\n this.showToast('Restored from history', 'success');\r\n }\r\n\r\n private pushHistory(key: string, lang: string): void {\r\n const isImage = lang === 'img';\r\n const shortKey = isImage ? key.split('/').pop() || 'image' : (key.split('_').pop() || key);\r\n const label = isImage ? `Changed ${shortKey}` : `Edited ${shortKey}`;\r\n this.openDB().then(db => {\r\n const tx = db.transaction(STORE_NAME, 'readwrite');\r\n tx.objectStore(STORE_NAME).add({\r\n slug: this.currentSlug, timestamp: Date.now(),\r\n label, lang,\r\n snapshot: JSON.stringify({ texts: this.pageTexts, images: this.pageImages })\r\n });\r\n }).catch(() => { /* ignore */ });\r\n }\r\n\r\n private async cleanOldHistory(): Promise<void> {\r\n try {\r\n const db = await this.openDB();\r\n const cutoff = Date.now() - this.historyRetentionMs;\r\n const tx = db.transaction(STORE_NAME, 'readwrite');\r\n const index = tx.objectStore(STORE_NAME).index('timestamp');\r\n const req = index.openCursor(IDBKeyRange.upperBound(cutoff));\r\n req.onsuccess = () => { const c = req.result; if (c) { c.delete(); c.continue(); } };\r\n } catch { /* ignore */ }\r\n }\r\n\r\n private openDB(): Promise<IDBDatabase> {\r\n if (this.db) return Promise.resolve(this.db);\r\n return new Promise((resolve, reject) => {\r\n const req = indexedDB.open(DB_NAME, 1);\r\n req.onupgradeneeded = () => {\r\n const db = req.result;\r\n if (!db.objectStoreNames.contains(STORE_NAME)) {\r\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });\r\n store.createIndex('slug', 'slug', { unique: false });\r\n store.createIndex('timestamp', 'timestamp', { unique: false });\r\n }\r\n };\r\n req.onsuccess = () => { this.db = req.result; resolve(this.db); };\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n // ===============================================\r\n // TOAST\r\n // ===============================================\r\n\r\n private showToast(message: string, type: 'success' | 'error'): void {\r\n if (!this.toastEl) return;\r\n this.toastMessage = message;\r\n this.toastType = type;\r\n\r\n const icon = type === 'success' ? ICON.check : ICON.error;\r\n this.toastEl.className = `lcms-toast lcms-toast-${type}`;\r\n this.toastEl.innerHTML = `${icon} ${message}`;\r\n\r\n if (this.toastTimer) clearTimeout(this.toastTimer);\r\n this.toastTimer = setTimeout(() => {\r\n if (this.toastEl) this.toastEl.classList.add('lcms-hidden');\r\n }, 3000);\r\n }\r\n\r\n // ===============================================\r\n // FAB & PANEL\r\n // ===============================================\r\n\r\n private onFabClick(e: Event): void {\r\n e.stopPropagation();\r\n if (this.hasMoved) return;\r\n this.isOpen = !this.isOpen;\r\n this.updateUI();\r\n }\r\n\r\n private togglePanel(): void {\r\n if (!this.hasMoved) {\r\n this.isOpen = !this.isOpen;\r\n this.updateUI();\r\n }\r\n }\r\n\r\n private toggleEditMode(e: Event): void {\r\n e.stopPropagation();\r\n const checked = (e.target as HTMLInputElement).checked;\r\n if (checked) {\r\n sessionStorage.setItem('builder_edit_mode', 'true');\r\n this.editMode = true;\r\n this.currentLang = this.detectCurrentLanguage();\r\n this.applyEditMode(true);\r\n this.loadPageContent('draft');\r\n } else {\r\n sessionStorage.removeItem('builder_edit_mode');\r\n this.editMode = false;\r\n this.applyEditMode(false);\r\n }\r\n this.updateUI();\r\n this.config.onEditModeChanged?.(this.editMode);\r\n }\r\n\r\n private switchLang(lang: string): void {\r\n this.currentLang = lang;\r\n\r\n // 1. Persist language so framework picks it up after reload\r\n localStorage.setItem('selectedLanguage', lang);\r\n document.documentElement.setAttribute('lang', lang);\r\n document.documentElement.setAttribute('dir', lang === 'ar' ? 'rtl' : 'ltr');\r\n\r\n // 2. Notify (fires before reload so any sync listener can catch it)\r\n this.config.onLangChanged?.(lang);\r\n window.dispatchEvent(new CustomEvent('cms:langChanged', { detail: { lang } }));\r\n\r\n // 3. Reload so the framework re-initializes with the new language\r\n window.location.reload();\r\n }\r\n\r\n // ===============================================\r\n // FAB DRAG\r\n // ===============================================\r\n\r\n private onDragStart(e: MouseEvent): void {\r\n if ((e.target as HTMLElement).closest('button:not(.lcms-fab-btn)') || (e.target as HTMLElement).closest('.lcms-panel')) return;\r\n this.isDragging = true;\r\n this.hasMoved = false;\r\n this.dragStartX = e.clientX;\r\n this.dragStartY = e.clientY;\r\n this.startPosX = this.posX;\r\n this.startPosY = this.posY;\r\n document.addEventListener('mousemove', this.boundMouseMove);\r\n document.addEventListener('mouseup', this.boundMouseUp);\r\n }\r\n\r\n private onDragMove(e: MouseEvent): void {\r\n if (!this.isDragging || !this.fabEl) return;\r\n const dx = e.clientX - this.dragStartX, dy = e.clientY - this.dragStartY;\r\n if (Math.abs(dx) > 3 || Math.abs(dy) > 3) this.hasMoved = true;\r\n this.posX = Math.max(0, Math.min(window.innerWidth - 60, this.startPosX + dx));\r\n this.posY = Math.max(0, Math.min(window.innerHeight - 60, this.startPosY + dy));\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n }\r\n\r\n private onDragEnd(): void {\r\n this.isDragging = false;\r\n document.removeEventListener('mousemove', this.boundMouseMove);\r\n document.removeEventListener('mouseup', this.boundMouseUp);\r\n }\r\n\r\n private onTouchStart(e: TouchEvent): void {\r\n if ((e.target as HTMLElement).closest('button:not(.lcms-fab-btn)') || (e.target as HTMLElement).closest('.lcms-panel')) return;\r\n const t = e.touches[0];\r\n this.isDragging = true;\r\n this.hasMoved = false;\r\n this.dragStartX = t.clientX;\r\n this.dragStartY = t.clientY;\r\n this.startPosX = this.posX;\r\n this.startPosY = this.posY;\r\n document.addEventListener('touchmove', this.boundTouchMove, { passive: false });\r\n document.addEventListener('touchend', this.boundTouchEnd);\r\n }\r\n\r\n private onTouchMove(e: TouchEvent): void {\r\n if (!this.isDragging || !this.fabEl) return;\r\n e.preventDefault();\r\n const t = e.touches[0];\r\n const dx = t.clientX - this.dragStartX, dy = t.clientY - this.dragStartY;\r\n if (Math.abs(dx) > 3 || Math.abs(dy) > 3) this.hasMoved = true;\r\n this.posX = Math.max(0, Math.min(window.innerWidth - 60, this.startPosX + dx));\r\n this.posY = Math.max(0, Math.min(window.innerHeight - 60, this.startPosY + dy));\r\n this.fabEl.style.left = this.posX + 'px';\r\n this.fabEl.style.top = this.posY + 'px';\r\n }\r\n\r\n private onTouchEnd(): void {\r\n this.isDragging = false;\r\n document.removeEventListener('touchmove', this.boundTouchMove);\r\n document.removeEventListener('touchend', this.boundTouchEnd);\r\n }\r\n\r\n // ===============================================\r\n // HELPERS\r\n // ===============================================\r\n\r\n private setLoading(val: boolean): void {\r\n this.loading = val;\r\n this.updateUI();\r\n }\r\n\r\n private detectCurrentLanguage(): string {\r\n const htmlLang = document.documentElement.getAttribute('lang');\r\n if (htmlLang && this.languages.includes(htmlLang)) return htmlLang;\r\n const stored = localStorage.getItem('selectedLanguage');\r\n if (stored && this.languages.includes(stored)) return stored;\r\n return this.defaultLanguage;\r\n }\r\n\r\n private createElement(tag: string, className: string): HTMLElement {\r\n const el = document.createElement(tag);\r\n el.className = className;\r\n return el;\r\n }\r\n\r\n private formatDate(timestamp: number): string {\r\n const d = new Date(timestamp);\r\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\r\n const h = d.getHours();\r\n const m = d.getMinutes().toString().padStart(2, '0');\r\n const ampm = h >= 12 ? 'PM' : 'AM';\r\n const h12 = h % 12 || 12;\r\n return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;\r\n }\r\n\r\n // ===============================================\r\n // LOGIN MODAL\r\n // ===============================================\r\n\r\n private showLoginModal(): void {\r\n if (this.loginModalEl) return;\r\n\r\n const overlay = document.createElement('div');\r\n overlay.className = 'lcms-login-overlay';\r\n overlay.id = 'lcms-login-modal';\r\n\r\n overlay.innerHTML = `\r\n <div class=\"lcms-login-box\">\r\n <div class=\"lcms-login-logo\">\r\n <div class=\"lcms-login-logo-icon\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </div>\r\n <span class=\"lcms-login-logo-text\">XtroEdge CMS</span>\r\n </div>\r\n <div class=\"lcms-login-title\">Builder Login</div>\r\n <div class=\"lcms-login-sub\">Sign in to access edit mode</div>\r\n <div class=\"lcms-login-field\">\r\n <label class=\"lcms-login-label\">Username</label>\r\n <input class=\"lcms-login-input\" id=\"lcms-login-email\" type=\"text\" placeholder=\"Enter your username\" autocomplete=\"username\" />\r\n </div>\r\n <div class=\"lcms-login-field\">\r\n <label class=\"lcms-login-label\">Password</label>\r\n <input class=\"lcms-login-input\" id=\"lcms-login-password\" type=\"password\" placeholder=\"Enter your password\" autocomplete=\"current-password\" />\r\n </div>\r\n <button class=\"lcms-login-btn\" id=\"lcms-login-btn\">Sign In</button>\r\n <div class=\"lcms-login-error\" id=\"lcms-login-error\"></div>\r\n </div>\r\n `;\r\n\r\n document.body.appendChild(overlay);\r\n this.loginModalEl = overlay;\r\n\r\n const btn = overlay.querySelector('#lcms-login-btn') as HTMLButtonElement;\r\n const emailInput = overlay.querySelector('#lcms-login-email') as HTMLInputElement;\r\n const passInput = overlay.querySelector('#lcms-login-password') as HTMLInputElement;\r\n\r\n const doLogin = () => this.attemptLogin(emailInput.value.trim(), passInput.value);\r\n btn.addEventListener('click', doLogin);\r\n passInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') doLogin(); });\r\n\r\n // Focus email field\r\n setTimeout(() => emailInput.focus(), 50);\r\n }\r\n\r\n private hideLoginModal(): void {\r\n this.loginModalEl?.remove();\r\n this.loginModalEl = null;\r\n }\r\n\r\n private async attemptLogin(email: string, password: string): Promise<void> {\r\n const btn = document.getElementById('lcms-login-btn') as HTMLButtonElement;\r\n const errorEl = document.getElementById('lcms-login-error') as HTMLElement;\r\n\r\n if (!email || !password) {\r\n errorEl.textContent = 'Please enter your username and password.';\r\n errorEl.classList.add('visible');\r\n return;\r\n }\r\n\r\n btn.disabled = true;\r\n btn.textContent = 'Signing in...';\r\n errorEl.classList.remove('visible');\r\n\r\n try {\r\n const loginUrl = this.config.loginUrl || `${this.config.apiBase}/auth/login`;\r\n const res = await fetch(loginUrl, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ username: email, password }),\r\n });\r\n\r\n // Try to parse body regardless of status (API may return error details in body)\r\n let data: any = null;\r\n try { data = await res.json(); } catch { /* ignore parse error */ }\r\n\r\n if (!res.ok) {\r\n // Show API error message if available (e.g. Xano: { message: \"Invalid credentials.\" })\r\n const apiMsg = data?.message || data?.error || null;\r\n throw new Error(apiMsg || `HTTP ${res.status}`);\r\n }\r\n\r\n // Store token — support common response shapes: { token }, { authToken }, { data: { token } }\r\n const token = data?.token || data?.authToken || data?.auth_token || data?.data?.token;\r\n if (!token) throw new Error('Login successful but no token returned.');\r\n\r\n localStorage.setItem('builder_token', token);\r\n this.hideLoginModal();\r\n\r\n // Now enable edit mode\r\n this.editMode = true;\r\n this.pendingEditMode = false;\r\n sessionStorage.setItem('builder_edit_mode', 'true');\r\n this.applyEditMode(true);\r\n this.updateUI();\r\n this.loadPageContent('draft');\r\n } catch (err: any) {\r\n btn.disabled = false;\r\n btn.textContent = 'Sign In';\r\n errorEl.textContent = err?.message || 'Login failed. Please try again.';\r\n errorEl.classList.add('visible');\r\n }\r\n }\r\n\r\n // ===============================================\r\n // SITE IDENTIFIER\r\n // ===============================================\r\n\r\n private resolveSiteIdentifier(): string {\r\n const hostname = window.location.hostname;\r\n if (hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.startsWith('192.168.')) {\r\n return hostname;\r\n }\r\n let id = localStorage.getItem('xtroedge_site_id');\r\n if (!id) {\r\n id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\r\n const r = Math.random() * 16 | 0;\r\n return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);\r\n });\r\n localStorage.setItem('xtroedge_site_id', id);\r\n }\r\n return id;\r\n }\r\n\r\n // ===============================================\r\n // THEME COLOR\r\n // ===============================================\r\n\r\n private hexToRgb(hex: string): string {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (!result) return '0,200,83';\r\n return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;\r\n }\r\n\r\n private getDarkerColor(hex: string): string {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (!result) return '#2E7D32';\r\n const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));\r\n const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));\r\n const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));\r\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\r\n }\r\n\r\n private applyThemeColor(color: string): void {\r\n this.highlightColor = color;\r\n document.documentElement.style.setProperty('--lcms-primary', color);\r\n document.documentElement.style.setProperty('--lcms-primary-rgb', this.hexToRgb(color));\r\n document.documentElement.style.setProperty('--lcms-primary-dark', this.getDarkerColor(color));\r\n\r\n // Re-apply highlight to managed elements\r\n if (this.editMode) {\r\n for (const [el] of this.managedElements) {\r\n el.style.outline = `2px dashed ${color}`;\r\n }\r\n for (const [img] of this.managedImages) {\r\n img.style.outline = `2px dashed ${color}`;\r\n }\r\n }\r\n\r\n // Update swatch active states\r\n const swatches = this.panelEl?.querySelectorAll('.lcms-theme-swatch');\r\n swatches?.forEach(s => {\r\n (s as HTMLElement).classList.toggle('active', (s as HTMLElement).dataset.color === color);\r\n });\r\n\r\n // Persist to localStorage\r\n localStorage.setItem('xtroedge_theme_color', color);\r\n }\r\n\r\n // ===============================================\r\n // STATIC CONVENIENCE\r\n // ===============================================\r\n\r\n /** Quick init - create and start CMS in one call */\r\n static create(config?: XtroedgeCmsConfig): XtroedgeCMS {\r\n const cms = new XtroedgeCMS(config);\r\n cms.init();\r\n return cms;\r\n }\r\n\r\n /** Auto-init: called automatically when package is loaded. No user code needed. */\r\n static autoInit(): void {\r\n // Prevent double init\r\n if ((window as any).__xtroedge_cms_instance__) return;\r\n\r\n const userConfig: XtroedgeCmsConfig = (window as any).__XTROEDGE_CMS_CONFIG__ || {};\r\n const cms = XtroedgeCMS.create(userConfig);\r\n (window as any).__xtroedge_cms_instance__ = cms;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":[]}
|