ngx-xtroedge-cms 1.0.1 → 1.2.0

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.mjs CHANGED
@@ -6,32 +6,32 @@ var CMS_STYLES = `
6
6
  .lcms-loader-overlay {
7
7
  position: fixed; inset: 0; z-index: 10003;
8
8
  display: flex; align-items: center; justify-content: center;
9
- background: rgba(15, 5, 30, 0.45);
9
+ background: rgba(8, 8, 15, 0.45);
10
10
  backdrop-filter: blur(12px) saturate(1.4);
11
11
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
12
12
  }
13
13
  .lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }
14
14
  .lcms-orbit-loader { position: relative; width: 90px; height: 90px; }
15
15
  .lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }
16
- .lcms-orbit-1 { border-top-color: rgba(103,34,251,0.5); animation: lcmsSpin 2.4s linear infinite; }
17
- .lcms-orbit-2 { inset: 10px; border-right-color: rgba(139,92,246,0.5); animation: lcmsSpin 3.2s linear infinite reverse; }
18
- .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(167,139,250,0.5); animation: lcmsSpin 4.2s linear infinite; }
16
+ .lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }
17
+ .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; }
18
+ .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }
19
19
  .lcms-particle {
20
20
  position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;
21
21
  box-shadow: 0 0 12px 3px currentColor;
22
22
  }
23
- .lcms-orbit-1 .lcms-particle { background: #6722FB; color: #6722FB; }
24
- .lcms-orbit-2 .lcms-particle { background: #8B5CF6; color: #8B5CF6; top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }
25
- .lcms-orbit-3 .lcms-particle { background: #A78BFA; color: #A78BFA; top: auto; bottom: -4px; }
23
+ .lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }
24
+ .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; }
25
+ .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; }
26
26
  .lcms-core-glow {
27
27
  position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);
28
- border-radius: 50%; background: radial-gradient(circle, rgba(103,34,251,0.4), transparent 70%);
28
+ border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);
29
29
  animation: lcmsPulse 2s ease-in-out infinite;
30
30
  }
31
31
  .lcms-core {
32
32
  position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);
33
- border-radius: 50%; background: linear-gradient(135deg, #6722FB, #A78BFA);
34
- box-shadow: 0 0 20px rgba(103,34,251,0.6);
33
+ border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));
34
+ box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);
35
35
  }
36
36
  .lcms-loader-text {
37
37
  font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;
@@ -48,10 +48,10 @@ var CMS_STYLES = `
48
48
  padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;
49
49
  font-family: system-ui, -apple-system, sans-serif; color: white;
50
50
  display: flex; align-items: center; gap: 8px;
51
- box-shadow: 0 8px 32px rgba(103,34,251,0.25);
51
+ box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);
52
52
  animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;
53
53
  }
54
- .lcms-toast-success { background: linear-gradient(135deg, #6722FB, #8B5CF6); }
54
+ .lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }
55
55
  .lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }
56
56
  @keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
57
57
  @keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }
@@ -60,15 +60,15 @@ var CMS_STYLES = `
60
60
  .lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }
61
61
  .lcms-fab-btn {
62
62
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);
63
- background: rgba(103,34,251,0.35); color: white;
63
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;
64
64
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
65
65
  cursor: grab; display: flex; align-items: center; justify-content: center;
66
- box-shadow: 0 4px 20px rgba(103,34,251,0.3), inset 0 1px 0 rgba(255,255,255,0.15);
66
+ 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);
67
67
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;
68
68
  }
69
- .lcms-fab-btn:not(.lcms-fab-active) { background: rgba(103,34,251,0.25); box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); }
70
- .lcms-fab-btn.lcms-fab-active { background: rgba(103,34,251,0.4); box-shadow: 0 4px 24px rgba(103,34,251,0.4), 0 0 16px rgba(103,34,251,0.2), inset 0 1px 0 rgba(255,255,255,0.2); }
71
- .lcms-fab-btn:hover { transform: scale(1.08); background: rgba(103,34,251,0.5); box-shadow: 0 6px 28px rgba(103,34,251,0.4), inset 0 1px 0 rgba(255,255,255,0.2); }
69
+ .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); }
70
+ .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); }
71
+ .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); }
72
72
  .lcms-badge {
73
73
  position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;
74
74
  font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;
@@ -77,14 +77,45 @@ var CMS_STYLES = `
77
77
 
