ngx-xtroedge-cms 1.3.17 → 1.4.1

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/LICENSE ADDED
@@ -0,0 +1,46 @@
1
+ XtroEdge CMS - Proprietary Software License
2
+
3
+ Copyright (c) 2024-2026 XtroEdge. All rights reserved.
4
+
5
+ IMPORTANT: READ THIS LICENSE AGREEMENT CAREFULLY BEFORE USING THIS SOFTWARE.
6
+
7
+ 1. GRANT OF LICENSE
8
+ This software is licensed, not sold. XtroEdge grants you a non-exclusive,
9
+ non-transferable, revocable license to use this software subject to a valid
10
+ subscription or active free trial period.
11
+
12
+ 2. FREE TRIAL
13
+ New users are granted a 30-day free trial starting from the date of
14
+ registration. During the trial period, all features are available. After
15
+ the trial period expires, a paid subscription ($10/month) is required.
16
+
17
+ 3. RESTRICTIONS
18
+ You may NOT:
19
+ - Copy, modify, merge, or create derivative works of this software
20
+ - Distribute, sublicense, sell, or transfer this software to any third party
21
+ - Reverse engineer, decompile, or disassemble this software
22
+ - Remove or alter any proprietary notices, labels, or marks
23
+ - Use this software after your license or trial has expired
24
+ - Share your license key with unauthorized parties
25
+
26
+ 4. SUBSCRIPTION
27
+ After the free trial, continued use requires an active subscription at the
28
+ current rate ($10/month). Failure to maintain an active subscription will
29
+ result in suspension of the software functionality.
30
+
31
+ 5. TERMINATION
32
+ This license is effective until terminated. XtroEdge may terminate this
33
+ license at any time if you fail to comply with any term of this agreement.
34
+ Upon termination, you must destroy all copies of the software.
35
+
36
+ 6. DISCLAIMER OF WARRANTIES
37
+ THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS
38
+ OR IMPLIED. XTROEDGE DOES NOT WARRANT THAT THE SOFTWARE WILL BE
39
+ UNINTERRUPTED OR ERROR-FREE.
40
+
41
+ 7. LIMITATION OF LIABILITY
42
+ IN NO EVENT SHALL XTROEDGE BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
43
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE.
44
+
45
+ For licensing inquiries: support@xtroedge.com
46
+ Website: https://xtroedge.com
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # xtro-edge-page-editor
package/dist/index.d.mts CHANGED
@@ -1,8 +1,12 @@
1
1
  /** Configuration for the CMS */
