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.js CHANGED
@@ -32,32 +32,32 @@ var CMS_STYLES = `
32
32
  .lcms-loader-overlay {
33
33
  position: fixed; inset: 0; z-index: 10003;
34
34
  display: flex; align-items: center; justify-content: center;
35
- background: rgba(15, 5, 30, 0.45);
35
+ background: rgba(8, 8, 15, 0.45);
36
36
  backdrop-filter: blur(12px) saturate(1.4);
37
37
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
38
38
  }
39
39
  .lcms-loader-content { display: flex; flex-direction: column; align-items: center; gap: 28px; }
40
40
  .lcms-orbit-loader { position: relative; width: 90px; height: 90px; }
41
41
  .lcms-orbit { position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; }
42
- .lcms-orbit-1 { border-top-color: rgba(103,34,251,0.5); animation: lcmsSpin 2.4s linear infinite; }
43
- .lcms-orbit-2 { inset: 10px; border-right-color: rgba(139,92,246,0.5); animation: lcmsSpin 3.2s linear infinite reverse; }
44
- .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(167,139,250,0.5); animation: lcmsSpin 4.2s linear infinite; }
42
+ .lcms-orbit-1 { border-top-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.5); animation: lcmsSpin 2.4s linear infinite; }
43
+ .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; }
44
+ .lcms-orbit-3 { inset: 20px; border-bottom-color: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); animation: lcmsSpin 4.2s linear infinite; }
45
45
  .lcms-particle {
46
46
  position: absolute; width: 8px; height: 8px; border-radius: 50%; top: -4px; left: 50%; margin-left: -4px;
47
47
  box-shadow: 0 0 12px 3px currentColor;
48
48
  }
49
- .lcms-orbit-1 .lcms-particle { background: #6722FB; color: #6722FB; }
50
- .lcms-orbit-2 .lcms-particle { background: #8B5CF6; color: #8B5CF6; top: 50%; left: auto; right: -4px; margin-left: 0; margin-top: -4px; }
51
- .lcms-orbit-3 .lcms-particle { background: #A78BFA; color: #A78BFA; top: auto; bottom: -4px; }
49
+ .lcms-orbit-1 .lcms-particle { background: var(--lcms-primary, #00C853); color: var(--lcms-primary, #00C853); }
50
+ .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; }
51
+ .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; }
52
52
  .lcms-core-glow {
53
53
  position: absolute; width: 30px; height: 30px; top: 50%; left: 50%; transform: translate(-50%,-50%);
54
- border-radius: 50%; background: radial-gradient(circle, rgba(103,34,251,0.4), transparent 70%);
54
+ border-radius: 50%; background: radial-gradient(circle, rgba(var(--lcms-primary-rgb, 0,200,83),0.4), transparent 70%);
55
55
  animation: lcmsPulse 2s ease-in-out infinite;
56
56
  }
57
57
  .lcms-core {
58
58
  position: absolute; width: 12px; height: 12px; top: 50%; left: 50%; transform: translate(-50%,-50%);
59
- border-radius: 50%; background: linear-gradient(135deg, #6722FB, #A78BFA);
60
- box-shadow: 0 0 20px rgba(103,34,251,0.6);
59
+ border-radius: 50%; background: linear-gradient(135deg, var(--lcms-primary, #00C853), rgba(var(--lcms-primary-rgb, 0,200,83),0.6));
60
+ box-shadow: 0 0 20px rgba(var(--lcms-primary-rgb, 0,200,83),0.6);
61
61
  }
62
62
  .lcms-loader-text {
63
63
  font-family: system-ui, -apple-system, sans-serif; font-size: 12px; font-weight: 600;
@@ -74,10 +74,10 @@ var CMS_STYLES = `
74
74
  padding: 10px 20px; border-radius: 10px; font-size: 13px; font-weight: 600;
75
75
  font-family: system-ui, -apple-system, sans-serif; color: white;
76
76
  display: flex; align-items: center; gap: 8px;
77
- box-shadow: 0 8px 32px rgba(103,34,251,0.25);
77
+ box-shadow: 0 8px 32px rgba(var(--lcms-primary-rgb, 0,200,83),0.25);
78
78
  animation: lcmsToastIn 0.3s ease, lcmsToastOut 0.3s ease 2.7s forwards; white-space: nowrap;