78
78
  /* PANEL */
79
79
  .lcms-panel {
80
- background: rgba(30,15,60,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
81
- border: 1px solid rgba(139,92,246,0.25); border-radius: 16px; padding: 16px; min-width: 230px;
80
+ background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
81
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;
82
82
  box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);
83
83
  color: white; font-family: system-ui, -apple-system, sans-serif;
84
84
  animation: lcmsPanelIn 0.25s ease; position: absolute;
85
85
  }
86
86
  @keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
87
87
 
88
+ /* SITE IDENTIFIER */
89
+ .lcms-site-id {
90
+ display: flex; align-items: center; gap: 5px;
91
+ font-size: 10px; color: rgba(255,255,255,0.4);
92
+ padding: 0 0 8px; margin-bottom: 8px;
93
+ border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);
94
+ font-family: system-ui, -apple-system, sans-serif;
95
+ letter-spacing: 0.3px;
96
+ }
97
+ .lcms-site-id-icon { font-size: 12px; opacity: 0.7; }
98
+ .lcms-site-id-text {
99
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;
100
+ font-weight: 500;
101
+ }
102
+
103
+ /* BRANDING */
104
+ .lcms-branding {
105
+ display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;
106
+ border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;
107
+ cursor: pointer; transition: opacity 0.2s; user-select: none;
108
+ }
109
+ .lcms-branding:hover { opacity: 0.8; }
110
+ .lcms-branding-logo {
111
+ width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));
112
+ display: flex; align-items: center; justify-content: center;
113
+ }
114
+ .lcms-branding-text {
115
+ font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;
116
+ }
117
+ .lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }
118
+
88
119
  .lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
89
120
  .lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
90
121
  .lcms-toggle input { display: none; }