2
2
  interface XtroedgeCmsConfig {
3
- /** API base URL for save/publish/load endpoints (optional - only needed when backend is ready) */
3
+ /** Our XtroEdge server URL login, license, save, publish (required) */
4
4
  apiBase?: string;
5
- /** Base URL prepended to uploaded image paths (defaults to apiBase origin) */
5
+ /** Client's API server URL GET pages, image upload (falls back to apiBase if not set) */
6
+ clientApi?: string;
7
+ /** Headers to send with client API GET requests (e.g. {"x-data-source": "dev"}) */
8
+ clientHeaders?: Record<string, string>;
9
+ /** Base URL prepended to uploaded image paths (defaults to clientApi or apiBase origin) */
6
10
  imageBaseUrl?: string;
7
11
  /** CSS selector for the content container to scan (default: 'body') */
8
12
  containerSelector?: string;
@@ -20,6 +24,12 @@ interface XtroedgeCmsConfig {
20
24
  highlightColor?: string;
21
25
  /** Login API URL — if builder_token not found in localStorage, show login modal (default: apiBase + '/auth/login') */
22
26
  loginUrl?: string;
27
+ /** License key for subscription validation */
28
+ licenseKey?: string;
29
+ /** License validation API URL (default: apiBase + '/license/validate') */
30
+ licenseValidateUrl?: string;
31
+ /** Enable rich text toolbar for inline editing (default: true) */
32
+ richText?: boolean;
23
33
  onSaved?: () => void;
24
34
  onPublished?: () => void;
25
35
  onError?: (action: string, error: any) => void;
@@ -60,8 +70,25 @@ interface EditHistoryEntry {
60
70
  lang: string;
61
71
  snapshot: string;
62
72
  }
73
+ /** License validation response */
74
+ interface LicenseStatus {
75
+ valid: boolean;
76
+ plan: 'trial' | 'paid' | 'expired' | 'invalid';
77
+ daysLeft?: number;
78
+ message?: string;
79
+ }
63
80
 
64
81
  declare class XtroedgeCMS {
82
+ private static readonly _SK;
83
+ private static readonly _VAULT_KEY;
84
+ private static _enc;
85
+ private static _dec;
86
+ private static _readVault;
87
+ private static _writeVault;
88
+ private static secureSet;
89
+ private static secureGet;
90
+ private static secureRemove;
91
+ private static secureClear;
65
92
  private config;
66
93
  private containerSelector;
67
94
  private editableTags;
@@ -98,6 +125,7 @@ declare class XtroedgeCMS {
98
125
  private dirtyKeys;
99
126
  private dirtyImageKeys;
100
127
  private registeredKeys;
128
+ private domOriginals;
101
129
  private managedElements;
102
130
  private managedImages;
103
131
  private autoDetectedElements;
@@ -105,6 +133,11 @@ declare class XtroedgeCMS {
105
133
  private scanTimeout;
106
134
  private activeImageEl;
107
135
  private imageCtxMenu;
136
+ private floatingEditDialog;
137
+ private richToolbarEl;
138
+ private activeEditableEl;
139
+ private toolbarHideTimeout;
140
+ private selectionChangeHandler;
108
141
  private currentSlug;
109
142
  private currentTitle;
110
143
  private initialized;
@@ -132,6 +165,9 @@ declare class XtroedgeCMS {
132
165
  private editModeContent;
133
166
  private fileInput;
134
167
  private imgOverlay;
168
+ private editScrollHandler;
169
+ private editScrollRAF;
170
+ private editClickCaptureHandler;
135
171
  private posX;
136
172
  private posY;
137
173
  private isDragging;
@@ -141,6 +177,10 @@ declare class XtroedgeCMS {
141
177
  private startPosY;
142
178
  private hasMoved;
143
179
  private toastTimer;
180
+ private licenseValid;
181
+ private licenseStatus;
182
+ private licenseOverlayEl;
183
+ private trialBannerDismissed;
144
184
  private db;
145
185
  private boundMouseMove;
146
186
  private boundMouseUp;
@@ -150,8 +190,17 @@ declare class XtroedgeCMS {
150
190
  private boundHashChange;
151
191
  private translationCache;
152
192
  constructor(config?: XtroedgeCmsConfig);
153
- init(): void;
193
+ init(): Promise<void>;
154
194
  destroy(): void;
195
+ private static readonly LICENSE_CACHE_KEY;
196
+ private static readonly LICENSE_CACHE_TTL;
197
+ private validateLicense;
198
+ private getLicenseCache;
199
+ private setLicenseCache;
200
+ /** Shows toast when user tries to edit with expired/invalid license */
201
+ private showLicenseExpiredToast;
202
+ /** Returns trial/expired banner HTML if applicable, or empty string */
203
+ private getTrialBannerHTML;
155
204
  private injectStyles;
156
205
  private interceptNavigation;
157
206
  private handleNavigation;
@@ -166,12 +215,38 @@ declare class XtroedgeCMS {
166
215
  private scanImages;
167
216
  private getDirectTextContent;
168
217
  private hasEditableChildren;
218
+ private getElementContent;
219
+ private setElementContent;
169
220
  private setDirectTextContent;
170
221
  private attachElement;
171
222
  private detachElement;
223
+ /** Stop propagation so parent carousels (Swiper, Owl, etc.) don't hijack the event */
224
+ private static stopProp;
225
+ private focusEditableEnd;
172
226
  private enableElementEdit;
173
227
  private disableElementEdit;
174
228
  private applyEditMode;
229
+ /** Set of positioned ancestors we added pointer-events:none to (for cleanup) */
230
+ private modifiedAncestors;
231
+ /**
232
+ * For each managed element, find the nearest position:absolute/fixed ancestor.
233
+ * If that ancestor is invisible (opacity ≈ 0), set pointer-events:none on it
234
+ * so clicks pass through to the visible element behind it.
235
+ */
236
+ private syncEditablePointerEvents;
237
+ /** Walk up from el to find the nearest position:absolute or position:fixed ancestor */
238
+ private findPositionedAncestor;
239
+ private killAnimations;
240
+ /** Remove GSAP ScrollTrigger pin-spacer wrapper divs and restore original elements */
241
+ private removePinSpacers;
242
+ /** Clear only animation-related inline styles (set by GSAP/ScrollTrigger) without breaking layout */
243
+ private clearAnimationInlineStyles;
244
+ /** Capture each element's current DOM text before CMS applies saved edits */
245
+ private captureDomOriginals;
246
+ /** Ensure every entry in pageTexts has _orig for current language (from domOriginals) */
247
+ private ensureOriginals;
248
+ /** Find a managed element whose current text matches the given original text */
249
+ private findElementByOriginal;
175
250
  private updateElementTexts;
176
251
  private cleanupManagedElements;
177
252
  private attachImage;
@@ -182,6 +257,8 @@ declare class XtroedgeCMS {
182
257
  private disableImageEdit;
183
258
  private showImageContextMenu;
184
259
  private dismissImageCtxMenu;
260
+ private showFloatingEditDialog;
261
+ private dismissFloatingEditDialog;
185
262
  private onImageFileSelected;
186
263
  private uploadImageToApi;
187
264
  private applyPageImages;
@@ -190,6 +267,18 @@ declare class XtroedgeCMS {
190
267
  private onImageChanged;
191
268
  private createSnapshot;
192
269
  private applySnapshot;
270
+ private get richTextEnabled();
271
+ private static readonly SINGLE_LINE_TAGS;
272
+ private static readonly ALLOWED_TAGS;
273
+ private static readonly ALLOWED_ATTRS;
274
+ private sanitizeHTML;
275
+ private createRichToolbar;
276
+ private destroyRichToolbar;
277
+ private execToolbarCommand;
278
+ private showRichToolbar;
279
+ private positionToolbar;
280
+ private hideRichToolbar;
281
+ private updateToolbarState;
193
282
  private onUndo;
194
283
  private onRedo;
195
284
  private recalcDirtyKeys;
@@ -200,6 +289,10 @@ declare class XtroedgeCMS {
200
289
  private loadTranslationsAndInit;
201
290
  private flattenTranslations;
202
291
  private getPageSection;
292
+ /** Resolve a stored URL against our server (apiBase) */
293
+ private resolveServerUrl;
294
+ /** Resolve a stored URL against client's server (clientApi, falls back to apiBase) */
295
+ private resolveClientUrl;
203
296
  private apiFetch;
204
297
  private fetchSection;
205
298
  private hasSection;
@@ -239,9 +332,9 @@ declare class XtroedgeCMS {
239
332
  private getDarkerColor;
240
333
  private applyThemeColor;
241
334
  /** Quick init - create and start CMS in one call */
242
- static create(config?: XtroedgeCmsConfig): XtroedgeCMS;
335
+ static create(config?: XtroedgeCmsConfig): Promise<XtroedgeCMS>;
243
336
  /** Auto-init: called automatically when package is loaded. No user code needed. */
244
- static autoInit(): void;
337
+ static autoInit(): Promise<void>;
245
338
  }
246
339
 
247
- export { type EditHistoryEntry, type PageTextEntry, type WebPageContent, XtroedgeCMS, type XtroedgeCmsConfig };
340
+ export { type EditHistoryEntry, type LicenseStatus, type PageTextEntry, type WebPageContent, XtroedgeCMS, type XtroedgeCmsConfig };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  /** Configuration for the CMS */
2
2
  interface XtroedgeCmsConfig {
3
- /** API base URL for save/publish/load endpoints (optional - only needed when backend is ready) */
3
+ /** Our XtroEdge server URL login, license, save, publish (required) */
4
4
  apiBase?: string;
5
- /** Base URL prepended to uploaded image paths (defaults to apiBase origin) */
5
+ /** Client's API server URL GET pages, image upload (falls back to apiBase if not set) */
6
+ clientApi?: string;
7
+ /** Headers to send with client API GET requests (e.g. {"x-data-source": "dev"}) */
8
+ clientHeaders?: Record<string, string>;
9
+ /** Base URL prepended to uploaded image paths (defaults to clientApi or apiBase origin) */
6
10
  imageBaseUrl?: string;
7
11
  /** CSS selector for the content container to scan (default: 'body') */
8
12
  containerSelector?: string;
@@ -20,6 +24,12 @@ interface XtroedgeCmsConfig {
20
24
  highlightColor?: string;
21
25
  /** Login API URL — if builder_token not found in localStorage, show login modal (default: apiBase + '/auth/login') */
22
26
  loginUrl?: string;
27
+ /** License key for subscription validation */
28
+ licenseKey?: string;
29
+ /** License validation API URL (default: apiBase + '/license/validate') */
30
+ licenseValidateUrl?: string;
31
+ /** Enable rich text toolbar for inline editing (default: true) */
32
+ richText?: boolean;
23
33
  onSaved?: () => void;
24
34
  onPublished?: () => void;
25
35
  onError?: (action: string, error: any) => void;
@@ -60,8 +70,25 @@ interface EditHistoryEntry {
60
70
  lang: string;
61
71
  snapshot: string;
62
72
  }
73
+ /** License validation response */
74
+ interface LicenseStatus {
75
+ valid: boolean;
76
+ plan: 'trial' | 'paid' | 'expired' | 'invalid';
77
+ daysLeft?: number;
78
+ message?: string;
79
+ }
63
80
 
64
81
  declare class XtroedgeCMS {
82
+ private static readonly _SK;
83
+ private static readonly _VAULT_KEY;
84
+ private static _enc;
85
+ private static _dec;
86
+ private static _readVault;
87
+ private static _writeVault;
88
+ private static secureSet;
89
+ private static secureGet;
90
+ private static secureRemove;
91
+ private static secureClear;
65
92
  private config;
66
93
  private containerSelector;
67
94
  private editableTags;
@@ -98,6 +125,7 @@ declare class XtroedgeCMS {
98
125
  private dirtyKeys;
99
126
  private dirtyImageKeys;
100
127
  private registeredKeys;
128
+ private domOriginals;
101
129
  private managedElements;
102
130
  private managedImages;
103
131
  private autoDetectedElements;
@@ -105,6 +133,11 @@ declare class XtroedgeCMS {
105
133
  private scanTimeout;
106
134
  private activeImageEl;
107
135
  private imageCtxMenu;
136
+ private floatingEditDialog;
137
+ private richToolbarEl;
138
+ private activeEditableEl;
139
+ private toolbarHideTimeout;
140
+ private selectionChangeHandler;
108
141
  private currentSlug;
109
142
  private currentTitle;
110
143
  private initialized;
@@ -132,6 +165,9 @@ declare class XtroedgeCMS {
132
165
  private editModeContent;
133
166
  private fileInput;
134
167
  private imgOverlay;
168
+ private editScrollHandler;
169
+ private editScrollRAF;
170
+ private editClickCaptureHandler;
135
171
  private posX;
136
172
  private posY;
137
173
  private isDragging;
@@ -141,6 +177,10 @@ declare class XtroedgeCMS {
141
177
  private startPosY;
142
178
  private hasMoved;
143
179
  private toastTimer;
180
+ private licenseValid;
181
+ private licenseStatus;
182
+ private licenseOverlayEl;
183
+ private trialBannerDismissed;
144
184
  private db;
145
185
  private boundMouseMove;
146
186
  private boundMouseUp;
@@ -150,8 +190,17 @@ declare class XtroedgeCMS {
150
190
  private boundHashChange;
151
191
  private translationCache;
152
192
  constructor(config?: XtroedgeCmsConfig);
153
- init(): void;
193
+ init(): Promise<void>;
154
194
  destroy(): void;
195
+ private static readonly LICENSE_CACHE_KEY;
196
+ private static readonly LICENSE_CACHE_TTL;
197
+ private validateLicense;
198
+ private getLicenseCache;
199
+ private setLicenseCache;
200
+ /** Shows toast when user tries to edit with expired/invalid license */
201
+ private showLicenseExpiredToast;
202
+ /** Returns trial/expired banner HTML if applicable, or empty string */
203
+ private getTrialBannerHTML;
155
204
  private injectStyles;
156
205
  private interceptNavigation;
157
206
  private handleNavigation;
@@ -166,12 +215,38 @@ declare class XtroedgeCMS {
166
215
  private scanImages;
167
216
  private getDirectTextContent;
168
217
  private hasEditableChildren;
218
+ private getElementContent;
219
+ private setElementContent;
169
220
  private setDirectTextContent;
170
221
  private attachElement;
171
222
  private detachElement;
223
+ /** Stop propagation so parent carousels (Swiper, Owl, etc.) don't hijack the event */
224
+ private static stopProp;
225
+ private focusEditableEnd;
172
226
  private enableElementEdit;
173
227
  private disableElementEdit;
174
228
  private applyEditMode;
229
+ /** Set of positioned ancestors we added pointer-events:none to (for cleanup) */
230
+ private modifiedAncestors;
231
+ /**
232
+ * For each managed element, find the nearest position:absolute/fixed ancestor.
233
+ * If that ancestor is invisible (opacity ≈ 0), set pointer-events:none on it
234
+ * so clicks pass through to the visible element behind it.
235
+ */
236
+ private syncEditablePointerEvents;
237
+ /** Walk up from el to find the nearest position:absolute or position:fixed ancestor */
238
+ private findPositionedAncestor;
239
+ private killAnimations;
240
+ /** Remove GSAP ScrollTrigger pin-spacer wrapper divs and restore original elements */
241
+ private removePinSpacers;
242
+ /** Clear only animation-related inline styles (set by GSAP/ScrollTrigger) without breaking layout */
243
+ private clearAnimationInlineStyles;
244
+ /** Capture each element's current DOM text before CMS applies saved edits */
245
+ private captureDomOriginals;
246
+ /** Ensure every entry in pageTexts has _orig for current language (from domOriginals) */
247
+ private ensureOriginals;
248
+ /** Find a managed element whose current text matches the given original text */
249
+ private findElementByOriginal;
175
250
  private updateElementTexts;
176
251
  private cleanupManagedElements;
177
252
  private attachImage;
@@ -182,6 +257,8 @@ declare class XtroedgeCMS {
182
257
  private disableImageEdit;
183
258
  private showImageContextMenu;
184
259
  private dismissImageCtxMenu;
260
+ private showFloatingEditDialog;
261
+ private dismissFloatingEditDialog;
185
262
  private onImageFileSelected;
186
263
  private uploadImageToApi;
187
264
  private applyPageImages;
@@ -190,6 +267,18 @@ declare class XtroedgeCMS {
190
267
  private onImageChanged;
191
268
  private createSnapshot;
192
269
  private applySnapshot;
270
+ private get richTextEnabled();
271
+ private static readonly SINGLE_LINE_TAGS;
272
+ private static readonly ALLOWED_TAGS;
273
+ private static readonly ALLOWED_ATTRS;
274
+ private sanitizeHTML;
275
+ private createRichToolbar;
276
+ private destroyRichToolbar;
277
+ private execToolbarCommand;
278
+ private showRichToolbar;
279
+ private positionToolbar;
280
+ private hideRichToolbar;
281
+ private updateToolbarState;
193
282
  private onUndo;
194
283
  private onRedo;
195
284
  private recalcDirtyKeys;
@@ -200,6 +289,10 @@ declare class XtroedgeCMS {
200
289
  private loadTranslationsAndInit;
201
290
  private flattenTranslations;
202
291
  private getPageSection;
292
+ /** Resolve a stored URL against our server (apiBase) */
293
+ private resolveServerUrl;
294
+ /** Resolve a stored URL against client's server (clientApi, falls back to apiBase) */
295
+ private resolveClientUrl;
203
296
  private apiFetch;
204
297
  private fetchSection;
205
298
  private hasSection;
@@ -239,9 +332,9 @@ declare class XtroedgeCMS {
239
332
  private getDarkerColor;
240
333
  private applyThemeColor;
241
334
  /** Quick init - create and start CMS in one call */
242
- static create(config?: XtroedgeCmsConfig): XtroedgeCMS;
335
+ static create(config?: XtroedgeCmsConfig): Promise<XtroedgeCMS>;
243
336
  /** Auto-init: called automatically when package is loaded. No user code needed. */
244
- static autoInit(): void;
337
+ static autoInit(): Promise<void>;
245
338
  }
246
339
 
247
- export { type EditHistoryEntry, type PageTextEntry, type WebPageContent, XtroedgeCMS, type XtroedgeCmsConfig };
340
+ export { type EditHistoryEntry, type LicenseStatus, type PageTextEntry, type WebPageContent, XtroedgeCMS, type XtroedgeCmsConfig };