79
79
  }
80
- .lcms-toast-success { background: linear-gradient(135deg, #6722FB, #8B5CF6); }
80
+ .lcms-toast-success { background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32)); }
81
81
  .lcms-toast-error { background: linear-gradient(135deg, #dc2626, #ef4444); }
82
82
  @keyframes lcmsToastIn { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
83
83
  @keyframes lcmsToastOut { from { opacity: 1; transform: translateX(-50%) translateY(0); } to { opacity: 0; transform: translateX(-50%) translateY(-12px); } }
@@ -86,15 +86,15 @@ var CMS_STYLES = `
86
86
  .lcms-fab { position: fixed; z-index: 10001; user-select: none; touch-action: none; }
87
87
  .lcms-fab-btn {
88
88
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.2);
89
- background: rgba(103,34,251,0.35); color: white;
89
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.35); color: white;
90
90
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
91
91
  cursor: grab; display: flex; align-items: center; justify-content: center;
92
- box-shadow: 0 4px 20px rgba(103,34,251,0.3), inset 0 1px 0 rgba(255,255,255,0.15);
92
+ 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);
93
93
  transition: transform 0.2s, box-shadow 0.2s, background 0.2s; position: relative;
94
94
  }
95
- .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); }
96
- .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); }
97
- .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); }
95
+ .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); }
96
+ .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); }
97
+ .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); }
98
98
  .lcms-badge {
99
99
  position: absolute; top: -4px; right: -4px; background: #ef4444; color: white;
100
100
  font-size: 11px; font-weight: 700; width: 20px; height: 20px; border-radius: 50%;
@@ -103,14 +103,45 @@ var CMS_STYLES = `
103
103
 
104
104
  /* PANEL */
105
105
  .lcms-panel {
106
- background: rgba(30,15,60,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
107
- border: 1px solid rgba(139,92,246,0.25); border-radius: 16px; padding: 16px; min-width: 230px;
106
+ background: rgba(12,12,18,0.55); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
107
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.25); border-radius: 16px; padding: 16px; min-width: 230px;
108
108
  box-shadow: 0 8px 32px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.06);
109
109
  color: white; font-family: system-ui, -apple-system, sans-serif;
110
110
  animation: lcmsPanelIn 0.25s ease; position: absolute;
111
111
  }
112
112
  @keyframes lcmsPanelIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }
113
113
 
114
+ /* SITE IDENTIFIER */
115
+ .lcms-site-id {
116
+ display: flex; align-items: center; gap: 5px;
117
+ font-size: 10px; color: rgba(255,255,255,0.4);
118
+ padding: 0 0 8px; margin-bottom: 8px;
119
+ border-bottom: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12);
120
+ font-family: system-ui, -apple-system, sans-serif;
121
+ letter-spacing: 0.3px;
122
+ }
123
+ .lcms-site-id-icon { font-size: 12px; opacity: 0.7; }
124
+ .lcms-site-id-text {
125
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;
126
+ font-weight: 500;
127
+ }
128
+
129
+ /* BRANDING */
130
+ .lcms-branding {
131
+ display: flex; align-items: center; gap: 6px; padding: 8px 0 4px;
132
+ border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); margin-top: 10px;
133
+ cursor: pointer; transition: opacity 0.2s; user-select: none;
134
+ }
135
+ .lcms-branding:hover { opacity: 0.8; }
136
+ .lcms-branding-logo {
137
+ width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--lcms-primary, #00C853), var(--lcms-primary-dark, #2E7D32));
138
+ display: flex; align-items: center; justify-content: center;
139
+ }
140
+ .lcms-branding-text {
141
+ font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.35); letter-spacing: 0.5px;
142
+ }
143
+ .lcms-branding-text span { color: var(--lcms-primary, #00C853); font-weight: 700; }
144
+
114
145
  .lcms-panel-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
115
146
  .lcms-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
116
147
  .lcms-toggle input { display: none; }
@@ -122,53 +153,84 @@ var CMS_STYLES = `
122
153
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
123
154
  top: 2px; left: 2px; background: rgba(255,255,255,0.6); transition: transform 0.25s, background 0.25s;
124
155
  }
125
- .lcms-toggle input:checked + .lcms-toggle-slider { background: #6722FB; }
156
+ .lcms-toggle input:checked + .lcms-toggle-slider { background: var(--lcms-primary, #00C853); }
126
157
  .lcms-toggle input:checked + .lcms-toggle-slider::after { transform: translateX(16px); background: white; }
127
158
  .lcms-toggle-label { font-size: 12px; font-weight: 700; color: rgba(255,255,255,0.5); letter-spacing: 0.5px; transition: color 0.25s; }
128
- .lcms-toggle input:checked ~ .lcms-toggle-label { color: #a78bfa; }
129
- .lcms-lang-switch { display: flex; border: 1px solid rgba(103,34,251,0.4); border-radius: 6px; overflow: hidden; margin-left: auto; }
159
+ .lcms-toggle input:checked ~ .lcms-toggle-label { color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); }
160
+ .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; }
130
161
  .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; }
131
- .lcms-lang-btn.active { background: #6722FB; color: white; }
132
- .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(103,34,251,0.2); }
162
+ .lcms-lang-btn.active { background: var(--lcms-primary, #00C853); color: white; }
163
+ .lcms-lang-btn:hover:not(.active) { color: white; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.2); }
133
164
  .lcms-close-btn { background: transparent; border: none; color: rgba(255,255,255,0.4); cursor: pointer; padding: 2px; display: flex; transition: color 0.2s; }
134
165
  .lcms-close-btn:hover { color: white; }
135
- .lcms-changes-info { font-size: 12px; color: #a78bfa; margin-bottom: 10px; padding-left: 2px; }
166
+ .lcms-changes-info { font-size: 12px; color: rgba(var(--lcms-primary-rgb, 0,200,83),0.75); margin-bottom: 10px; padding-left: 2px; }
136
167
 
137
168
  .lcms-undo-row { display: flex; gap: 6px; margin-bottom: 12px; }
138
169
  .lcms-icon-btn {
139
- width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(103,34,251,0.3);
140
- background: rgba(103,34,251,0.1); color: rgba(255,255,255,0.8); cursor: pointer;
170
+ width: 36px; height: 32px; border-radius: 8px; border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.3);
171
+ background: rgba(var(--lcms-primary-rgb, 0,200,83),0.1); color: rgba(255,255,255,0.8); cursor: pointer;
141
172
  display: flex; align-items: center; justify-content: center; transition: all 0.2s;
142
173
  }
143
- .lcms-icon-btn:hover:not(:disabled) { background: rgba(103,34,251,0.25); border-color: rgba(103,34,251,0.5); color: white; }
174
+ .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; }
144
175
  .lcms-icon-btn:disabled { opacity: 0.25; cursor: not-allowed; }
145
176
 
177
+ /* COLOR THEME PICKER */
178
+ .lcms-theme-row {
179
+ display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
180
+ padding: 6px 0;
181
+ }
182
+ .lcms-theme-label {
183
+ font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.45);
184
+ text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;
185
+ }
186
+ .lcms-theme-colors {
187
+ display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
188
+ }
189
+ .lcms-theme-swatch {
190
+ width: 20px; height: 20px; border-radius: 50%; border: 2px solid transparent;
191
+ cursor: pointer; transition: all 0.2s; position: relative;
192
+ }
193
+ .lcms-theme-swatch:hover { transform: scale(1.15); }
194
+ .lcms-theme-swatch.active { border-color: white; box-shadow: 0 0 8px rgba(255,255,255,0.3); }
195
+ .lcms-theme-custom {
196
+ width: 20px; height: 20px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.3);
197
+ cursor: pointer; overflow: hidden; position: relative;
198
+ }
199
+ .lcms-theme-custom input {
200
+ position: absolute; inset: -4px; width: 28px; height: 28px; border: none;
201
+ background: transparent; cursor: pointer; opacity: 0;
202
+ }
203
+ .lcms-theme-custom-preview {
204
+ width: 100%; height: 100%; border-radius: 50%;
205
+ background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
206
+ }
207
+
146
208
  .lcms-history-btn {
147
209
  width: 100%; padding: 7px 12px; border-radius: 8px;
148
- border: 1px dashed rgba(139,92,246,0.35); background: rgba(103,34,251,0.08);
210
+ border: 1px dashed rgba(var(--lcms-primary-rgb, 0,200,83),0.35); background: rgba(var(--lcms-primary-rgb, 0,200,83),0.08);
149
211
  color: rgba(255,255,255,0.6); font-size: 12px; font-weight: 500; cursor: pointer;
150
212
  display: flex; align-items: center; justify-content: center; gap: 6px;
151
213
  transition: all 0.2s; margin-bottom: 12px; font-family: system-ui, -apple-system, sans-serif;
152
214
  }
153
- .lcms-history-btn:hover { background: rgba(103,34,251,0.18); border-color: rgba(139,92,246,0.5); color: white; }
154
- .lcms-history-btn.active { background: rgba(103,34,251,0.25); border-color: #6722FB; border-style: solid; color: white; }
215
+ .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; }
216
+ .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; }
155
217
 
156
- .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(139,92,246,0.15); padding-top: 10px; }
218
+ .lcms-history-panel { margin-top: 8px; border-top: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.15); padding-top: 10px; }
157
219
  .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; }
158
220
  .lcms-history-empty { font-size: 12px; color: rgba(255,255,255,0.3); text-align: center; padding: 12px 0; }
159
221
  .lcms-history-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
160
222
  .lcms-history-list::-webkit-scrollbar { width: 4px; }
161
223
  .lcms-history-list::-webkit-scrollbar-track { background: transparent; }
162
- .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(103,34,251,0.3); border-radius: 4px; }
224
+ .lcms-history-list::-webkit-scrollbar-thumb { background: rgba(var(--lcms-primary-rgb, 0,200,83),0.3); border-radius: 4px; }
163
225
  .lcms-history-item {
164
- width: 100%; text-align: left; background: rgba(103,34,251,0.06);
165
- border: 1px solid rgba(103,34,251,0.12); border-radius: 8px; padding: 8px 10px;
226
+ width: 100%; text-align: left; background: rgba(var(--lcms-primary-rgb, 0,200,83),0.06);
227
+ border: 1px solid rgba(var(--lcms-primary-rgb, 0,200,83),0.12); border-radius: 8px; padding: 8px 10px;
166
228
  cursor: pointer; transition: all 0.2s; color: white; font-family: system-ui, -apple-system, sans-serif;
167
229
  }
168
- .lcms-history-item:hover { background: rgba(103,34,251,0.15); border-color: rgba(103,34,251,0.3); }
230
+ .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); }
169
231
  .lcms-history-label { font-size: 12px; font-weight: 500; margin-bottom: 2px; }
170
232
  .lcms-history-meta { font-size: 10px; color: rgba(255,255,255,0.4); display: flex; align-items: center; gap: 6px; }
171
- .lcms-history-lang { background: rgba(103,34,251,0.2); padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 600; color: #a78bfa; }
233
+ .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); }
172
234
 
173
235
  .lcms-actions { display: flex; flex-direction: column; gap: 6px; }
174
236
  .lcms-actions button {
@@ -176,14 +238,14 @@ var CMS_STYLES = `
176
238
  cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; border: none;
177
239
  font-family: system-ui, -apple-system, sans-serif;
178
240
  }
179
- .lcms-btn-save { background: #6722FB; color: white; }
180
- .lcms-btn-save:hover { background: #7c3aed; }
181
- .lcms-btn-save:disabled { background: rgba(103,34,251,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
182
- .lcms-btn-publish { background: linear-gradient(135deg, #22c55e, #16a34a); color: white; }
183
- .lcms-btn-publish:hover { background: linear-gradient(135deg, #16a34a, #15803d); }
184
- .lcms-btn-publish:disabled { background: rgba(103,34,251,0.2); color: rgba(255,255,255,0.35); cursor: not-allowed; }
185
- .lcms-btn-cancel { background: transparent; color: rgba(255,255,255,0.5); border: 1px solid rgba(103,34,251,0.25) !important; }
186
- .lcms-btn-cancel:hover { color: white; border-color: rgba(103,34,251,0.5) !important; background: rgba(103,34,251,0.08); }
241
+ .lcms-btn-save { background: var(--lcms-primary, #00C853); color: white; }
242
+ .lcms-btn-save:hover { background: var(--lcms-primary, #00C853); filter: brightness(1.15); }
243
+ .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; }
244
+ .lcms-btn-publish { background: linear-gradient(135deg, #2196F3, #1976D2); color: white; }
245
+ .lcms-btn-publish:hover { background: linear-gradient(135deg, #1976D2, #1565C0); }
246
+ .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; }
247
+ .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; }
248
+ .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); }
187
249
  .lcms-btn-cancel:disabled { opacity: 0.3; cursor: not-allowed; }
188
250
 
189
251
  .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; }
@@ -192,14 +254,14 @@ var CMS_STYLES = `
192
254
  .lcms-img-upload-overlay {
193
255
  position: fixed; inset: 0; z-index: 10005;
194
256
  display: flex; align-items: center; justify-content: center;
195
- background: rgba(15, 5, 30, 0.5); backdrop-filter: blur(8px);
257
+ background: rgba(8, 8, 15, 0.5); backdrop-filter: blur(8px);
196
258
  }
197
259
  .lcms-img-upload-content {
198
260
  display: flex; flex-direction: column; align-items: center; gap: 16px;
199
261
  color: white; font-family: system-ui, -apple-system, sans-serif;
200
262
  font-size: 13px; font-weight: 600;
201
263
  }
202
- .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; }
264
+ .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; }
203
265
 
204
266
  /* HIDDEN ELEMENTS */
205
267
  .lcms-hidden { display: none !important; }
@@ -244,6 +306,9 @@ var DEFAULT_EDITABLE_TAGS = [
244
306
  ];
245
307
  var XtroedgeCMS = class _XtroedgeCMS {
246
308
  constructor(config) {
309
+ this.brandingEl = null;
310
+ this.siteIdentifier = "";
311
+ this.siteIdEl = null;
247
312
  // ===== State =====
248
313
  this.editMode = false;
249
314
  this.currentLang = "en";
@@ -322,14 +387,17 @@ var XtroedgeCMS = class _XtroedgeCMS {
322
387
  this.db = null;
323
388
  // ===== i18n cache =====
324
389
  this.translationCache = /* @__PURE__ */ new Map();
325
- this.config = config;
326
- this.containerSelector = config.containerSelector || "body";
327
- this.editableTags = (config.editableTags || DEFAULT_EDITABLE_TAGS).map((t) => t.toLowerCase());
328
- this.languages = config.languages || ["en"];
329
- this.defaultLanguage = config.defaultLanguage || this.languages[0] || "en";
330
- this.highlightColor = config.highlightColor || "#6722FB";
331
- this.historyRetentionMs = (config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
390
+ this.config = config || {};
391
+ this.containerSelector = this.config.containerSelector || "";
392
+ this.editableTags = (this.config.editableTags || DEFAULT_EDITABLE_TAGS).map((t) => t.toLowerCase());
393
+ this.languages = this.config.languages || ["en"];
394
+ this.defaultLanguage = this.config.defaultLanguage || this.languages[0] || "en";
395
+ this.highlightColor = this.config.highlightColor || "#00C853";
396
+ this.historyRetentionMs = (this.config.historyRetentionDays || 7) * 24 * 60 * 60 * 1e3;
332
397
  this.currentLang = this.defaultLanguage;
398
+ this.siteIdentifier = this.resolveSiteIdentifier();
399
+ const savedColor = localStorage.getItem("xtroedge_theme_color");
400
+ if (savedColor) this.highlightColor = savedColor;
333
401
  this.boundMouseMove = (e) => this.onDragMove(e);
334
402
  this.boundMouseUp = () => this.onDragEnd();
335
403
  this.boundTouchMove = (e) => this.onTouchMove(e);
@@ -343,9 +411,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
343
411
  init() {
344
412
  this.posY = window.innerHeight - 72;
345
413
  this.injectStyles();
414
+ this.applyThemeColor(this.highlightColor);
346
415
  this.buildUI();
347
416
  this.interceptNavigation();
348
417
  this.observer = new MutationObserver(() => {
418
+ if (this.rootEl && !document.contains(this.rootEl)) {
419
+ document.body.appendChild(this.rootEl);
420
+ }
421
+ if (this.styleEl && !document.contains(this.styleEl)) {
422
+ document.head.appendChild(this.styleEl);
423
+ }
349
424
  if (this.scanTimeout) clearTimeout(this.scanTimeout);
350
425
  this.scanTimeout = setTimeout(() => this.autoDetectAndScan(), 150);
351
426
  });
@@ -508,6 +583,10 @@ var XtroedgeCMS = class _XtroedgeCMS {
508
583
  });
509
584
  header.appendChild(closeBtn);
510
585
  this.panelEl.appendChild(header);
586
+ this.siteIdEl = this.createElement("div", "lcms-site-id");
587
+ const isDomain = this.siteIdentifier.includes(".");
588
+ 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>`;
589
+ this.panelEl.appendChild(this.siteIdEl);
511
590
  this.editModeContent = this.createElement("div", "lcms-hidden");
512
591
  this.changesInfoEl = this.createElement("div", "lcms-changes-info lcms-hidden");
513
592
  this.editModeContent.appendChild(this.changesInfoEl);
@@ -531,6 +610,37 @@ var XtroedgeCMS = class _XtroedgeCMS {
531
610
  undoRow.appendChild(this.undoBtn);
532
611
  undoRow.appendChild(this.redoBtn);
533
612
  this.editModeContent.appendChild(undoRow);
613
+ const themeRow = this.createElement("div", "lcms-theme-row");
614
+ const themeLabel = this.createElement("span", "lcms-theme-label");
615
+ themeLabel.textContent = "Theme";
616
+ themeRow.appendChild(themeLabel);
617
+ const themeColors = this.createElement("div", "lcms-theme-colors");
618
+ const presetColors = ["#00C853", "#6722FB", "#2196F3", "#FF5722", "#E91E63", "#FFD600"];
619
+ for (const color of presetColors) {
620
+ const swatch = this.createElement("div", "lcms-theme-swatch");
621
+ swatch.style.background = color;
622
+ swatch.dataset.color = color;
623
+ if (color === this.highlightColor) swatch.classList.add("active");
624
+ swatch.addEventListener("click", (e) => {
625
+ e.stopPropagation();
626
+ this.applyThemeColor(color);
627
+ });
628
+ themeColors.appendChild(swatch);
629
+ }
630
+ const customSwatch = this.createElement("div", "lcms-theme-custom");
631
+ const customPreview = this.createElement("div", "lcms-theme-custom-preview");
632
+ const customInput = document.createElement("input");
633
+ customInput.type = "color";
634
+ customInput.value = this.highlightColor;
635
+ customInput.addEventListener("input", (e) => {
636
+ e.stopPropagation();
637
+ this.applyThemeColor(e.target.value);
638
+ });
639
+ customSwatch.appendChild(customPreview);
640
+ customSwatch.appendChild(customInput);
641
+ themeColors.appendChild(customSwatch);
642
+ themeRow.appendChild(themeColors);
643
+ this.editModeContent.appendChild(themeRow);
534
644
  this.historyBtnEl = document.createElement("button");
535
645
  this.historyBtnEl.className = "lcms-history-btn";
536
646
  this.historyBtnEl.innerHTML = `${ICON.history} History (7 days)`;
@@ -573,6 +683,13 @@ var XtroedgeCMS = class _XtroedgeCMS {
573
683
  this.actionsEl.appendChild(this.cancelBtn);
574
684
  this.editModeContent.appendChild(this.actionsEl);
575
685
  this.panelEl.appendChild(this.editModeContent);
686
+ this.brandingEl = this.createElement("div", "lcms-branding");
687
+ 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>`;
688
+ this.brandingEl.addEventListener("click", (e) => {
689
+ e.stopPropagation();
690
+ window.open("https://xtro.vercel.app/", "_blank");
691
+ });
692
+ this.panelEl.appendChild(this.brandingEl);
576
693
  }
577
694
  buildLangButtons() {
578
695
  if (!this.langSwitchEl) return;
@@ -655,8 +772,14 @@ var XtroedgeCMS = class _XtroedgeCMS {
655
772
  this.scanDOM();
656
773
  this.scanImages();
657
774
  }
775
+ resolveContainer() {
776
+ if (this.containerSelector) {
777
+ return document.querySelector(this.containerSelector) || document.body;
778
+ }
779
+ return document.querySelector(".layout") || document.body;
780
+ }
658
781
  autoDetectElements() {
659
- const container = document.querySelector(this.containerSelector);
782
+ const container = this.resolveContainer();
660
783
  if (!container) return;
661
784
  for (const el of this.autoDetectedElements) {
662
785
  if (!document.contains(el)) this.autoDetectedElements.delete(el);
@@ -693,7 +816,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
693
816
  }
694
817
  }
695
818
  scanImages() {
696
- const container = document.querySelector(this.containerSelector);
819
+ const container = this.resolveContainer();
697
820
  if (!container) return;
698
821
  const currentImages = { ...this.pageImages };
699
822
  let hasNew = false;
@@ -939,7 +1062,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
939
1062
  });
940
1063
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
941
1064
  const data = await res.json();
942
- const baseUrl = this.config.imageBaseUrl || new URL(this.config.apiBase).origin;
1065
+ const baseUrl = this.config.imageBaseUrl || (this.config.apiBase ? new URL(this.config.apiBase).origin : "");
943
1066
  const fullUrl = baseUrl + data.path;
944
1067
  if (this.activeImageEl) {
945
1068
  const key = this.managedImages.get(this.activeImageEl)?.key || "";
@@ -1084,8 +1207,15 @@ var XtroedgeCMS = class _XtroedgeCMS {
1084
1207
  }
1085
1208
  this.autoDetectAndScan();
1086
1209
  if (this.editMode) this.applyEditMode(true);
1087
- if (loadDraft) this.loadPageContent("draft");
1088
- else this.loadPublishedContent();
1210
+ if (this.config.apiBase) {
1211
+ if (loadDraft) this.loadPageContent("draft");
1212
+ else this.loadPublishedContent();
1213
+ } else {
1214
+ this.buildDefaultTexts();
1215
+ this.originalTexts = JSON.parse(JSON.stringify(this.pageTexts));
1216
+ this.originalImages = JSON.parse(JSON.stringify(this.pageImages));
1217
+ this.setLoading(false);
1218
+ }
1089
1219
  this.updateUI();
1090
1220
  }
1091
1221
  flattenTranslations(obj, prefix, pageSection) {
@@ -1111,7 +1241,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1111
1241
  this.setLoading(true);
1112
1242
  this.cleanOldHistory();
1113
1243
  try {
1114
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}`);
1244
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=${status}&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1115
1245
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1116
1246
  const page = await res.json();
1117
1247
  const texts = page?.published_content?.texts || page?.content?.texts;
@@ -1141,7 +1271,7 @@ var XtroedgeCMS = class _XtroedgeCMS {
1141
1271
  async loadPublishedContent() {
1142
1272
  this.setLoading(true);
1143
1273
  try {
1144
- const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published`);
1274
+ const res = await fetch(`${this.config.apiBase}/web-page/get?slug=${encodeURIComponent(this.currentSlug)}&status=published&site_identifier=${encodeURIComponent(this.siteIdentifier)}`);
1145
1275
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
1146
1276
  const page = await res.json();
1147
1277
  const texts = page?.published_content?.texts;
@@ -1191,11 +1321,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
1191
1321
  }
1192
1322
  }
1193
1323
  async saveChanges() {
1324
+ if (!this.config.apiBase) {
1325
+ this.showToast("No API configured. Set apiBase to enable save.", "error");
1326
+ return;
1327
+ }
1194
1328
  this.isSaving = true;
1195
1329
  this.updateUI();
1196
1330
  const payload = {
1197
1331
  slug: this.currentSlug,
1198
1332
  title: this.currentTitle,
1333
+ site_identifier: this.siteIdentifier,
1199
1334
  content: { texts: this.pageTexts, images: this.pageImages }
1200
1335
  };
1201
1336
  try {
@@ -1218,11 +1353,16 @@ var XtroedgeCMS = class _XtroedgeCMS {
1218
1353
  }
1219
1354
  }
1220
1355
  async publishChanges() {
1356
+ if (!this.config.apiBase) {
1357
+ this.showToast("No API configured. Set apiBase to enable publish.", "error");
1358
+ return;
1359
+ }
1221
1360
  this.isPublishing = true;
1222
1361
  this.updateUI();
1223
1362
  const payload = {
1224
1363
  slug: this.currentSlug,
1225
1364
  title: this.currentTitle,
1365
+ site_identifier: this.siteIdentifier,
1226
1366
  published_content: { texts: this.pageTexts, images: this.pageImages }
1227
1367
  };
1228
1368
  try {
@@ -1499,6 +1639,59 @@ var XtroedgeCMS = class _XtroedgeCMS {
1499
1639
  return `${months[d.getMonth()]} ${d.getDate()}, ${h12}:${m} ${ampm}`;
1500
1640
  }
1501
1641
  // ===============================================
1642
+ // SITE IDENTIFIER
1643
+ // ===============================================
1644
+ resolveSiteIdentifier() {
1645
+ const hostname = window.location.hostname;
1646
+ if (hostname && hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.startsWith("192.168.")) {
1647
+ return hostname;
1648
+ }
1649
+ let id = localStorage.getItem("xtroedge_site_id");
1650
+ if (!id) {
1651
+ id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1652
+ const r = Math.random() * 16 | 0;
1653
+ return (c === "x" ? r : r & 3 | 8).toString(16);
1654
+ });
1655
+ localStorage.setItem("xtroedge_site_id", id);
1656
+ }
1657
+ return id;
1658
+ }
1659
+ // ===============================================
1660
+ // THEME COLOR
1661
+ // ===============================================
1662
+ hexToRgb(hex) {
1663
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1664
+ if (!result) return "0,200,83";
1665
+ return `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
1666
+ }
1667
+ getDarkerColor(hex) {
1668
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1669
+ if (!result) return "#2E7D32";
1670
+ const r = Math.max(0, Math.floor(parseInt(result[1], 16) * 0.6));
1671
+ const g = Math.max(0, Math.floor(parseInt(result[2], 16) * 0.6));
1672
+ const b = Math.max(0, Math.floor(parseInt(result[3], 16) * 0.6));
1673
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
1674
+ }
1675
+ applyThemeColor(color) {
1676
+ this.highlightColor = color;
1677
+ document.documentElement.style.setProperty("--lcms-primary", color);
1678
+ document.documentElement.style.setProperty("--lcms-primary-rgb", this.hexToRgb(color));
1679
+ document.documentElement.style.setProperty("--lcms-primary-dark", this.getDarkerColor(color));
1680
+ if (this.editMode) {
1681
+ for (const [el] of this.managedElements) {
1682
+ el.style.borderBottom = `2px dashed ${color}`;
1683
+ }
1684
+ for (const [img] of this.managedImages) {
1685
+ img.style.outline = `2px dashed ${color}`;
1686
+ }
1687
+ }
1688
+ const swatches = this.panelEl?.querySelectorAll(".lcms-theme-swatch");
1689
+ swatches?.forEach((s) => {
1690
+ s.classList.toggle("active", s.dataset.color === color);
1691
+ });
1692
+ localStorage.setItem("xtroedge_theme_color", color);
1693
+ }
1694
+ // ===============================================
1502
1695
  // STATIC CONVENIENCE
1503
1696
  // ===============================================
1504
1697
  /** Quick init - create and start CMS in one call */
@@ -1507,7 +1700,26 @@ var XtroedgeCMS = class _XtroedgeCMS {
1507
1700
  cms.init();
1508
1701
  return cms;
1509
1702
  }
1703
+ /** Auto-init: called automatically when package is loaded. No user code needed. */
1704
+ static autoInit() {
1705
+ if (window.__xtroedge_cms_instance__) return;
1706
+ const userConfig = window.__XTROEDGE_CMS_CONFIG__ || {};
1707
+ const cms = _XtroedgeCMS.create(userConfig);
1708
+ window.__xtroedge_cms_instance__ = cms;
1709
+ }
1510
1710
  };
1711
+
1712
+ // src/index.ts
1713
+ function boot() {
1714
+ XtroedgeCMS.autoInit();
1715
+ }
1716
+ if (typeof window !== "undefined") {
1717
+ if (document.readyState === "loading") {
1718
+ document.addEventListener("DOMContentLoaded", boot);
1719
+ } else {
1720
+ boot();
1721
+ }
1722
+ }
1511
1723
  // Annotate the CommonJS export names for ESM import in node:
1512
1724
  0 && (module.exports = {
1513
1725
  XtroedgeCMS