@@ -96,53 +127,84 @@ var CMS_STYLES = `
96
127
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
97
128
  top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;
98
129
  }
99
- .lcms-toggle input:checked + .lcms-toggle-slider { background: #6722FB; }
130
+ .lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }
100
131
  .lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }
101
132
  .lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }
102
- .lcms-toggle input:checked ~ .lcms-toggle-label { color: #a78bfa; }
103
- .lcms-lang-switch { display: flex; border: 1px solid rgba(103,34,251,0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
133
+ .lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }
134
+ .lcms-lang-switch { display: flex; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
104
135
  .lcms-lang-btn { background: transparent; border: none; color: rgba(255,255,255,0.45); padding: 3px 12px; font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.2s; }
105
- .lcms-lang-btn.active { background: #6722FB; color: white; }
106
- .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(103,34,251,0.2); }
136
+ .lcms-lang-btn.active { background: var(--lcms-primary, #00C853); color: white; }
137
+ .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); }
107
138
  .lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }
108
139
  .lcms-close-btn:hover { color: white; }
109
- .lcms-changes-info { font-size: 12px; color: #a78bfa; margin-bottom: 10px; padding-left: 2px; }
140
+ .lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }
110
141
 
111
142
  .lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }
112
143
  .lcms-icon-btn {
113
- width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(103,34,251,0.3);
114
- background: rgba(103,34,251,0.1); color: rgba(255,255,255,0.8); cursor: pointer;
144
+ width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);
145
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;
115
146
  display: flex; align-items: center; justify-content: center; transition: all 0.2s;
116
147
  }
117
- .lcms-icon-btn:hover:not(:disabled) { background: rgba(103,34,251,0.25); border-color: rgba(103,34,251,0.5); color: white; }
148
+ .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; }
118
149
  .lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }
119
150
 
151
+ /* COLOR THEME PICKER */
152
+ .lcms-theme-row {
153
+ display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
154
+ padding: 6px 0;
155
+ }
156
+ .lcms-theme-label {
157
+ font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);
158
+ text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;
159
+ }
160
+ .lcms-theme-colors {
161
+ display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
162
+ }
163
+ .lcms-theme-swatch {
164
+ width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;
165
+ cursor: pointer; transition: all 0.2s; position: relative;
166
+ }
167
+ .lcms-theme-swatch:hover { transform: scale(1.15); }
168
+ .lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }
169
+ .lcms-theme-custom {
170
+ width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);
171
+ cursor: pointer; overflow: hidden; position: relative;
172
+ }
173
+ .lcms-theme-custom input {
174
+ position: absolute; inset: -4px; width: 28px; height: 28px; border: none;
175
+ background: transparent; cursor: pointer; opacity: 0;
176
+ }
177
+ .lcms-theme-custom-preview {
178
+ width: 100%; height: 100%; border-radius: 50%;
179
+ background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
180
+ }
181
+
120
182
  .lcms-history-btn {
121
183
  width: 100%; padding: 7px 12px; border-radius: 8px;
122
- border: 1px dashed rgba(139,92,246,0.35); background: rgba(103,34,251,0.08);
184
+ border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);
123
185
  color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;
124
186
  display: flex; align-items: center; justify-content: center; gap: 6px;
125
187
  transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;
126
188
  }
127
- .lcms-history-btn:hover { background: rgba(103,34,251,0.18); border-color: rgba(139,92,246,0.5); color: white; }
128
- .lcms-history-btn.active { background: rgba(103,34,251,0.25); border-color: #6722FB; border-style: solid; color: white; }
189
+ .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; }
190
+ .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; }
129
191
 
130
- .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(139,92,246,0.15); padding-top: 10px; }
192
+ .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }
131
193
  .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; }
132
194
  .lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }
133
195
  .lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
134
196
  .lcms-history-list::-webkit-scrollbar { width: 4px; }
135
197
  .lcms-history-list::-webkit-scrollbar-track { background: transparent; }
136
- .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(103,34,251,0.3); border-radius: 4px; }
198
+ .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }
137
199
  .lcms-history-item {
138
- width: 100%; text-align: left; background: rgba(103,34,251,0.06);
139
- border: 1px solid rgba(103,34,251,0.12); border-radius: 8px; padding: 8px 10px;
200
+ width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);
201
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;
140
202
  cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;
141
203
  }
142
- .lcms-history-item:hover { background: rgba(103,34,251,0.15); border-color: rgba(103,34,251,0.3); }
204
+ .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); }
143
205
  .lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }
144
206
  .lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }
145
- .lcms-history-lang { background: rgba(103,34,251,0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: #a78bfa; }
207
+ .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); }
146
208
 
147
209
  .lcms-actions { display: flex; flex-direction: column; gap: 6px; }
148
210
  .lcms-actions button {
@@ -150,14 +212,14 @@ var CMS_STYLES = `
150
212
  cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;
151
213
  font-family: system-ui, -apple-system, sans-serif;
152
214
  }
153
- .lcms-btn-save { background: #6722FB; color: white; }
154
- .lcms-btn-save:hover { background: #7c3aed; }
155
- .lcms-btn-save:disabled { background: rgba(103,34,251,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
156
- .lcms-btn-publish { background: linear-gradient(135deg, #22c55e, #16a34a); color: white; }
157
- .lcms-btn-publish:hover { background: linear-gradient(135deg, #16a34a, #15803d); }
158
- .lcms-btn-publish:disabled { background: rgba(103,34,251,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
159
- .lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(103,34,251,0.25) !important; }
160
- .lcms-btn-cancel:hover { color: white; border-color: rgba(103,34,251,0.5) !important; background: rgba(103,34,251,0.08); }
215
+ .lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }
216
+ .lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }
217
+ .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; }
218
+ .lcms-btn-publish { background: linear-gradient(135deg, #2196F3, #1976D2); color: white; }
219
+ .lcms-btn-publish:hover { background: linear-gradient(135deg, #1976D2, #1565C0); }
220
+ .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; }
221
+ .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; }
222
+ .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); }
161
223
  .lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }
162
224
 
163
225
  .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; }
@@ -166,14 +228,14 @@ var CMS_STYLES = `
166
228
  .lcms-img-upload-overlay {
167
229
  position: fixed; inset: 0; z-index: 10005;
168
230
  display: flex; align-items: center; justify-content: center;
169
- background: rgba(15, 5, 30, 0.5); backdrop-filter: blur(8px);
231
+ background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);
170
232
  }
171
233
  .lcms-img-upload-content {
172
234
  display: flex; flex-direction: column; align-items: center; gap: 16px;
173
235
  color: white; font-family: system-ui, -apple-system, sans-serif;
174
236
  font-size: 13px; font-weight: 600;
175
237
  }
176
- .lcms-spinner-lg { width: 36px; height: 36px; border: 3px solid rgba(255,255,255,0.2); border-top-color: #6722FB; border-radius: 50%; animation: lcmsSpin 0.6s linear infinite; }
238
+ .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; }
177
239
 
178
240
  /* HIDDEN ELEMENTS */
179
241
  .lcms-hidden { display: none !important; }
@@ -218,6 +280,9 @@ var DEFAULT_EDITABLE_TAGS = [
218
280
  ];
219
281
  var XtroedgeCMS = class _XtroedgeCMS {
220
282
  constructor(config) {
283
+ this.brandingEl = null;
284
+ this.siteIdentifier = "";
285
+ this.siteIdEl = null;
221
286
  // ===== State =====
222
287
  this.editMode = false;
223
288
  this.currentLang = "en";
@@ -296,14 +361,17 @@ var XtroedgeCMS = class _XtroedgeCMS {
296
361
  this.db = null;
297
362
  // ===== i18n cache =====
298
363
  this.translationCache = /* @__PURE__ */ new Map();
299
- this.config = config;
300
- this.containerSelector = config.containerSelector || "body";
301
- this.editableTags = (config.editableTags || DEFAULT_EDITABLE_TAGS).map((t) => t.toLowerCase());
302
- this.languages = config.languages || ["en"];
303
- this.defaultLanguage = config.defaultLanguage || this.languages[0] || "en";
304
- this.highlightColor = config.highlightColor || "#6722FB";
305
- this.historyRetentionMs = (config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
364
+ this.config = config || {};
365
+ this.containerSelector = this.config.containerSelector || "";
366
+ this.editableTags = (this.config.editableTags || DEFAULT_EDITABLE_TAGS).map((t) => t.toLowerCase());
367
+ this.languages = this.config.languages || ["en"];
368
+ this.defaultLanguage = this.config.defaultLanguage || this.languages[0] || "en";
369
+ this.highlightColor = this.config.highlightColor || "#00C853";
370
+ this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
306
371
  this.currentLang = this.defaultLanguage;
372
+ this.siteIdentifier = this.resolveSiteIdentifier();
373
+ const savedColor = localStorage.getItem("xtroedge_theme_color");
374
+ if (savedColor) this.highlightColor = savedColor;
307
375
  this.boundMouseMove = (e) => this.onDragMove(e);
308
376
  this.boundMouseUp = () => this.onDragEnd();
309
377
  this.boundTouchMove = (e) => this.onTouchMove(e);
@@ -317,9 +385,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
317
385
  init() {
318
386
  this.posY = window.innerHeight - 72;
319
387
  this.injectStyles();
388
+ this.applyThemeColor(this.highlightColor);
320
389
  this.buildUI();
321
390
  this.interceptNavigation();
322
391
  this.observer = new MutationObserver(() => {
392
+ if (this.rootEl && !document.contains(this.rootEl)) {
393
+ document.body.appendChild(this.rootEl);
394
+ }
395
+ if (this.styleEl && !document.contains(this.styleEl)) {
396
+ document.head.appendChild(this.styleEl);
397
+ }
323
398
  if (this.scanTimeout) clearTimeout(this.scanTimeout);
324
399
  this.scanTimeout = setTimeout(() => this.autoDetectAndScan(), 150);
325
400
  });
@@ -482,6 +557,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
482
557
  });
483
558
  header.appendChild(closeBtn);
484
559
  this.panelEl.appendChild(header);
560
+ this.siteIdEl = this.createElement("div", "lcms-site-id");
561
+ const isDomain = this.siteIdentifier.includes(".");
562
+ 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>`;
563
+ this.panelEl.appendChild(this.siteIdEl);
485
564
  this.editModeContent = this.createElement("div", "lcms-hidden");
486
565
  this.changesInfoEl = this.createElement("div", "lcms-changes-info lcms-hidden");
487
566
  this.editModeContent.appendChild(this.changesInfoEl);
@@ -505,6 +584,37 @@ var XtroedgeCMS = class _XtroedgeCMS {
505
584
  undoRow.appendChild(this.undoBtn);
506
585
  undoRow.appendChild(this.redoBtn);
507
586
  this.editModeContent.appendChild(undoRow);
587
+ const themeRow = this.createElement("div", "lcms-theme-row");
588
+ const themeLabel = this.createElement("span", "lcms-theme-label");
589
+ themeLabel.textContent = "Theme";
590
+ themeRow.appendChild(themeLabel);
591
+ const themeColors = this.createElement("div", "lcms-theme-colors");
592
+ const presetColors = ["#00C853", "#6722FB", "#2196F3", "#FF5722", "#E91E63", "#FFD600"];
593
+ for (const color of presetColors) {
594
+ const swatch = this.createElement("div", "lcms-theme-swatch");
595
+ swatch.style.background = color;
596
+ swatch.dataset.color = color;
597
+ if (color === this.highlightColor) swatch.classList.add("active");
598
+ swatch.addEventListener("click", (e) => {
599
+ e.stopPropagation();
600
+ this.applyThemeColor(color);
601
+ });
602
+ themeColors.appendChild(swatch);
603
+ }
604
+ const customSwatch = this.createElement("div", "lcms-theme-custom");
605
+ const customPreview = this.createElement("div", "lcms-theme-custom-preview");
606
+ const customInput = document.createElement("input");
607
+ customInput.type = "color";
608
+ customInput.value = this.highlightColor;
609
+ customInput.addEventListener("input", (e) => {
610
+ e.stopPropagation();
611
+ this.applyThemeColor(e.target.value);
612
+ });
613
+ customSwatch.appendChild(customPreview);
614
+ customSwatch.appendChild(customInput);
615
+ themeColors.appendChild(customSwatch);
616
+ themeRow.appendChild(themeColors);
617
+ this.editModeContent.appendChild(themeRow);
508
618
  this.historyBtnEl = document.createElement("button");
509
619
  this.historyBtnEl.className = "lcms-history-btn";
510
620
  this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;
@@ -547,6 +657,13 @@ var XtroedgeCMS = class _XtroedgeCMS {
547
657
  this.actionsEl.appendChild(this.cancelBtn);
548
658
  this.editModeContent.appendChild(this.actionsEl);
549
659
  this.panelEl.appendChild(this.editModeContent);
660
+ this.brandingEl = this.createElement("div", "lcms-branding");
661
+ 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>`;
662
+ this.brandingEl.addEventListener("click", (e) => {
663
+ e.stopPropagation();
664
+ window.open("https://xtro.vercel.app/", "_blank");
665
+ });
666
+ this.panelEl.appendChild(this.brandingEl);
550
667
  }
551
668
  buildLangButtons() {
552
669
  if (!this.langSwitchEl) return;
@@ -629,8 +746,14 @@ var XtroedgeCMS = class _XtroedgeCMS {
629
746
  this.scanDOM();
630
747
  this.scanImages();
631
748
  }
749
+ resolveContainer() {
750
+ if (this.containerSelector) {
751
+ return document.querySelector(this.containerSelector) || document.body;
752
+ }
753
+ return document.querySelector(".layout") || document.body;
754
+ }
632
755
  autoDetectElements() {
633
- const container = document.querySelector(this.containerSelector);
756
+ const container = this.resolveContainer();
634
757
  if (!container) return;
635
758
  for (const el of this.autoDetectedElements) {
636
759
  if (!document.contains(el)) this.autoDetectedElements.delete(el);
@@ -667,7 +790,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
667
790
  }
668
791
  }
669
792
  scanImages() {
670
- const container = document.querySelector(this.containerSelector);
793
+ const container = this.resolveContainer();
671
794
  if (!container) return;
672
795
  const currentImages = { ...this.pageImages };
673
796
  let hasNew = false;
@@ -913,7 +1036,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
913
1036
  });
914
1037
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
915
1038
  const data = await res.json();
916
- const baseUrl = this.config.imageBaseUrl || new URL(this.config.apiBase).origin;
1039
+ const baseUrl = this.config.imageBaseUrl || (this.config.apiBase ? new URL(this.config.apiBase).origin : "");
917
1040
  const fullUrl = baseUrl + data.path;
918
1041
  if (this.activeImageEl) {
919
1042
  const key = this.managedImages.get(this.activeImageEl)?.key || "";
@@ -1058,8 +1181,15 @@ var XtroedgeCMS = class _XtroedgeCMS {
1058
1181
  }
1059
1182
  this.autoDetectAndScan();
1060
1183
  if (this.editMode) this.applyEditMode(true);
1061
- if (loadDraft) this.loadPageContent("draft");
1062
- else this.loadPublishedContent();
1184
+ if (this.config.apiBase) {
1185
+ if (loadDraft) this.loadPageContent("draft");
1186
+ else this.loadPublishedContent();
1187
+ } else {
1188
+ this.buildDefaultTexts();
1189
+ this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));
1190
+ this.originalImages = JSON.parse(JSON.stringify(this.pageImages));
1191
+ this.setLoading(false);
1192
+ }
1063
1193
  this.updateUI();
1064
1194
  }
1065
1195
  flattenTranslations(obj, prefix, pageSection) {
@@ -1085,7 +1215,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1085
1215
  this.setLoading(true);
1086
1216
  this.cleanOldHistory();
1087
1217
  try {
1088
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}`);
1218
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1089
1219
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1090
1220
  const page = await res.json();
1091
1221
  const texts = page?.published_content?.texts || page?.content?.texts;
@@ -1115,7 +1245,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1115
1245
  async loadPublishedContent() {
1116
1246
  this.setLoading(true);
1117
1247
  try {
1118
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published`);
1248
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1119
1249
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1120
1250
  const page = await res.json();
1121
1251
  const texts = page?.published_content?.texts;
@@ -1165,11 +1295,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
1165
1295
  }
1166
1296
  }
1167
1297
  async saveChanges() {
1298
+ if (!this.config.apiBase) {
1299
+ this.showToast("No API configured. Set apiBase to enable save.", "error");
1300
+ return;
1301
+ }
1168
1302
  this.isSaving = true;
1169
1303
  this.updateUI();
1170
1304
  const payload = {
1171
1305
  slug: this.currentSlug,
1172
1306
  title: this.currentTitle,
1307
+ site_identifier: this.siteIdentifier,
1173
1308
  content: { texts: this.pageTexts, images: this.pageImages }
1174
1309
  };
1175
1310
  try {
@@ -1192,11 +1327,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
1192
1327
  }
1193
1328
  }
1194
1329
  async publishChanges() {
1330
+ if (!this.config.apiBase) {
1331
+ this.showToast("No API configured. Set apiBase to enable publish.", "error");
1332
+ return;
1333
+ }
1195
1334
  this.isPublishing = true;
1196
1335
  this.updateUI();
1197
1336
  const payload = {
1198
1337
  slug: this.currentSlug,
1199
1338
  title: this.currentTitle,
1339
+ site_identifier: this.siteIdentifier,
1200
1340
  published_content: { texts: this.pageTexts, images: this.pageImages }
1201
1341
  };
1202
1342
  try {
@@ -1473,6 +1613,59 @@ var XtroedgeCMS = class _XtroedgeCMS {
1473
1613
  return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;
1474
1614
  }
1475
1615
  // ===============================================
1616
+ // SITE IDENTIFIER
1617
+ // ===============================================
1618
+ resolveSiteIdentifier() {
1619
+ const hostname = window.location.hostname;
1620
+ if (hostname && hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.startsWith("192.168.")) {
1621
+ return hostname;
1622
+ }
1623
+ let id = localStorage.getItem("xtroedge_site_id");
1624
+ if (!id) {
1625
+ id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1626
+ const r = Math.random() * 16 | 0;
1627
+ return (c === "x" ? r : r & 3 | 8).toString(16);
1628
+ });
1629
+ localStorage.setItem("xtroedge_site_id", id);
1630
+ }
1631
+ return id;
1632
+ }
1633
+ // ===============================================
1634
+ // THEME COLOR
1635
+ // ===============================================
1636
+ hexToRgb(hex) {
1637
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1638
+ if (!result) return "0,200,83";
1639
+ return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
1640
+ }
1641
+ getDarkerColor(hex) {
1642
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1643
+ if (!result) return "#2E7D32";
1644
+ const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));
1645
+ const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));
1646
+ const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));
1647
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
1648
+ }
1649
+ applyThemeColor(color) {
1650
+ this.highlightColor = color;
1651
+ document.documentElement.style.setProperty("--lcms-primary", color);
1652
+ document.documentElement.style.setProperty("--lcms-primary-rgb", this.hexToRgb(color));
1653
+ document.documentElement.style.setProperty("--lcms-primary-dark", this.getDarkerColor(color));
1654
+ if (this.editMode) {
1655
+ for (const [el] of this.managedElements) {
1656
+ el.style.borderBottom = `2px dashed ${color}`;
1657
+ }
1658
+ for (const [img] of this.managedImages) {
1659
+ img.style.outline = `2px dashed ${color}`;
1660
+ }
1661
+ }
1662
+ const swatches = this.panelEl?.querySelectorAll(".lcms-theme-swatch");
1663
+ swatches?.forEach((s) => {
1664
+ s.classList.toggle("active", s.dataset.color === color);
1665
+ });
1666
+ localStorage.setItem("xtroedge_theme_color", color);
1667
+ }
1668
+ // ===============================================
1476
1669
  // STATIC CONVENIENCE
1477
1670
  // ===============================================
1478
1671
  /** Quick init - create and start CMS in one call */
@@ -1481,7 +1674,26 @@ var XtroedgeCMS = class _XtroedgeCMS {
1481
1674
  cms.init();
1482
1675
  return cms;
1483
1676
  }
1677
+ /** Auto-init: called automatically when package is loaded. No user code needed. */
1678
+ static autoInit() {
1679
+ if (window.__xtroedge_cms_instance__) return;
1680
+ const userConfig = window.__XTROEDGE_CMS_CONFIG__ || {};
1681
+ const cms = _XtroedgeCMS.create(userConfig);
1682
+ window.__xtroedge_cms_instance__ = cms;
1683
+ }
1484
1684
  };
1685
+
1686
+ // src/index.ts
1687
+ function boot() {
1688
+ XtroedgeCMS.autoInit();
1689
+ }
1690
+ if (typeof window !== "undefined") {
1691
+ if (document.readyState === "loading") {
1692
+ document.addEventListener("DOMContentLoaded", boot);
1693
+ } else {
1694
+ boot();
1695
+ }
1696
+ }
1485
1697
  export {
1486
1698
  XtroedgeCMS
1487
1699
  };