@kustomizer/visual-editor 0.0.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.
@@ -0,0 +1,2235 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken, Type, EnvironmentProviders, OnInit, OnDestroy } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+ import * as _ngrx_store from '@ngrx/store';
5
+ import * as _kustomizer_visual_editor from '@kustomizer/visual-editor';
6
+ import { SafeHtml } from '@angular/platform-browser';
7
+ import { Session, User, SupabaseClient } from '@supabase/supabase-js';
8
+ import { CanActivateFn } from '@angular/router';
9
+
10
+ /**
11
+ * Navigation target for the visual editor
12
+ */
13
+ type VisualEditorNavigationTarget = {
14
+ type: 'page-list';
15
+ } | {
16
+ type: 'page-edit';
17
+ pageId: string;
18
+ } | {
19
+ type: 'page-preview';
20
+ pageId: string;
21
+ };
22
+ /**
23
+ * Confirmation dialog options
24
+ */
25
+ interface ConfirmDialogOptions {
26
+ title: string;
27
+ message: string;
28
+ confirmText?: string;
29
+ cancelText?: string;
30
+ }
31
+ /**
32
+ * Abstract navigation service that consumers can implement
33
+ * to customize how the visual editor navigates between views
34
+ */
35
+ declare abstract class VisualEditorNavigation {
36
+ /**
37
+ * Navigate to a target within the editor context
38
+ */
39
+ abstract navigate(target: VisualEditorNavigationTarget): void;
40
+ /**
41
+ * Show a confirmation dialog
42
+ * Returns Observable<boolean> to support async dialogs (e.g., Material Dialog)
43
+ */
44
+ abstract confirm(options: ConfirmDialogOptions): Observable<boolean>;
45
+ /**
46
+ * Get the current page ID from the navigation context
47
+ * Returns null if not on a page edit route
48
+ */
49
+ abstract getCurrentPageId(): Observable<string | null>;
50
+ }
51
+
52
+ interface EditorElement {
53
+ id: string;
54
+ type: string;
55
+ props: Record<string, unknown>;
56
+ slotName?: string;
57
+ children?: EditorElement[];
58
+ adminLabel?: string;
59
+ }
60
+ interface EditorSection {
61
+ id: string;
62
+ type: string;
63
+ props: Record<string, unknown>;
64
+ elements: EditorElement[];
65
+ adminLabel?: string;
66
+ }
67
+ interface HistoryEntry {
68
+ sections: EditorSection[];
69
+ timestamp: number;
70
+ actionType: string;
71
+ }
72
+ interface VisualEditorState {
73
+ sections: EditorSection[];
74
+ selectedElementId: string | null;
75
+ selectedSectionId: string | null;
76
+ isDragging: boolean;
77
+ draggedElementId: string | null;
78
+ history: HistoryEntry[];
79
+ historyIndex: number;
80
+ maxHistorySize: number;
81
+ currentPage: PageContext | null;
82
+ isDirty: boolean;
83
+ }
84
+ declare const initialVisualEditorState: VisualEditorState;
85
+ declare const VISUAL_EDITOR_FEATURE_KEY = "visualEditor";
86
+
87
+ declare const SHOPIFY_API_VERSION = "2026-01";
88
+ interface ShopifyConfig {
89
+ shopDomain: string;
90
+ accessToken: string;
91
+ apiVersion: string;
92
+ }
93
+ declare const SHOPIFY_CONFIG: InjectionToken<ShopifyConfig | Observable<ShopifyConfig>>;
94
+ /**
95
+ * Metafield representation from Shopify
96
+ */
97
+ interface Metafield {
98
+ id: string;
99
+ namespace: string;
100
+ key: string;
101
+ value: string;
102
+ type: string;
103
+ createdAt?: string;
104
+ updatedAt?: string;
105
+ }
106
+ /**
107
+ * Page status - draft pages are only visible in admin, published pages are public
108
+ */
109
+ type PageStatus = 'draft' | 'published';
110
+ /**
111
+ * Entry in the pages index (lightweight reference)
112
+ */
113
+ interface PageIndexEntry {
114
+ id: string;
115
+ slug: string;
116
+ title: string;
117
+ status: PageStatus;
118
+ updatedAt: string;
119
+ publishedAt?: string;
120
+ size: number;
121
+ }
122
+ /**
123
+ * Index of all pages stored in a single metafield
124
+ */
125
+ interface PagesIndex {
126
+ version: number;
127
+ lastUpdated: string;
128
+ pages: PageIndexEntry[];
129
+ }
130
+ /**
131
+ * Full page model with all content
132
+ */
133
+ interface Page {
134
+ id: string;
135
+ slug: string;
136
+ title: string;
137
+ description?: string;
138
+ sections: EditorSection[];
139
+ status: PageStatus;
140
+ createdAt: string;
141
+ updatedAt: string;
142
+ publishedAt?: string;
143
+ version: number;
144
+ }
145
+ /**
146
+ * Lightweight page summary for listing
147
+ */
148
+ interface PageSummary {
149
+ id: string;
150
+ slug: string;
151
+ title: string;
152
+ status: PageStatus;
153
+ updatedAt: string;
154
+ publishedAt?: string;
155
+ }
156
+ /**
157
+ * Page context stored in editor state (minimal info needed while editing)
158
+ */
159
+ interface PageContext {
160
+ id: string;
161
+ slug: string;
162
+ title: string;
163
+ status: PageStatus;
164
+ version: number;
165
+ }
166
+ /**
167
+ * Request payload for creating a new page
168
+ */
169
+ interface CreatePageRequest {
170
+ title: string;
171
+ slug: string;
172
+ description?: string;
173
+ }
174
+ /**
175
+ * Request payload for updating an existing page
176
+ */
177
+ interface UpdatePageRequest {
178
+ title?: string;
179
+ slug?: string;
180
+ description?: string;
181
+ sections?: EditorSection[];
182
+ version: number;
183
+ }
184
+ /**
185
+ * Request payload for publishing/unpublishing
186
+ */
187
+ interface PublishPageRequest {
188
+ version: number;
189
+ }
190
+
191
+ /**
192
+ * Abstract strategy for loading pages into the editor
193
+ * Consumers can implement custom strategies for different use cases
194
+ */
195
+ declare abstract class PageLoadingStrategy {
196
+ /**
197
+ * Load a page by ID
198
+ */
199
+ abstract loadPage(pageId: string): Observable<Page>;
200
+ /**
201
+ * Get the current page ID to load
202
+ * This abstracts the source of the page ID (route, input, etc.)
203
+ */
204
+ abstract getPageIdToLoad(): Observable<string | null>;
205
+ }
206
+ /**
207
+ * Default strategy that uses route params via the navigation service
208
+ */
209
+ declare class RoutePageLoadingStrategy extends PageLoadingStrategy {
210
+ private readonly pageService;
211
+ private readonly navigation;
212
+ loadPage(pageId: string): Observable<Page>;
213
+ getPageIdToLoad(): Observable<string | null>;
214
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RoutePageLoadingStrategy, never>;
215
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<RoutePageLoadingStrategy>;
216
+ }
217
+ /**
218
+ * Input-based strategy for when page is passed via component input
219
+ * Useful for embedding the editor in modals or custom layouts
220
+ */
221
+ declare class InputPageLoadingStrategy extends PageLoadingStrategy {
222
+ private readonly pageService;
223
+ private readonly pageId$;
224
+ /**
225
+ * Set the page ID to load
226
+ * Call this when the input changes
227
+ */
228
+ setPageId(pageId: string | null): void;
229
+ loadPage(pageId: string): Observable<Page>;
230
+ getPageIdToLoad(): Observable<string | null>;
231
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<InputPageLoadingStrategy, never>;
232
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<InputPageLoadingStrategy>;
233
+ }
234
+
235
+ /**
236
+ * Configuration for the default router navigation
237
+ */
238
+ interface RouterNavigationConfig {
239
+ /** Route path for page list (default: '/admin') */
240
+ pageListPath: string;
241
+ /** Route path pattern for page edit (default: '/admin/pages/:pageId') */
242
+ pageEditPath: string;
243
+ /** Route path pattern for preview (optional) */
244
+ pagePreviewPath?: string;
245
+ /** Route param name for page ID (default: 'pageId') */
246
+ pageIdParam: string;
247
+ }
248
+ /**
249
+ * Default router navigation configuration
250
+ */
251
+ declare const DEFAULT_ROUTER_NAVIGATION_CONFIG: RouterNavigationConfig;
252
+ /**
253
+ * Injection token for router navigation configuration
254
+ */
255
+ declare const ROUTER_NAVIGATION_CONFIG: InjectionToken<RouterNavigationConfig>;
256
+ /**
257
+ * Default navigation service implementation using Angular Router
258
+ */
259
+ declare class DefaultRouterNavigationService extends VisualEditorNavigation {
260
+ private readonly router;
261
+ private readonly route;
262
+ private readonly config;
263
+ navigate(target: VisualEditorNavigationTarget): void;
264
+ confirm(options: ConfirmDialogOptions): Observable<boolean>;
265
+ getCurrentPageId(): Observable<string | null>;
266
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DefaultRouterNavigationService, never>;
267
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DefaultRouterNavigationService>;
268
+ }
269
+
270
+ /**
271
+ * Main configuration interface for the Visual Editor library
272
+ */
273
+ interface VisualEditorConfig {
274
+ /**
275
+ * Navigation configuration
276
+ */
277
+ navigation?: {
278
+ /**
279
+ * Custom navigation service class
280
+ * If provided, routerConfig is ignored
281
+ */
282
+ navigationService?: Type<VisualEditorNavigation>;
283
+ /**
284
+ * Router-based config (used with DefaultRouterNavigationService)
285
+ * Only used if navigationService is not provided
286
+ */
287
+ routerConfig?: Partial<RouterNavigationConfig>;
288
+ };
289
+ /**
290
+ * Page loading configuration
291
+ */
292
+ pageLoading?: {
293
+ /**
294
+ * Custom page loading strategy
295
+ * Defaults to RoutePageLoadingStrategy
296
+ */
297
+ strategy?: Type<PageLoadingStrategy>;
298
+ };
299
+ /**
300
+ * Page service configuration
301
+ */
302
+ pages?: {
303
+ /**
304
+ * Use in-memory storage instead of Shopify
305
+ * Useful for development and demos
306
+ * Defaults to false (uses Shopify)
307
+ */
308
+ useInMemory?: boolean;
309
+ };
310
+ /**
311
+ * UI configuration
312
+ */
313
+ ui?: {
314
+ /**
315
+ * Show back button in editor toolbar
316
+ * Defaults to true
317
+ */
318
+ showBackButton?: boolean;
319
+ /**
320
+ * Show publish/unpublish buttons
321
+ * Defaults to true
322
+ */
323
+ showPublishButtons?: boolean;
324
+ /**
325
+ * Show save button
326
+ * Defaults to true
327
+ */
328
+ showSaveButton?: boolean;
329
+ };
330
+ }
331
+ /**
332
+ * Injection token for the Visual Editor configuration
333
+ */
334
+ declare const VISUAL_EDITOR_CONFIG: InjectionToken<VisualEditorConfig>;
335
+ /**
336
+ * Default configuration values
337
+ */
338
+ declare const DEFAULT_VISUAL_EDITOR_CONFIG: Required<VisualEditorConfig>;
339
+
340
+ /**
341
+ * Provides all necessary services and configuration for the Visual Editor
342
+ *
343
+ * Note: You must also call provideVisualEditorStore() to set up the NgRx state.
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * // Minimal setup (uses Shopify by default)
348
+ * export const appConfig: ApplicationConfig = {
349
+ * providers: [
350
+ * provideStore(),
351
+ * provideVisualEditorStore(), // Required: sets up NgRx state
352
+ * provideVisualEditor(), // Sets up services and config
353
+ * provideEditorComponents(myComponents),
354
+ * ],
355
+ * };
356
+ *
357
+ * // With custom configuration
358
+ * provideVisualEditor({
359
+ * navigation: {
360
+ * routerConfig: {
361
+ * pageListPath: '/cms',
362
+ * pageEditPath: '/cms/editor/:id',
363
+ * pageIdParam: 'id',
364
+ * }
365
+ * },
366
+ * pages: {
367
+ * useInMemory: true // Use in-memory storage for development
368
+ * }
369
+ * })
370
+ * ```
371
+ */
372
+ declare function provideVisualEditor(config?: VisualEditorConfig): EnvironmentProviders;
373
+
374
+ declare const VisualEditorActions: {
375
+ addSection: _ngrx_store.ActionCreator<"[Visual Editor] Add Section", (props: {
376
+ section: EditorSection;
377
+ index?: number;
378
+ }) => {
379
+ section: EditorSection;
380
+ index?: number;
381
+ } & _ngrx_store.Action<"[Visual Editor] Add Section">>;
382
+ removeSection: _ngrx_store.ActionCreator<"[Visual Editor] Remove Section", (props: {
383
+ sectionId: string;
384
+ }) => {
385
+ sectionId: string;
386
+ } & _ngrx_store.Action<"[Visual Editor] Remove Section">>;
387
+ moveSection: _ngrx_store.ActionCreator<"[Visual Editor] Move Section", (props: {
388
+ sectionId: string;
389
+ newIndex: number;
390
+ }) => {
391
+ sectionId: string;
392
+ newIndex: number;
393
+ } & _ngrx_store.Action<"[Visual Editor] Move Section">>;
394
+ updateSection: _ngrx_store.ActionCreator<"[Visual Editor] Update Section", (props: {
395
+ sectionId: string;
396
+ changes: Partial<EditorSection>;
397
+ }) => {
398
+ sectionId: string;
399
+ changes: Partial<EditorSection>;
400
+ } & _ngrx_store.Action<"[Visual Editor] Update Section">>;
401
+ updateSectionProps: _ngrx_store.ActionCreator<"[Visual Editor] Update Section Props", (props: {
402
+ sectionId: string;
403
+ props: Record<string, unknown>;
404
+ }) => {
405
+ sectionId: string;
406
+ props: Record<string, unknown>;
407
+ } & _ngrx_store.Action<"[Visual Editor] Update Section Props">>;
408
+ addElement: _ngrx_store.ActionCreator<"[Visual Editor] Add Element", (props: {
409
+ sectionId: string;
410
+ element: EditorElement;
411
+ index?: number;
412
+ }) => {
413
+ sectionId: string;
414
+ element: EditorElement;
415
+ index?: number;
416
+ } & _ngrx_store.Action<"[Visual Editor] Add Element">>;
417
+ removeElement: _ngrx_store.ActionCreator<"[Visual Editor] Remove Element", (props: {
418
+ sectionId: string;
419
+ elementId: string;
420
+ }) => {
421
+ sectionId: string;
422
+ elementId: string;
423
+ } & _ngrx_store.Action<"[Visual Editor] Remove Element">>;
424
+ moveElement: _ngrx_store.ActionCreator<"[Visual Editor] Move Element", (props: {
425
+ sourceSectionId: string;
426
+ targetSectionId: string;
427
+ elementId: string;
428
+ newIndex: number;
429
+ }) => {
430
+ sourceSectionId: string;
431
+ targetSectionId: string;
432
+ elementId: string;
433
+ newIndex: number;
434
+ } & _ngrx_store.Action<"[Visual Editor] Move Element">>;
435
+ updateElement: _ngrx_store.ActionCreator<"[Visual Editor] Update Element", (props: {
436
+ sectionId: string;
437
+ elementId: string;
438
+ changes: Partial<EditorElement>;
439
+ }) => {
440
+ sectionId: string;
441
+ elementId: string;
442
+ changes: Partial<EditorElement>;
443
+ } & _ngrx_store.Action<"[Visual Editor] Update Element">>;
444
+ updateElementProps: _ngrx_store.ActionCreator<"[Visual Editor] Update Element Props", (props: {
445
+ sectionId: string;
446
+ elementId: string;
447
+ props: Record<string, unknown>;
448
+ }) => {
449
+ sectionId: string;
450
+ elementId: string;
451
+ props: Record<string, unknown>;
452
+ } & _ngrx_store.Action<"[Visual Editor] Update Element Props">>;
453
+ addBlock: _ngrx_store.ActionCreator<"[Visual Editor] Add Block", (props: {
454
+ sectionId: string;
455
+ slotName: string;
456
+ element: EditorElement;
457
+ index?: number;
458
+ }) => {
459
+ sectionId: string;
460
+ slotName: string;
461
+ element: EditorElement;
462
+ index?: number;
463
+ } & _ngrx_store.Action<"[Visual Editor] Add Block">>;
464
+ removeBlock: _ngrx_store.ActionCreator<"[Visual Editor] Remove Block", (props: {
465
+ sectionId: string;
466
+ elementId: string;
467
+ }) => {
468
+ sectionId: string;
469
+ elementId: string;
470
+ } & _ngrx_store.Action<"[Visual Editor] Remove Block">>;
471
+ moveBlock: _ngrx_store.ActionCreator<"[Visual Editor] Move Block", (props: {
472
+ sectionId: string;
473
+ elementId: string;
474
+ targetSlotName: string;
475
+ newIndex: number;
476
+ }) => {
477
+ sectionId: string;
478
+ elementId: string;
479
+ targetSlotName: string;
480
+ newIndex: number;
481
+ } & _ngrx_store.Action<"[Visual Editor] Move Block">>;
482
+ updateBlockProps: _ngrx_store.ActionCreator<"[Visual Editor] Update Block Props", (props: {
483
+ sectionId: string;
484
+ elementId: string;
485
+ props: Record<string, unknown>;
486
+ }) => {
487
+ sectionId: string;
488
+ elementId: string;
489
+ props: Record<string, unknown>;
490
+ } & _ngrx_store.Action<"[Visual Editor] Update Block Props">>;
491
+ renameSection: _ngrx_store.ActionCreator<"[Visual Editor] Rename Section", (props: {
492
+ sectionId: string;
493
+ adminLabel: string;
494
+ }) => {
495
+ sectionId: string;
496
+ adminLabel: string;
497
+ } & _ngrx_store.Action<"[Visual Editor] Rename Section">>;
498
+ renameBlock: _ngrx_store.ActionCreator<"[Visual Editor] Rename Block", (props: {
499
+ sectionId: string;
500
+ elementId: string;
501
+ adminLabel: string;
502
+ }) => {
503
+ sectionId: string;
504
+ elementId: string;
505
+ adminLabel: string;
506
+ } & _ngrx_store.Action<"[Visual Editor] Rename Block">>;
507
+ duplicateSection: _ngrx_store.ActionCreator<"[Visual Editor] Duplicate Section", (props: {
508
+ sectionId: string;
509
+ }) => {
510
+ sectionId: string;
511
+ } & _ngrx_store.Action<"[Visual Editor] Duplicate Section">>;
512
+ duplicateBlock: _ngrx_store.ActionCreator<"[Visual Editor] Duplicate Block", (props: {
513
+ sectionId: string;
514
+ elementId: string;
515
+ }) => {
516
+ sectionId: string;
517
+ elementId: string;
518
+ } & _ngrx_store.Action<"[Visual Editor] Duplicate Block">>;
519
+ duplicateNestedBlock: _ngrx_store.ActionCreator<"[Visual Editor] Duplicate Nested Block", (props: {
520
+ sectionId: string;
521
+ parentPath: string[];
522
+ elementId: string;
523
+ }) => {
524
+ sectionId: string;
525
+ parentPath: string[];
526
+ elementId: string;
527
+ } & _ngrx_store.Action<"[Visual Editor] Duplicate Nested Block">>;
528
+ addNestedBlock: _ngrx_store.ActionCreator<"[Visual Editor] Add Nested Block", (props: {
529
+ sectionId: string;
530
+ parentPath: string[];
531
+ slotName: string;
532
+ element: EditorElement;
533
+ index?: number;
534
+ }) => {
535
+ sectionId: string;
536
+ parentPath: string[];
537
+ slotName: string;
538
+ element: EditorElement;
539
+ index?: number;
540
+ } & _ngrx_store.Action<"[Visual Editor] Add Nested Block">>;
541
+ removeNestedBlock: _ngrx_store.ActionCreator<"[Visual Editor] Remove Nested Block", (props: {
542
+ sectionId: string;
543
+ parentPath: string[];
544
+ elementId: string;
545
+ }) => {
546
+ sectionId: string;
547
+ parentPath: string[];
548
+ elementId: string;
549
+ } & _ngrx_store.Action<"[Visual Editor] Remove Nested Block">>;
550
+ updateNestedBlockProps: _ngrx_store.ActionCreator<"[Visual Editor] Update Nested Block Props", (props: {
551
+ sectionId: string;
552
+ parentPath: string[];
553
+ elementId: string;
554
+ props: Record<string, unknown>;
555
+ }) => {
556
+ sectionId: string;
557
+ parentPath: string[];
558
+ elementId: string;
559
+ props: Record<string, unknown>;
560
+ } & _ngrx_store.Action<"[Visual Editor] Update Nested Block Props">>;
561
+ moveNestedBlock: _ngrx_store.ActionCreator<"[Visual Editor] Move Nested Block", (props: {
562
+ sectionId: string;
563
+ parentPath: string[];
564
+ elementId: string;
565
+ targetSlotName: string;
566
+ newIndex: number;
567
+ }) => {
568
+ sectionId: string;
569
+ parentPath: string[];
570
+ elementId: string;
571
+ targetSlotName: string;
572
+ newIndex: number;
573
+ } & _ngrx_store.Action<"[Visual Editor] Move Nested Block">>;
574
+ reparentBlock: _ngrx_store.ActionCreator<"[Visual Editor] Reparent Block", (props: {
575
+ sourceSectionId: string;
576
+ sourceParentPath: string[];
577
+ elementId: string;
578
+ targetSectionId: string;
579
+ targetParentPath: string[];
580
+ targetSlotName: string;
581
+ targetIndex: number;
582
+ }) => {
583
+ sourceSectionId: string;
584
+ sourceParentPath: string[];
585
+ elementId: string;
586
+ targetSectionId: string;
587
+ targetParentPath: string[];
588
+ targetSlotName: string;
589
+ targetIndex: number;
590
+ } & _ngrx_store.Action<"[Visual Editor] Reparent Block">>;
591
+ selectElement: _ngrx_store.ActionCreator<"[Visual Editor] Select Element", (props: {
592
+ sectionId: string | null;
593
+ elementId: string | null;
594
+ }) => {
595
+ sectionId: string | null;
596
+ elementId: string | null;
597
+ } & _ngrx_store.Action<"[Visual Editor] Select Element">>;
598
+ clearSelection: _ngrx_store.ActionCreator<"[Visual Editor] Clear Selection", () => _ngrx_store.Action<"[Visual Editor] Clear Selection">>;
599
+ startDrag: _ngrx_store.ActionCreator<"[Visual Editor] Start Drag", (props: {
600
+ elementId: string;
601
+ }) => {
602
+ elementId: string;
603
+ } & _ngrx_store.Action<"[Visual Editor] Start Drag">>;
604
+ endDrag: _ngrx_store.ActionCreator<"[Visual Editor] End Drag", () => _ngrx_store.Action<"[Visual Editor] End Drag">>;
605
+ undo: _ngrx_store.ActionCreator<"[Visual Editor] Undo", () => _ngrx_store.Action<"[Visual Editor] Undo">>;
606
+ redo: _ngrx_store.ActionCreator<"[Visual Editor] Redo", () => _ngrx_store.Action<"[Visual Editor] Redo">>;
607
+ clearHistory: _ngrx_store.ActionCreator<"[Visual Editor] Clear History", () => _ngrx_store.Action<"[Visual Editor] Clear History">>;
608
+ loadSections: _ngrx_store.ActionCreator<"[Visual Editor] Load Sections", (props: {
609
+ sections: EditorSection[];
610
+ }) => {
611
+ sections: EditorSection[];
612
+ } & _ngrx_store.Action<"[Visual Editor] Load Sections">>;
613
+ resetEditor: _ngrx_store.ActionCreator<"[Visual Editor] Reset Editor", () => _ngrx_store.Action<"[Visual Editor] Reset Editor">>;
614
+ loadPage: _ngrx_store.ActionCreator<"[Visual Editor] Load Page", (props: {
615
+ page: Page;
616
+ }) => {
617
+ page: Page;
618
+ } & _ngrx_store.Action<"[Visual Editor] Load Page">>;
619
+ updatePageContext: _ngrx_store.ActionCreator<"[Visual Editor] Update Page Context", (props: {
620
+ context: Partial<PageContext>;
621
+ }) => {
622
+ context: Partial<PageContext>;
623
+ } & _ngrx_store.Action<"[Visual Editor] Update Page Context">>;
624
+ markDirty: _ngrx_store.ActionCreator<"[Visual Editor] Mark Dirty", () => _ngrx_store.Action<"[Visual Editor] Mark Dirty">>;
625
+ markClean: _ngrx_store.ActionCreator<"[Visual Editor] Mark Clean", () => _ngrx_store.Action<"[Visual Editor] Mark Clean">>;
626
+ clearPage: _ngrx_store.ActionCreator<"[Visual Editor] Clear Page", () => _ngrx_store.Action<"[Visual Editor] Clear Page">>;
627
+ };
628
+
629
+ declare const visualEditorReducer: _ngrx_store.ActionReducer<VisualEditorState, _ngrx_store.Action<string>>;
630
+
631
+ declare const selectVisualEditorState: _ngrx_store.MemoizedSelector<object, VisualEditorState, _ngrx_store.DefaultProjectorFn<VisualEditorState>>;
632
+ declare const selectSections: _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.EditorSection[], (s1: VisualEditorState) => _kustomizer_visual_editor.EditorSection[]>;
633
+ declare const selectSelectedElementId: _ngrx_store.MemoizedSelector<object, string | null, (s1: VisualEditorState) => string | null>;
634
+ declare const selectSelectedSectionId: _ngrx_store.MemoizedSelector<object, string | null, (s1: VisualEditorState) => string | null>;
635
+ declare const selectIsDragging: _ngrx_store.MemoizedSelector<object, boolean, (s1: VisualEditorState) => boolean>;
636
+ declare const selectDraggedElementId: _ngrx_store.MemoizedSelector<object, string | null, (s1: VisualEditorState) => string | null>;
637
+ declare const selectHistoryIndex: _ngrx_store.MemoizedSelector<object, number, (s1: VisualEditorState) => number>;
638
+ declare const selectHistoryLength: _ngrx_store.MemoizedSelector<object, number, (s1: VisualEditorState) => number>;
639
+ declare const selectCanUndo: _ngrx_store.MemoizedSelector<object, boolean, (s1: VisualEditorState) => boolean>;
640
+ declare const selectCanRedo: _ngrx_store.MemoizedSelector<object, boolean, (s1: VisualEditorState) => boolean>;
641
+ declare const selectSelectedSection: _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.EditorSection | null, (s1: _kustomizer_visual_editor.EditorSection[], s2: string | null) => _kustomizer_visual_editor.EditorSection | null>;
642
+ declare const selectSelectedElement: _ngrx_store.MemoizedSelector<object, EditorElement | null, (s1: _kustomizer_visual_editor.EditorSection | null, s2: string | null) => EditorElement | null>;
643
+ declare const selectSectionById: (sectionId: string) => _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.EditorSection | null, (s1: _kustomizer_visual_editor.EditorSection[]) => _kustomizer_visual_editor.EditorSection | null>;
644
+ declare const selectElementById: (sectionId: string, elementId: string) => _ngrx_store.MemoizedSelector<object, EditorElement | null, (s1: _kustomizer_visual_editor.EditorSection | null) => EditorElement | null>;
645
+ declare const selectHistory: _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.HistoryEntry[], (s1: VisualEditorState) => _kustomizer_visual_editor.HistoryEntry[]>;
646
+ declare const selectLastAction: _ngrx_store.MemoizedSelector<object, string | null, (s1: _kustomizer_visual_editor.HistoryEntry[], s2: number) => string | null>;
647
+ declare const selectSelectedElementType: _ngrx_store.MemoizedSelector<object, string | null, (s1: EditorElement | null) => string | null>;
648
+ declare const selectSelectedSectionType: _ngrx_store.MemoizedSelector<object, string | null, (s1: _kustomizer_visual_editor.EditorSection | null) => string | null>;
649
+ declare const selectBlocksForSection: (sectionId: string) => _ngrx_store.MemoizedSelector<object, EditorElement[], (s1: _kustomizer_visual_editor.EditorSection | null) => EditorElement[]>;
650
+ declare const selectBlocksForSlot: (sectionId: string, slotName: string) => _ngrx_store.MemoizedSelector<object, EditorElement[], (s1: EditorElement[]) => EditorElement[]>;
651
+ declare const selectSelectedBlock: _ngrx_store.MemoizedSelector<object, EditorElement | null, (s1: _kustomizer_visual_editor.EditorSection | null, s2: string | null) => EditorElement | null>;
652
+ declare const selectSelectedBlockSlotName: _ngrx_store.MemoizedSelector<object, string | null, (s1: EditorElement | null) => string | null>;
653
+ declare const selectCurrentPage: _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.PageContext | null, (s1: VisualEditorState) => _kustomizer_visual_editor.PageContext | null>;
654
+ declare const selectCurrentPageId: _ngrx_store.MemoizedSelector<object, string | null, (s1: _kustomizer_visual_editor.PageContext | null) => string | null>;
655
+ declare const selectCurrentPageSlug: _ngrx_store.MemoizedSelector<object, string | null, (s1: _kustomizer_visual_editor.PageContext | null) => string | null>;
656
+ declare const selectCurrentPageTitle: _ngrx_store.MemoizedSelector<object, string | null, (s1: _kustomizer_visual_editor.PageContext | null) => string | null>;
657
+ declare const selectCurrentPageStatus: _ngrx_store.MemoizedSelector<object, _kustomizer_visual_editor.PageStatus | null, (s1: _kustomizer_visual_editor.PageContext | null) => _kustomizer_visual_editor.PageStatus | null>;
658
+ declare const selectCurrentPageVersion: _ngrx_store.MemoizedSelector<object, number | null, (s1: _kustomizer_visual_editor.PageContext | null) => number | null>;
659
+ declare const selectIsDirty: _ngrx_store.MemoizedSelector<object, boolean, (s1: VisualEditorState) => boolean>;
660
+ declare const selectIsPageLoaded: _ngrx_store.MemoizedSelector<object, boolean, (s1: _kustomizer_visual_editor.PageContext | null) => boolean>;
661
+
662
+ declare function provideVisualEditorStore(): EnvironmentProviders;
663
+
664
+ /**
665
+ * Supported property types for the editor
666
+ */
667
+ type PropType = 'string' | 'number' | 'boolean' | 'color' | 'image' | 'video' | 'url' | 'richtext' | 'textarea' | 'select' | 'range' | 'json';
668
+ /**
669
+ * Option for select-type properties
670
+ */
671
+ interface SelectOption {
672
+ label: string;
673
+ value: string | number;
674
+ }
675
+ /**
676
+ * Validation rules for a property
677
+ */
678
+ interface PropValidation {
679
+ required?: boolean;
680
+ min?: number;
681
+ max?: number;
682
+ minLength?: number;
683
+ maxLength?: number;
684
+ pattern?: string;
685
+ }
686
+ /**
687
+ * Condition to show/hide a property based on another property's value
688
+ */
689
+ interface PropCondition {
690
+ dependsOn: string;
691
+ equals?: unknown;
692
+ oneOf?: unknown[];
693
+ }
694
+ /**
695
+ * Schema definition for a single property
696
+ */
697
+ interface PropSchema<T = unknown> {
698
+ type: PropType;
699
+ label: string;
700
+ description?: string;
701
+ defaultValue: T;
702
+ placeholder?: string;
703
+ validation?: PropValidation;
704
+ condition?: PropCondition;
705
+ group?: string;
706
+ order?: number;
707
+ options?: SelectOption[];
708
+ step?: number;
709
+ accept?: string[];
710
+ }
711
+ /**
712
+ * Map of property names to their schemas
713
+ */
714
+ type PropSchemaMap = Record<string, PropSchema>;
715
+
716
+ /**
717
+ * Constraints for what can be placed in a slot
718
+ */
719
+ interface SlotConstraints {
720
+ allowedTypes?: string[];
721
+ disallowedTypes?: string[];
722
+ minItems?: number;
723
+ maxItems?: number;
724
+ }
725
+ /**
726
+ * Definition of a slot where child components can be inserted
727
+ */
728
+ interface SlotDefinition {
729
+ name: string;
730
+ label: string;
731
+ description?: string;
732
+ constraints?: SlotConstraints;
733
+ emptyPlaceholder?: string;
734
+ droppable?: boolean;
735
+ }
736
+
737
+ /**
738
+ * Category for grouping components in the editor panel
739
+ */
740
+ type ComponentCategory = 'layout' | 'content' | 'media' | 'form' | 'navigation' | 'commerce' | 'custom';
741
+ /**
742
+ * Block configuration within a preset
743
+ */
744
+ interface PresetBlockConfig {
745
+ type: string;
746
+ settings?: Record<string, unknown>;
747
+ slotName?: string;
748
+ blocks?: PresetBlockConfig[];
749
+ }
750
+ /**
751
+ * Pre-configured variant of a component
752
+ */
753
+ interface ComponentPreset {
754
+ name: string;
755
+ category?: string;
756
+ description?: string;
757
+ icon?: string;
758
+ thumbnail?: string;
759
+ settings?: Record<string, unknown>;
760
+ blocks?: PresetBlockConfig[];
761
+ }
762
+ /**
763
+ * Complete definition of a registered editor component
764
+ */
765
+ interface ComponentDefinition<TProps extends Record<string, unknown> = Record<string, unknown>> {
766
+ /**
767
+ * Unique identifier matching EditorElement.type or EditorSection.type
768
+ */
769
+ type: string;
770
+ /**
771
+ * Display name in the component panel
772
+ */
773
+ name: string;
774
+ /**
775
+ * Description of the component
776
+ */
777
+ description?: string;
778
+ /**
779
+ * Category for grouping in the component panel
780
+ */
781
+ category: ComponentCategory;
782
+ /**
783
+ * Icon name or URL
784
+ */
785
+ icon?: string;
786
+ /**
787
+ * Angular component class to render
788
+ */
789
+ component: Type<unknown>;
790
+ /**
791
+ * Schema of editable properties
792
+ */
793
+ props: PropSchemaMap;
794
+ /**
795
+ * Available slots for child components
796
+ */
797
+ slots?: SlotDefinition[];
798
+ /**
799
+ * Whether this is a section (top-level container) vs element
800
+ */
801
+ isSection?: boolean;
802
+ /**
803
+ * Whether this is a block (element that lives inside section slots)
804
+ */
805
+ isBlock?: boolean;
806
+ /**
807
+ * Scope of the block: 'theme' = available in all sections, 'section' = only in specific sections
808
+ * Defaults to 'theme' if not specified
809
+ */
810
+ blockScope?: 'section' | 'theme';
811
+ /**
812
+ * Section types where this block is available (only used when blockScope is 'section')
813
+ */
814
+ sectionTypes?: string[];
815
+ /**
816
+ * Whether the component can be dragged/reordered
817
+ */
818
+ draggable?: boolean;
819
+ /**
820
+ * Whether the component can be deleted
821
+ */
822
+ deletable?: boolean;
823
+ /**
824
+ * Whether the component can be duplicated
825
+ */
826
+ duplicable?: boolean;
827
+ /**
828
+ * Thumbnail URL for the component panel
829
+ */
830
+ thumbnail?: string;
831
+ /**
832
+ * Tags for search
833
+ */
834
+ tags?: string[];
835
+ /**
836
+ * Order in the component list (lower = first)
837
+ */
838
+ order?: number;
839
+ /**
840
+ * Pre-configured presets for this component.
841
+ * Each preset appears as a separate entry in the picker.
842
+ */
843
+ presets?: ComponentPreset[];
844
+ }
845
+
846
+ /**
847
+ * A resolved preset entry for use in pickers.
848
+ * If the component has no presets, preset is null and display fields come from the definition.
849
+ */
850
+ interface ResolvedPreset {
851
+ definition: ComponentDefinition;
852
+ preset: ComponentPreset | null;
853
+ displayName: string;
854
+ displayCategory: string;
855
+ displayIcon: string | undefined;
856
+ displayDescription: string | undefined;
857
+ }
858
+ /**
859
+ * Central service for registering and querying editor components
860
+ */
861
+ declare class ComponentRegistryService {
862
+ private readonly definitions;
863
+ private readonly injectedDefinitions;
864
+ constructor();
865
+ /**
866
+ * Register a component definition
867
+ */
868
+ register(definition: ComponentDefinition): void;
869
+ /**
870
+ * Register multiple definitions
871
+ */
872
+ registerAll(definitions: ComponentDefinition[]): void;
873
+ /**
874
+ * Get a definition by type
875
+ */
876
+ get(type: string): ComponentDefinition | undefined;
877
+ /**
878
+ * Check if a type is registered
879
+ */
880
+ has(type: string): boolean;
881
+ /**
882
+ * Get the Angular component for a type
883
+ */
884
+ getComponent(type: string): Type<unknown> | undefined;
885
+ /**
886
+ * Get the props schema for a type
887
+ */
888
+ getPropsSchema(type: string): PropSchemaMap | undefined;
889
+ /**
890
+ * Get the slots for a type
891
+ */
892
+ getSlots(type: string): SlotDefinition[];
893
+ /**
894
+ * Check if a component type has slots (can contain nested blocks)
895
+ */
896
+ hasSlots(type: string): boolean;
897
+ /**
898
+ * Get all definitions
899
+ */
900
+ getAll(): ComponentDefinition[];
901
+ /**
902
+ * Get definitions filtered by category
903
+ */
904
+ getByCategory(category: ComponentCategory): ComponentDefinition[];
905
+ /**
906
+ * Get only section components
907
+ */
908
+ getSections(): ComponentDefinition[];
909
+ /**
910
+ * Get only element components (non-sections, non-blocks)
911
+ */
912
+ getElements(): ComponentDefinition[];
913
+ /**
914
+ * Get only block components (elements that live inside section slots)
915
+ */
916
+ getBlocks(): ComponentDefinition[];
917
+ /**
918
+ * Get blocks available for a specific section type
919
+ * Returns theme blocks (global) + section blocks specific to this section type
920
+ */
921
+ getBlocksForSectionType(sectionType: string): ComponentDefinition[];
922
+ /**
923
+ * Search components by name or tags
924
+ */
925
+ search(query: string): ComponentDefinition[];
926
+ /**
927
+ * Generate default props for a type
928
+ */
929
+ getDefaultProps(type: string): Record<string, unknown>;
930
+ /**
931
+ * Resolve a definition into ResolvedPreset entries.
932
+ * If it has presets, returns one entry per preset; otherwise one entry for the definition itself.
933
+ */
934
+ resolvePresets(definition: ComponentDefinition): ResolvedPreset[];
935
+ /**
936
+ * Get all section definitions expanded into presets
937
+ */
938
+ getSectionPresets(): ResolvedPreset[];
939
+ /**
940
+ * Get all block definitions expanded into presets
941
+ */
942
+ getBlockPresets(): ResolvedPreset[];
943
+ /**
944
+ * Get block presets available for a specific section type
945
+ */
946
+ getBlockPresetsForSectionType(sectionType: string): ResolvedPreset[];
947
+ /**
948
+ * Merge schema defaults with preset settings to produce final props
949
+ */
950
+ getPresetProps(type: string, preset: ComponentPreset | null): Record<string, unknown>;
951
+ /**
952
+ * Validate props against the schema
953
+ */
954
+ validateProps(type: string, props: Record<string, unknown>): Map<string, string>;
955
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ComponentRegistryService, never>;
956
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ComponentRegistryService>;
957
+ }
958
+
959
+ /**
960
+ * Injection token for editor component definitions
961
+ */
962
+ declare const EDITOR_COMPONENT_DEFINITIONS: InjectionToken<ComponentDefinition<Record<string, unknown>>[][]>;
963
+ /**
964
+ * Provider function to register editor components.
965
+ *
966
+ * @example
967
+ * ```typescript
968
+ * // app.config.ts
969
+ * export const appConfig: ApplicationConfig = {
970
+ * providers: [
971
+ * provideStore(),
972
+ * provideVisualEditorStore(),
973
+ * provideEditorComponents([
974
+ * heroSectionDefinition,
975
+ * textBlockDefinition,
976
+ * ]),
977
+ * ],
978
+ * };
979
+ * ```
980
+ */
981
+ declare function provideEditorComponents(definitions: ComponentDefinition[]): EnvironmentProviders;
982
+
983
+ /**
984
+ * Component that dynamically renders an EditorElement
985
+ * based on its type registered in the ComponentRegistry
986
+ */
987
+ declare class DynamicRendererComponent {
988
+ private readonly registry;
989
+ private readonly viewContainerRef;
990
+ private readonly destroyRef;
991
+ /** Element to render */
992
+ readonly element: _angular_core.InputSignal<EditorElement>;
993
+ /** Additional context (sectionId, index, etc.) */
994
+ readonly context: _angular_core.InputSignal<Record<string, unknown>>;
995
+ /** Error state signal */
996
+ private _error;
997
+ error: () => boolean;
998
+ private componentRef;
999
+ private currentType;
1000
+ private currentAvailableInputs;
1001
+ private previousInputs;
1002
+ constructor();
1003
+ private renderComponent;
1004
+ private updateInputs;
1005
+ private setInputIfChanged;
1006
+ private getComponentInputs;
1007
+ private cleanup;
1008
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicRendererComponent, never>;
1009
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicRendererComponent, "lib-dynamic-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1010
+ }
1011
+
1012
+ /**
1013
+ * Renders child elements within a specific slot
1014
+ */
1015
+ declare class SlotRendererComponent {
1016
+ private readonly registry;
1017
+ /** Slot definition */
1018
+ readonly slot: _angular_core.InputSignal<SlotDefinition>;
1019
+ /** All children of the parent element */
1020
+ readonly children: _angular_core.InputSignal<EditorElement[]>;
1021
+ /** Parent element ID */
1022
+ readonly parentElementId: _angular_core.InputSignal<string>;
1023
+ /** Children filtered by slot name and constraints */
1024
+ readonly filteredChildren: _angular_core.Signal<EditorElement[]>;
1025
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SlotRendererComponent, never>;
1026
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlotRendererComponent, "lib-slot-renderer", never, { "slot": { "alias": "slot"; "required": true; "isSignal": true; }; "children": { "alias": "children"; "required": true; "isSignal": true; }; "parentElementId": { "alias": "parentElementId"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1027
+ }
1028
+
1029
+ /**
1030
+ * Facade service that combines Store operations with ComponentRegistry
1031
+ */
1032
+ declare class VisualEditorFacade {
1033
+ private readonly store;
1034
+ private readonly registry;
1035
+ private readonly pageService;
1036
+ readonly sections: _angular_core.Signal<EditorSection[]>;
1037
+ readonly selectedElement: _angular_core.Signal<EditorElement | null>;
1038
+ readonly selectedSection: _angular_core.Signal<EditorSection | null>;
1039
+ readonly canUndo: _angular_core.Signal<boolean>;
1040
+ readonly canRedo: _angular_core.Signal<boolean>;
1041
+ readonly isDragging: _angular_core.Signal<boolean>;
1042
+ readonly selectedBlock: _angular_core.Signal<EditorElement | null>;
1043
+ readonly selectedBlockSlotName: _angular_core.Signal<string | null>;
1044
+ readonly currentPage: _angular_core.Signal<PageContext | null>;
1045
+ readonly currentPageId: _angular_core.Signal<string | null>;
1046
+ readonly isDirty: _angular_core.Signal<boolean>;
1047
+ readonly isPageLoaded: _angular_core.Signal<boolean>;
1048
+ readonly selectedElementDefinition: _angular_core.Signal<ComponentDefinition<Record<string, unknown>> | null>;
1049
+ readonly selectedSectionDefinition: _angular_core.Signal<ComponentDefinition<Record<string, unknown>> | null>;
1050
+ readonly selectedBlockDefinition: _angular_core.Signal<ComponentDefinition<Record<string, unknown>> | null>;
1051
+ readonly availableSections: _angular_core.Signal<ComponentDefinition<Record<string, unknown>>[]>;
1052
+ readonly availableElements: _angular_core.Signal<ComponentDefinition<Record<string, unknown>>[]>;
1053
+ readonly availableBlocks: _angular_core.Signal<ComponentDefinition<Record<string, unknown>>[]>;
1054
+ readonly availableSectionPresets: _angular_core.Signal<ResolvedPreset[]>;
1055
+ readonly availableBlockPresets: _angular_core.Signal<ResolvedPreset[]>;
1056
+ /**
1057
+ * Create a new element with default props from registry
1058
+ */
1059
+ createElementWithDefaults(type: string, overrides?: Partial<EditorElement>): EditorElement;
1060
+ /**
1061
+ * Create a new section with default props from registry
1062
+ */
1063
+ createSectionWithDefaults(type: string, overrides?: Partial<EditorSection>): EditorSection;
1064
+ /**
1065
+ * Add a section to the editor
1066
+ */
1067
+ addSection(type: string, index?: number): void;
1068
+ /**
1069
+ * Add an element to a section
1070
+ */
1071
+ addElement(sectionId: string, type: string, index?: number): void;
1072
+ /**
1073
+ * Remove a section
1074
+ */
1075
+ removeSection(sectionId: string): void;
1076
+ /**
1077
+ * Remove an element
1078
+ */
1079
+ removeElement(sectionId: string, elementId: string): void;
1080
+ /**
1081
+ * Move a section to a new index
1082
+ */
1083
+ moveSection(sectionId: string, newIndex: number): void;
1084
+ /**
1085
+ * Move an element within or between sections
1086
+ */
1087
+ moveElement(sourceSectionId: string, targetSectionId: string, elementId: string, newIndex: number): void;
1088
+ /**
1089
+ * Rename a section (set adminLabel)
1090
+ */
1091
+ renameSection(sectionId: string, adminLabel: string): void;
1092
+ /**
1093
+ * Rename a block (set adminLabel)
1094
+ */
1095
+ renameBlock(sectionId: string, elementId: string, adminLabel: string): void;
1096
+ /**
1097
+ * Create a block element with default props and slotName
1098
+ */
1099
+ createBlockWithDefaults(type: string, slotName: string, overrides?: Partial<EditorElement>): EditorElement;
1100
+ /**
1101
+ * Add a block to a section's slot
1102
+ */
1103
+ addBlock(sectionId: string, slotName: string, type: string, index?: number): void;
1104
+ /**
1105
+ * Add a section from a resolved preset.
1106
+ * Merges preset settings into default props and creates pre-configured blocks.
1107
+ */
1108
+ addSectionFromPreset(resolvedPreset: ResolvedPreset, index?: number): void;
1109
+ /**
1110
+ * Add a block from a resolved preset to a section's slot.
1111
+ */
1112
+ addBlockFromPreset(sectionId: string, slotName: string, resolvedPreset: ResolvedPreset, index?: number): void;
1113
+ /**
1114
+ * Generate EditorElement[] from a preset's blocks configuration
1115
+ */
1116
+ private createPresetBlocks;
1117
+ /**
1118
+ * Generate children for blocks that have slots, from preset block configs
1119
+ */
1120
+ private createPresetBlockChildren;
1121
+ /**
1122
+ * Remove a block from a section
1123
+ */
1124
+ removeBlock(sectionId: string, elementId: string): void;
1125
+ /**
1126
+ * Move a block within a section (can change slots)
1127
+ */
1128
+ moveBlock(sectionId: string, elementId: string, targetSlotName: string, newIndex: number): void;
1129
+ /**
1130
+ * Check if a section type can be duplicated
1131
+ */
1132
+ isSectionDuplicable(type: string): boolean;
1133
+ /**
1134
+ * Check if a block type can be duplicated
1135
+ */
1136
+ isBlockDuplicable(type: string): boolean;
1137
+ /**
1138
+ * Duplicate a section (deep clone with new IDs)
1139
+ */
1140
+ duplicateSection(sectionId: string): void;
1141
+ /**
1142
+ * Duplicate a block within a section
1143
+ */
1144
+ duplicateBlock(sectionId: string, elementId: string): void;
1145
+ /**
1146
+ * Duplicate a nested block
1147
+ */
1148
+ duplicateNestedBlock(sectionId: string, parentPath: string[], elementId: string): void;
1149
+ /**
1150
+ * Update block props with validation (works for both direct and nested blocks)
1151
+ */
1152
+ updateBlockProps(sectionId: string, elementId: string, props: Record<string, unknown>): void;
1153
+ /**
1154
+ * Get blocks for a specific slot in a section
1155
+ */
1156
+ getBlocksForSlot(sectionId: string, slotName: string): EditorElement[];
1157
+ /**
1158
+ * Get allowed block types for a slot
1159
+ */
1160
+ getAllowedBlocksForSlot(sectionType: string, slotName: string): ComponentDefinition[];
1161
+ /**
1162
+ * Check if a component type has slots (can contain nested blocks)
1163
+ */
1164
+ hasSlots(type: string): boolean;
1165
+ /**
1166
+ * Get slots for a block type
1167
+ */
1168
+ getBlockSlots(type: string): SlotDefinition[];
1169
+ /**
1170
+ * Check if adding a nested block is allowed (max 12 levels)
1171
+ */
1172
+ canAddNestedBlock(parentPath: string[]): boolean;
1173
+ /**
1174
+ * Add a nested block to a parent element
1175
+ */
1176
+ addNestedBlock(sectionId: string, parentPath: string[], slotName: string, type: string, index?: number): void;
1177
+ /**
1178
+ * Remove a nested block from a parent element
1179
+ */
1180
+ removeNestedBlock(sectionId: string, parentPath: string[], elementId: string): void;
1181
+ /**
1182
+ * Update nested block props
1183
+ */
1184
+ updateNestedBlockProps(sectionId: string, parentPath: string[], elementId: string, props: Record<string, unknown>): void;
1185
+ /**
1186
+ * Move a nested block within its parent
1187
+ */
1188
+ moveNestedBlock(sectionId: string, parentPath: string[], elementId: string, targetSlotName: string, newIndex: number): void;
1189
+ /**
1190
+ * Reparent a block: move it from one parent/section to another
1191
+ */
1192
+ reparentBlock(sourceSectionId: string, sourceParentPath: string[], elementId: string, targetSectionId: string, targetParentPath: string[], targetSlotName: string, targetIndex: number): void;
1193
+ /**
1194
+ * Get children of an element filtered by slot
1195
+ */
1196
+ getElementChildren(element: EditorElement, slotName?: string): EditorElement[];
1197
+ /**
1198
+ * Get allowed blocks for a nested slot
1199
+ */
1200
+ getAllowedBlocksForNestedSlot(parentType: string, slotName: string): ComponentDefinition[];
1201
+ /**
1202
+ * Select an element
1203
+ */
1204
+ selectElement(sectionId: string | null, elementId: string | null): void;
1205
+ /**
1206
+ * Clear selection
1207
+ */
1208
+ clearSelection(): void;
1209
+ /**
1210
+ * Update element props with validation
1211
+ */
1212
+ updateElementProps(sectionId: string, elementId: string, props: Record<string, unknown>): void;
1213
+ /**
1214
+ * Update section props with validation
1215
+ */
1216
+ updateSectionProps(sectionId: string, props: Record<string, unknown>): void;
1217
+ /**
1218
+ * Undo last action
1219
+ */
1220
+ undo(): void;
1221
+ /**
1222
+ * Redo last undone action
1223
+ */
1224
+ redo(): void;
1225
+ /**
1226
+ * Load sections into the editor
1227
+ */
1228
+ loadSections(sections: EditorSection[]): void;
1229
+ /**
1230
+ * Reset editor to initial state
1231
+ */
1232
+ resetEditor(): void;
1233
+ /**
1234
+ * Get component definition by type
1235
+ */
1236
+ getDefinition(type: string): ComponentDefinition | undefined;
1237
+ /**
1238
+ * Search components
1239
+ */
1240
+ searchComponents(query: string): ComponentDefinition[];
1241
+ /**
1242
+ * Get all pages (summaries)
1243
+ */
1244
+ getPages(): Observable<PageSummary[]>;
1245
+ /**
1246
+ * Get a page by ID and load it into the editor
1247
+ */
1248
+ getPage(id: string): Observable<Page>;
1249
+ /**
1250
+ * Get a published page by slug (for public rendering)
1251
+ */
1252
+ getPublishedPageBySlug(slug: string): Observable<Page>;
1253
+ /**
1254
+ * Load a page into the editor
1255
+ */
1256
+ loadPage(page: Page): void;
1257
+ /**
1258
+ * Create a new page
1259
+ */
1260
+ createPage(request: CreatePageRequest): Observable<Page>;
1261
+ /**
1262
+ * Save current editor state to a page
1263
+ */
1264
+ savePage(pageId: string): Observable<Page>;
1265
+ /**
1266
+ * Update page metadata (title, slug, etc.)
1267
+ */
1268
+ updatePageMetadata(pageId: string, metadata: Partial<PageContext>): Observable<Page>;
1269
+ /**
1270
+ * Delete a page
1271
+ */
1272
+ deletePage(id: string): Observable<void>;
1273
+ /**
1274
+ * Publish a page
1275
+ */
1276
+ publishPage(pageId: string): Observable<Page>;
1277
+ /**
1278
+ * Unpublish a page
1279
+ */
1280
+ unpublishPage(pageId: string): Observable<Page>;
1281
+ /**
1282
+ * Duplicate a page
1283
+ */
1284
+ duplicatePage(id: string): Observable<Page>;
1285
+ /**
1286
+ * Clear the current page from editor
1287
+ */
1288
+ clearPage(): void;
1289
+ /**
1290
+ * Mark editor as dirty (has unsaved changes)
1291
+ */
1292
+ markDirty(): void;
1293
+ /**
1294
+ * Mark editor as clean (no unsaved changes)
1295
+ */
1296
+ markClean(): void;
1297
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<VisualEditorFacade, never>;
1298
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<VisualEditorFacade>;
1299
+ }
1300
+
1301
+ type DropZone = 'before' | 'inside' | 'after';
1302
+ type DragItemKind = 'section' | 'block';
1303
+ interface DragItem {
1304
+ kind: DragItemKind;
1305
+ elementId: string;
1306
+ elementType: string;
1307
+ sectionId: string;
1308
+ parentPath: string[];
1309
+ slotName?: string;
1310
+ sourceIndex: number;
1311
+ }
1312
+ interface DropTarget {
1313
+ kind: DragItemKind;
1314
+ sectionId: string;
1315
+ parentPath: string[];
1316
+ slotName: string;
1317
+ index: number;
1318
+ depth: number;
1319
+ zone: DropZone;
1320
+ }
1321
+
1322
+ /**
1323
+ * Context for a block in the tree hierarchy
1324
+ */
1325
+ interface BlockTreeContext {
1326
+ sectionId: string;
1327
+ parentPath: string[];
1328
+ depth: number;
1329
+ }
1330
+ /**
1331
+ * Target information for opening the block picker
1332
+ */
1333
+ interface BlockPickerTarget {
1334
+ sectionId: string;
1335
+ parentPath: string[];
1336
+ parentType: string;
1337
+ slots: SlotDefinition[];
1338
+ }
1339
+ /**
1340
+ * Recursive component for rendering a block in the sidebar tree
1341
+ * Supports nested blocks with expand/collapse functionality
1342
+ */
1343
+ declare class BlockTreeItemComponent {
1344
+ readonly facade: VisualEditorFacade;
1345
+ private readonly dndService;
1346
+ private readonly sanitizer;
1347
+ private readonly treeBlock;
1348
+ readonly block: _angular_core.InputSignal<EditorElement>;
1349
+ readonly context: _angular_core.InputSignal<BlockTreeContext>;
1350
+ readonly index: _angular_core.InputSignal<number>;
1351
+ readonly totalSiblings: _angular_core.InputSignal<number>;
1352
+ readonly expandAll: _angular_core.InputSignal<boolean>;
1353
+ readonly selectBlock: _angular_core.OutputEmitterRef<{
1354
+ block: EditorElement;
1355
+ context: BlockTreeContext;
1356
+ }>;
1357
+ readonly deleteBlock: _angular_core.OutputEmitterRef<{
1358
+ block: EditorElement;
1359
+ context: BlockTreeContext;
1360
+ }>;
1361
+ readonly duplicateBlock: _angular_core.OutputEmitterRef<{
1362
+ block: EditorElement;
1363
+ context: BlockTreeContext;
1364
+ }>;
1365
+ readonly moveBlock: _angular_core.OutputEmitterRef<{
1366
+ block: EditorElement;
1367
+ context: BlockTreeContext;
1368
+ newIndex: number;
1369
+ }>;
1370
+ readonly openBlockPicker: _angular_core.OutputEmitterRef<BlockPickerTarget>;
1371
+ private readonly expanded;
1372
+ readonly dropZone: _angular_core.WritableSignal<DropZone | null>;
1373
+ readonly isDragSource: _angular_core.Signal<boolean>;
1374
+ readonly blockHasSlots: _angular_core.Signal<boolean>;
1375
+ readonly blockSlots: _angular_core.Signal<SlotDefinition[]>;
1376
+ readonly children: _angular_core.Signal<EditorElement[]>;
1377
+ readonly childContext: _angular_core.Signal<BlockTreeContext>;
1378
+ readonly blockIcon: _angular_core.Signal<SafeHtml>;
1379
+ readonly blockName: _angular_core.Signal<string>;
1380
+ readonly duplicable: _angular_core.Signal<boolean>;
1381
+ readonly canAddMore: _angular_core.Signal<boolean>;
1382
+ isExpanded(): boolean;
1383
+ toggleExpand(event: Event): void;
1384
+ hasSlots(): boolean;
1385
+ getBlockSlots(): SlotDefinition[];
1386
+ onDuplicate(event: Event): void;
1387
+ onSelect(event: Event): void;
1388
+ onDelete(event: Event): void;
1389
+ onMoveUp(event: Event): void;
1390
+ onMoveDown(event: Event): void;
1391
+ onAddBlock(event: Event): void;
1392
+ onDragStart(event: DragEvent): void;
1393
+ onDragEnd(event: DragEvent): void;
1394
+ onDragOver(event: DragEvent): void;
1395
+ onDragLeave(event: DragEvent): void;
1396
+ onDrop(event: DragEvent): void;
1397
+ onDragHandleKeydown(event: KeyboardEvent): void;
1398
+ private buildDropTarget;
1399
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BlockTreeItemComponent, never>;
1400
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BlockTreeItemComponent, "lib-block-tree-item", never, { "block": { "alias": "block"; "required": true; "isSignal": true; }; "context": { "alias": "context"; "required": true; "isSignal": true; }; "index": { "alias": "index"; "required": true; "isSignal": true; }; "totalSiblings": { "alias": "totalSiblings"; "required": true; "isSignal": true; }; "expandAll": { "alias": "expandAll"; "required": false; "isSignal": true; }; }, { "selectBlock": "selectBlock"; "deleteBlock": "deleteBlock"; "duplicateBlock": "duplicateBlock"; "moveBlock": "moveBlock"; "openBlockPicker": "openBlockPicker"; }, never, never, true, never>;
1401
+ }
1402
+
1403
+ /**
1404
+ * Main Visual Editor component
1405
+ * Provides a complete editing interface with:
1406
+ * - Sidebar with hierarchical tree view
1407
+ * - Canvas with live preview
1408
+ * - Properties panel for editing section/block properties
1409
+ */
1410
+ declare class VisualEditorComponent implements OnInit, OnDestroy {
1411
+ readonly facade: VisualEditorFacade;
1412
+ private readonly registry;
1413
+ private readonly navigation;
1414
+ private readonly loadingStrategy;
1415
+ private readonly config;
1416
+ private readonly dndService;
1417
+ private readonly sanitizer;
1418
+ private readonly destroy$;
1419
+ readonly showBackButton: _angular_core.Signal<boolean>;
1420
+ readonly showPublishButtons: _angular_core.Signal<boolean>;
1421
+ readonly showSaveButton: _angular_core.Signal<boolean>;
1422
+ readonly isPreviewMode: _angular_core.WritableSignal<boolean>;
1423
+ readonly editorContext: _angular_core.Signal<{
1424
+ isEditor: boolean;
1425
+ }>;
1426
+ private readonly canvasEl;
1427
+ readonly propertiesTab: _angular_core.WritableSignal<"props" | "blocks">;
1428
+ readonly expandedGroups: _angular_core.WritableSignal<Set<string>>;
1429
+ readonly expandedSections: _angular_core.WritableSignal<Set<string>>;
1430
+ readonly allBlocksExpanded: _angular_core.WritableSignal<Set<string>>;
1431
+ readonly showSectionPicker: _angular_core.WritableSignal<boolean>;
1432
+ readonly blockPickerSection: _angular_core.WritableSignal<EditorSection | null>;
1433
+ readonly nestedBlockPickerTarget: _angular_core.WritableSignal<BlockPickerTarget | null>;
1434
+ readonly filePickerOpen: _angular_core.WritableSignal<boolean>;
1435
+ readonly filePickerMediaType: _angular_core.WritableSignal<"IMAGE" | "VIDEO">;
1436
+ readonly filePickerTargetKey: _angular_core.WritableSignal<string>;
1437
+ readonly filePickerContext: _angular_core.WritableSignal<"section" | "block">;
1438
+ readonly filePickerCurrentValue: _angular_core.Signal<string>;
1439
+ readonly isSaving: _angular_core.WritableSignal<boolean>;
1440
+ readonly isPublishing: _angular_core.WritableSignal<boolean>;
1441
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1442
+ readonly searchQuery: _angular_core.WritableSignal<string>;
1443
+ readonly sectionPickerSearch: _angular_core.WritableSignal<string>;
1444
+ readonly blockPickerSearch: _angular_core.WritableSignal<string>;
1445
+ readonly nestedBlockPickerSearch: _angular_core.WritableSignal<string>;
1446
+ readonly sectionDropZone: _angular_core.WritableSignal<string | null>;
1447
+ readonly dndAnnouncement: _angular_core.WritableSignal<string>;
1448
+ private sectionAutoExpandTimer;
1449
+ readonly filteredSections: _angular_core.Signal<EditorSection[]>;
1450
+ readonly filteredAvailableSectionPresets: _angular_core.Signal<ResolvedPreset[]>;
1451
+ readonly groupedSectionPresets: _angular_core.Signal<{
1452
+ category: string;
1453
+ presets: ResolvedPreset[];
1454
+ }[]>;
1455
+ readonly filteredBlockPresetsForSection: _angular_core.Signal<ResolvedPreset[]>;
1456
+ readonly filteredBlockPresetsForNestedSlot: _angular_core.Signal<ResolvedPreset[]>;
1457
+ private readonly sectionIconMap;
1458
+ private readonly blockIconMap;
1459
+ readonly selectedBlockDefinition: _angular_core.Signal<ComponentDefinition<Record<string, unknown>> | null>;
1460
+ private readonly nameInput;
1461
+ readonly isEditingName: _angular_core.WritableSignal<boolean>;
1462
+ readonly editingNameValue: _angular_core.WritableSignal<string>;
1463
+ getSelectedDisplayName(def: ComponentDefinition): string;
1464
+ getSelectedDefaultName(def: ComponentDefinition): string;
1465
+ startEditingName(): void;
1466
+ saveEditingName(event: Event): void;
1467
+ cancelEditingName(): void;
1468
+ ngOnInit(): void;
1469
+ ngOnDestroy(): void;
1470
+ goBack(): void;
1471
+ savePage(): void;
1472
+ publishPage(): void;
1473
+ unpublishPage(): void;
1474
+ private readonly defaultSectionIcon;
1475
+ private readonly defaultBlockIcon;
1476
+ private toSafeIcon;
1477
+ getIcon(def: ComponentDefinition): SafeHtml;
1478
+ getBlockIcon(def: ComponentDefinition): SafeHtml;
1479
+ getBlockIconByType(type: string): SafeHtml;
1480
+ getSectionIcon(type: string): SafeHtml;
1481
+ isSectionExpanded(sectionId: string): boolean;
1482
+ isAllBlocksExpanded(sectionId: string): boolean;
1483
+ toggleSectionExpand(sectionId: string, event: Event): void;
1484
+ toggleGroup(entityId: string, group: string): void;
1485
+ isGroupCollapsed(entityId: string, group: string): boolean;
1486
+ getSectionBlocks(section: EditorSection): EditorElement[];
1487
+ private readonly rootBlockContextCache;
1488
+ private readonly emptyPath;
1489
+ getRootBlockContext(sectionId: string): BlockTreeContext;
1490
+ onSearchInput(event: Event): void;
1491
+ clearSearch(): void;
1492
+ isSectionDragSource(sectionId: string): boolean;
1493
+ onSectionDragStart(section: EditorSection, index: number, event: DragEvent): void;
1494
+ onSectionDragEnd(event: DragEvent): void;
1495
+ onSectionDragOver(section: EditorSection, index: number, event: DragEvent): void;
1496
+ onSectionDragLeave(event: DragEvent): void;
1497
+ onSectionDrop(event: DragEvent): void;
1498
+ onSectionDragHandleKeydown(sectionId: string, index: number, event: KeyboardEvent): void;
1499
+ onSectionContentDragOver(section: EditorSection, event: DragEvent): void;
1500
+ onSectionContentDragLeave(event: DragEvent): void;
1501
+ onSectionContentDrop(event: DragEvent): void;
1502
+ private startAutoExpandTimer;
1503
+ private clearAutoExpandTimer;
1504
+ private scrollToCanvasElement;
1505
+ /** Return the element itself if it has a box, otherwise its first laid-out child. */
1506
+ private resolveScrollTarget;
1507
+ private scrollToCanvasSection;
1508
+ onSectionPickerSearch(event: Event): void;
1509
+ onBlockPickerSearch(event: Event): void;
1510
+ toggleSectionPicker(): void;
1511
+ openBlockPicker(section: EditorSection, event: Event): void;
1512
+ closeBlockPicker(): void;
1513
+ onOpenNestedBlockPicker(target: BlockPickerTarget): void;
1514
+ closeNestedBlockPicker(): void;
1515
+ onNestedBlockPickerSearch(event: Event): void;
1516
+ addNestedBlock(blockType: string): void;
1517
+ onBlockSelect(event: {
1518
+ block: EditorElement;
1519
+ context: BlockTreeContext;
1520
+ }): void;
1521
+ onBlockDelete(event: {
1522
+ block: EditorElement;
1523
+ context: BlockTreeContext;
1524
+ }): void;
1525
+ onBlockMove(event: {
1526
+ block: EditorElement;
1527
+ context: BlockTreeContext;
1528
+ newIndex: number;
1529
+ }): void;
1530
+ onBlockDuplicate(event: {
1531
+ block: EditorElement;
1532
+ context: BlockTreeContext;
1533
+ }): void;
1534
+ duplicateSection(sectionId: string, event: Event): void;
1535
+ duplicateBlock(block: EditorElement, event: Event): void;
1536
+ addBlockToSection(section: EditorSection, blockType: string): void;
1537
+ getSectionName(section: EditorSection): string;
1538
+ getBlockName(block: EditorElement): string;
1539
+ addSection(type: string): void;
1540
+ addSectionFromPreset(rp: ResolvedPreset): void;
1541
+ addBlockToSectionFromPreset(section: EditorSection, rp: ResolvedPreset): void;
1542
+ addNestedBlockFromPreset(rp: ResolvedPreset): void;
1543
+ getSectionPresetIcon(rp: ResolvedPreset): SafeHtml;
1544
+ getBlockPresetIcon(rp: ResolvedPreset): SafeHtml;
1545
+ selectSection(section: EditorSection, event: Event): void;
1546
+ selectBlock(block: EditorElement): void;
1547
+ deleteSection(sectionId: string, event: Event): void;
1548
+ deleteBlock(block: EditorElement, event: Event): void;
1549
+ deleteSelectedBlock(): void;
1550
+ moveUp(sectionId: string, currentIndex: number, event: Event): void;
1551
+ moveDown(sectionId: string, currentIndex: number, event: Event): void;
1552
+ moveBlockUp(block: EditorElement, slotName: string, currentIndex: number, event: Event): void;
1553
+ moveBlockDown(block: EditorElement, slotName: string, currentIndex: number, event: Event): void;
1554
+ togglePreview(): void;
1555
+ getSectionSlots(): SlotDefinition[];
1556
+ getBlocksForSlot(slotName: string): EditorElement[];
1557
+ getBlockCount(): number;
1558
+ getPropertyGroups(def: ComponentDefinition): string[];
1559
+ getPropsForGroup(def: ComponentDefinition, group: string): Array<{
1560
+ key: string;
1561
+ schema: (typeof def.props)[string];
1562
+ }>;
1563
+ getPropertyValue(key: string): string;
1564
+ updateProperty(key: string, event: Event): void;
1565
+ getBlockPropertyGroups(): string[];
1566
+ getBlockPropsForGroup(group: string): Array<{
1567
+ key: string;
1568
+ schema: ComponentDefinition['props'][string];
1569
+ }>;
1570
+ getBlockPropertyValue(key: string): string;
1571
+ updateBlockProperty(key: string, event: Event): void;
1572
+ updateBlockBooleanProperty(key: string, event: Event): void;
1573
+ openFilePicker(mediaType: 'IMAGE' | 'VIDEO', key: string, context: 'block' | 'section'): void;
1574
+ closeFilePicker(): void;
1575
+ onFileSelected(url: string): void;
1576
+ clearBlockProperty(key: string): void;
1577
+ clearSectionProperty(key: string): void;
1578
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<VisualEditorComponent, never>;
1579
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<VisualEditorComponent, "lib-visual-editor", never, {}, {}, never, never, true, never>;
1580
+ }
1581
+
1582
+ interface ShopifyFile {
1583
+ id: string;
1584
+ alt: string;
1585
+ url: string;
1586
+ filename: string;
1587
+ mediaType: 'IMAGE' | 'VIDEO';
1588
+ mimeType: string;
1589
+ width?: number;
1590
+ height?: number;
1591
+ createdAt: string;
1592
+ }
1593
+ interface ShopifyFilesPage {
1594
+ files: ShopifyFile[];
1595
+ pageInfo: {
1596
+ hasNextPage: boolean;
1597
+ endCursor: string | null;
1598
+ };
1599
+ }
1600
+ declare const FILES_QUERY = "\n query GetFiles($first: Int!, $after: String, $query: String) {\n files(first: $first, after: $after, query: $query) {\n edges {\n node {\n ... on MediaImage {\n id\n alt\n createdAt\n mimeType\n image {\n url\n width\n height\n }\n originalSource {\n fileSize\n }\n }\n ... on Video {\n id\n alt\n createdAt\n filename\n originalSource {\n mimeType\n url\n }\n sources {\n url\n mimeType\n width\n height\n }\n }\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n";
1601
+ declare class ShopifyFilesService {
1602
+ private readonly client;
1603
+ getFiles(mediaType: 'IMAGE' | 'VIDEO', search?: string, first?: number, after?: string): Observable<ShopifyFilesPage>;
1604
+ private mapNode;
1605
+ private extractFilename;
1606
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopifyFilesService, never>;
1607
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopifyFilesService>;
1608
+ }
1609
+
1610
+ declare class ShopifyFilePickerComponent implements OnInit, OnDestroy {
1611
+ readonly mediaType: _angular_core.InputSignal<"IMAGE" | "VIDEO">;
1612
+ readonly currentValue: _angular_core.InputSignal<string>;
1613
+ readonly fileSelected: _angular_core.OutputEmitterRef<string>;
1614
+ readonly closed: _angular_core.OutputEmitterRef<void>;
1615
+ private readonly filesService;
1616
+ private readonly destroy$;
1617
+ private readonly searchSubject;
1618
+ private readonly searchInput;
1619
+ private readonly scrollContainer;
1620
+ readonly files: _angular_core.WritableSignal<ShopifyFile[]>;
1621
+ readonly selectedFile: _angular_core.WritableSignal<ShopifyFile | null>;
1622
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1623
+ readonly error: _angular_core.WritableSignal<string | null>;
1624
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1625
+ private endCursor;
1626
+ private hasNextPage;
1627
+ ngOnInit(): void;
1628
+ ngOnDestroy(): void;
1629
+ loadFiles(): void;
1630
+ onSearchInput(event: Event): void;
1631
+ onScroll(): void;
1632
+ selectFile(file: ShopifyFile): void;
1633
+ selectAndConfirm(file: ShopifyFile): void;
1634
+ confirmSelection(): void;
1635
+ close(): void;
1636
+ onBackdropClick(event: Event): void;
1637
+ getThumbnailUrl(url: string): string;
1638
+ private loadMore;
1639
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopifyFilePickerComponent, never>;
1640
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ShopifyFilePickerComponent, "lib-shopify-file-picker", never, { "mediaType": { "alias": "mediaType"; "required": true; "isSignal": true; }; "currentValue": { "alias": "currentValue"; "required": false; "isSignal": true; }; }, { "fileSelected": "fileSelected"; "closed": "closed"; }, never, never, true, never>;
1641
+ }
1642
+
1643
+ /**
1644
+ * Page manager component for listing, creating, and managing pages
1645
+ */
1646
+ declare class PageManagerComponent implements OnInit {
1647
+ private readonly facade;
1648
+ private readonly navigation;
1649
+ readonly pages: _angular_core.WritableSignal<PageSummary[]>;
1650
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1651
+ readonly error: _angular_core.WritableSignal<string | null>;
1652
+ readonly showCreateDialog: _angular_core.WritableSignal<boolean>;
1653
+ readonly newPageTitle: _angular_core.WritableSignal<string>;
1654
+ readonly newPageSlug: _angular_core.WritableSignal<string>;
1655
+ readonly isCreating: _angular_core.WritableSignal<boolean>;
1656
+ readonly createError: _angular_core.WritableSignal<string | null>;
1657
+ readonly pageToDelete: _angular_core.WritableSignal<PageSummary | null>;
1658
+ readonly isDeleting: _angular_core.WritableSignal<boolean>;
1659
+ ngOnInit(): void;
1660
+ loadPages(): void;
1661
+ openCreateDialog(): void;
1662
+ closeCreateDialog(): void;
1663
+ onTitleInput(event: Event): void;
1664
+ onSlugInput(event: Event): void;
1665
+ createPage(event: Event): void;
1666
+ editPage(pageId: string): void;
1667
+ duplicatePage(pageId: string, event: Event): void;
1668
+ confirmDelete(page: PageSummary, event: Event): void;
1669
+ cancelDelete(): void;
1670
+ deletePage(): void;
1671
+ formatDate(dateString: string): string;
1672
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PageManagerComponent, never>;
1673
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PageManagerComponent, "lib-page-manager", never, {}, {}, never, never, true, never>;
1674
+ }
1675
+
1676
+ /**
1677
+ * Token para inyectar el dominio de la tienda.
1678
+ * Debe ser configurado por la aplicación que instala el editor.
1679
+ *
1680
+ * Ejemplo de uso:
1681
+ * ```typescript
1682
+ * providers: [
1683
+ * { provide: STORE_DOMAIN, useValue: 'nike.com' }
1684
+ * ]
1685
+ * ```
1686
+ *
1687
+ * Si no se provee, el servicio intentará detectar el dominio desde window.location.hostname
1688
+ */
1689
+ declare const STORE_DOMAIN: InjectionToken<string>;
1690
+ interface Shop {
1691
+ id: string;
1692
+ name: string;
1693
+ shopify_domain: string;
1694
+ }
1695
+ interface ShopUser {
1696
+ email: string;
1697
+ role: 'owner' | 'admin' | 'reader';
1698
+ }
1699
+ interface ShopLicense {
1700
+ tier: 'starter' | 'growth' | 'enterprise';
1701
+ expires_at: string | null;
1702
+ active: boolean;
1703
+ }
1704
+ interface ShopAuthData {
1705
+ shop: Shop | null;
1706
+ user: ShopUser | null;
1707
+ license: ShopLicense | null;
1708
+ }
1709
+ interface ShopAuthError {
1710
+ code: string;
1711
+ message: string;
1712
+ }
1713
+ declare class ShopAuthService {
1714
+ private http;
1715
+ private config;
1716
+ private authService;
1717
+ private storeDomainConfig;
1718
+ private _shop;
1719
+ private _user;
1720
+ private _license;
1721
+ private _loading;
1722
+ private _error;
1723
+ private _initialized;
1724
+ readonly shop: _angular_core.Signal<Shop | null>;
1725
+ readonly user: _angular_core.Signal<ShopUser | null>;
1726
+ readonly license: _angular_core.Signal<ShopLicense | null>;
1727
+ readonly loading: _angular_core.Signal<boolean>;
1728
+ readonly error: _angular_core.Signal<ShopAuthError | null>;
1729
+ readonly initialized: _angular_core.Signal<boolean>;
1730
+ readonly shopId: _angular_core.Signal<string | null>;
1731
+ readonly shopName: _angular_core.Signal<string | null>;
1732
+ readonly shopifyDomain: _angular_core.Signal<string | null>;
1733
+ readonly userEmail: _angular_core.Signal<string | null>;
1734
+ readonly userRole: _angular_core.Signal<"owner" | "admin" | "reader" | null>;
1735
+ readonly isOwner: _angular_core.Signal<boolean>;
1736
+ readonly isAdmin: _angular_core.Signal<boolean>;
1737
+ readonly canEdit: _angular_core.Signal<boolean>;
1738
+ readonly licenseTier: _angular_core.Signal<"starter" | "growth" | "enterprise" | null>;
1739
+ readonly licenseActive: _angular_core.Signal<boolean>;
1740
+ readonly licenseExpiresAt: _angular_core.Signal<string | null>;
1741
+ readonly hasAccess: _angular_core.Signal<boolean>;
1742
+ readonly daysRemaining: _angular_core.Signal<number | null>;
1743
+ readonly isLicenseExpiringSoon: _angular_core.Signal<boolean>;
1744
+ /**
1745
+ * Obtiene el dominio actual.
1746
+ * Prioridad:
1747
+ * 1. STORE_DOMAIN token (inyectado)
1748
+ * 2. Query param ?shop= (solo en localhost)
1749
+ * 3. window.location.hostname
1750
+ */
1751
+ getCurrentDomain(): string;
1752
+ /**
1753
+ * Autentica al usuario para el dominio actual.
1754
+ * Esta es la función principal que debe llamarse al cargar la app.
1755
+ */
1756
+ authenticate(): Promise<ShopAuthData>;
1757
+ /**
1758
+ * Limpia el estado (para logout)
1759
+ */
1760
+ clear(): void;
1761
+ /**
1762
+ * Refresca la autenticación
1763
+ */
1764
+ refresh(): Promise<ShopAuthData>;
1765
+ /**
1766
+ * Verifica si el error actual indica que el usuario no tiene acceso
1767
+ */
1768
+ isNoAccessError(): boolean;
1769
+ /**
1770
+ * Verifica si el error actual indica que la licencia expiró
1771
+ */
1772
+ isLicenseExpiredError(): boolean;
1773
+ /**
1774
+ * Verifica si el usuario está inactivo
1775
+ */
1776
+ isUserInactiveError(): boolean;
1777
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopAuthService, never>;
1778
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopAuthService>;
1779
+ }
1780
+
1781
+ declare class LicenseGuardComponent {
1782
+ shopAuthService: ShopAuthService;
1783
+ showExpirationWarning: _angular_core.InputSignal<boolean>;
1784
+ subscribe: _angular_core.OutputEmitterRef<void>;
1785
+ renew: _angular_core.OutputEmitterRef<void>;
1786
+ reauth: _angular_core.OutputEmitterRef<void>;
1787
+ retry: _angular_core.OutputEmitterRef<void>;
1788
+ onSubscribe(): void;
1789
+ onRenew(): void;
1790
+ onReauth(): void;
1791
+ onRetry(): void;
1792
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LicenseGuardComponent, never>;
1793
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LicenseGuardComponent, "lib-license-guard", never, { "showExpirationWarning": { "alias": "showExpirationWarning"; "required": false; "isSignal": true; }; }, { "subscribe": "subscribe"; "renew": "renew"; "reauth": "reauth"; "retry": "retry"; }, never, ["*"], true, never>;
1794
+ }
1795
+
1796
+ declare class LoginComponent {
1797
+ private authService;
1798
+ private router;
1799
+ loginSuccess: _angular_core.OutputEmitterRef<void>;
1800
+ email: _angular_core.WritableSignal<string>;
1801
+ password: _angular_core.WritableSignal<string>;
1802
+ error: _angular_core.WritableSignal<string | null>;
1803
+ loading: _angular_core.WritableSignal<boolean>;
1804
+ isSignUp: _angular_core.WritableSignal<boolean>;
1805
+ showPassword: _angular_core.WritableSignal<boolean>;
1806
+ toggleMode(): void;
1807
+ togglePassword(): void;
1808
+ onSubmit(): Promise<void>;
1809
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LoginComponent, never>;
1810
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LoginComponent, "lib-login", never, {}, { "loginSuccess": "loginSuccess"; }, never, never, true, never>;
1811
+ }
1812
+
1813
+ type ViewState = 'loading' | 'no-store' | 'license-expired';
1814
+ declare class ActivateLicenseComponent implements OnInit {
1815
+ shopAuthService: ShopAuthService;
1816
+ viewState: _angular_core.Signal<ViewState>;
1817
+ ngOnInit(): void;
1818
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActivateLicenseComponent, never>;
1819
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActivateLicenseComponent, "lib-activate-license", never, {}, {}, never, never, true, never>;
1820
+ }
1821
+
1822
+ interface SupabaseConfig {
1823
+ supabaseUrl: string;
1824
+ supabaseAnonKey: string;
1825
+ }
1826
+ declare const SUPABASE_CONFIG: InjectionToken<SupabaseConfig>;
1827
+ declare class SupabaseAuthService implements OnDestroy {
1828
+ private config;
1829
+ private supabase;
1830
+ private supabasePromise;
1831
+ private authSubscription;
1832
+ private _session;
1833
+ private _user;
1834
+ private _loading;
1835
+ private _error;
1836
+ private _initialized;
1837
+ readonly session: _angular_core.Signal<Session | null>;
1838
+ readonly user: _angular_core.Signal<User | null>;
1839
+ readonly loading: _angular_core.Signal<boolean>;
1840
+ readonly error: _angular_core.Signal<string | null>;
1841
+ readonly initialized: _angular_core.Signal<boolean>;
1842
+ readonly isAuthenticated: _angular_core.Signal<boolean>;
1843
+ readonly accessToken: _angular_core.Signal<string | null>;
1844
+ readonly userEmail: _angular_core.Signal<string | null>;
1845
+ private getSupabaseClient;
1846
+ private initializeClient;
1847
+ ensureInitialized(): Promise<void>;
1848
+ signInWithPassword(email: string, password: string): Promise<{
1849
+ success: boolean;
1850
+ error?: string;
1851
+ }>;
1852
+ signUp(email: string, password: string): Promise<{
1853
+ success: boolean;
1854
+ error?: string;
1855
+ }>;
1856
+ signOut(): Promise<void>;
1857
+ resetPassword(email: string): Promise<{
1858
+ success: boolean;
1859
+ error?: string;
1860
+ }>;
1861
+ getClient(): Promise<SupabaseClient | null>;
1862
+ ngOnDestroy(): void;
1863
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SupabaseAuthService, never>;
1864
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SupabaseAuthService>;
1865
+ }
1866
+
1867
+ declare class AppShellComponent {
1868
+ authService: SupabaseAuthService;
1869
+ shopAuthService: ShopAuthService;
1870
+ loggedOut: _angular_core.OutputEmitterRef<void>;
1871
+ logout(): Promise<void>;
1872
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AppShellComponent, never>;
1873
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AppShellComponent, "lib-app-shell", never, {}, { "loggedOut": "loggedOut"; }, never, ["*"], true, never>;
1874
+ }
1875
+
1876
+ declare class NoAccessComponent {
1877
+ backToLogin: _angular_core.OutputEmitterRef<void>;
1878
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NoAccessComponent, never>;
1879
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NoAccessComponent, "ke-no-access", never, {}, { "backToLogin": "backToLogin"; }, never, never, true, never>;
1880
+ }
1881
+
1882
+ declare class LicenseExpiredComponent {
1883
+ backToLogin: _angular_core.OutputEmitterRef<void>;
1884
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LicenseExpiredComponent, never>;
1885
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LicenseExpiredComponent, "ke-license-expired", never, {}, { "backToLogin": "backToLogin"; }, never, never, true, never>;
1886
+ }
1887
+
1888
+ /**
1889
+ * Injection token to enable in-memory page storage (for development)
1890
+ * When false (default), uses Shopify metafields via GraphQL API
1891
+ */
1892
+ declare const USE_IN_MEMORY_PAGES: InjectionToken<boolean>;
1893
+ /**
1894
+ * Injection token for page environment (metafield key prefix).
1895
+ * Default is 'production'.
1896
+ */
1897
+ declare const PAGE_ENVIRONMENT: InjectionToken<string>;
1898
+ declare class PageService {
1899
+ private readonly useInMemory;
1900
+ private readonly pageEnvironment;
1901
+ private readonly memoryRepo;
1902
+ private readonly shopifyRepo;
1903
+ private resolveEnvironment;
1904
+ /**
1905
+ * Get all pages (summaries only for listing)
1906
+ */
1907
+ getPages(environment?: string): Observable<PageSummary[]>;
1908
+ /**
1909
+ * Get a single page by ID (full content)
1910
+ */
1911
+ getPage(id: string, environment?: string): Observable<Page>;
1912
+ /**
1913
+ * Get a published page by slug (for public rendering)
1914
+ */
1915
+ getPublishedPageBySlug(slug: string, environment?: string): Observable<Page>;
1916
+ /**
1917
+ * Create a new page
1918
+ */
1919
+ createPage(request: CreatePageRequest, environment?: string): Observable<Page>;
1920
+ /**
1921
+ * Update an existing page
1922
+ */
1923
+ updatePage(id: string, request: UpdatePageRequest, environment?: string): Observable<Page>;
1924
+ /**
1925
+ * Delete a page
1926
+ */
1927
+ deletePage(id: string, environment?: string): Observable<void>;
1928
+ /**
1929
+ * Publish a page (changes status to 'published')
1930
+ */
1931
+ publishPage(id: string, request: PublishPageRequest, environment?: string): Observable<Page>;
1932
+ /**
1933
+ * Unpublish a page (changes status to 'draft')
1934
+ */
1935
+ unpublishPage(id: string, request: PublishPageRequest, environment?: string): Observable<Page>;
1936
+ /**
1937
+ * Duplicate an existing page
1938
+ */
1939
+ duplicatePage(id: string, environment?: string): Observable<Page>;
1940
+ /**
1941
+ * Delete all pages for a given environment
1942
+ */
1943
+ deletePagesByEnvironment(environment?: string): Observable<void>;
1944
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PageService, never>;
1945
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<PageService>;
1946
+ }
1947
+
1948
+ interface ShopifyAppConfig {
1949
+ appUrl: string;
1950
+ }
1951
+ interface ShopifyTokenResponse {
1952
+ accessToken: string;
1953
+ shopifyDomain: string;
1954
+ }
1955
+ type TokenErrorCode = 'NOT_AUTHENTICATED' | 'NO_ACTIVE_STORE' | 'TOKEN_FETCH_FAILED' | 'SESSION_EXPIRED' | 'NO_STORE_ACCESS' | 'NETWORK_ERROR' | 'UNKNOWN_ERROR';
1956
+ interface TokenError {
1957
+ code: TokenErrorCode;
1958
+ message: string;
1959
+ status?: number;
1960
+ }
1961
+ declare const SHOPIFY_APP_CONFIG: InjectionToken<ShopifyAppConfig>;
1962
+ declare class ShopifyTokenService {
1963
+ private readonly http;
1964
+ private readonly config;
1965
+ private readonly authService;
1966
+ private readonly shopAuthService;
1967
+ private readonly CACHE_TTL_MS;
1968
+ private readonly tokenCache;
1969
+ private readonly _currentToken;
1970
+ private readonly _currentDomain;
1971
+ private readonly _loading;
1972
+ private readonly _error;
1973
+ private pendingRequest;
1974
+ readonly currentToken: _angular_core.Signal<string | null>;
1975
+ readonly currentDomain: _angular_core.Signal<string | null>;
1976
+ readonly loading: _angular_core.Signal<boolean>;
1977
+ readonly error: _angular_core.Signal<TokenError | null>;
1978
+ readonly hasToken: _angular_core.Signal<boolean>;
1979
+ readonly isReady: _angular_core.Signal<boolean>;
1980
+ getToken(): Observable<ShopifyTokenResponse>;
1981
+ getTokenForDomain(shopifyDomain: string): Observable<ShopifyTokenResponse>;
1982
+ refreshToken(): Observable<ShopifyTokenResponse>;
1983
+ invalidateCache(shopifyDomain?: string): void;
1984
+ clear(): void;
1985
+ private fetchToken;
1986
+ private getCachedToken;
1987
+ private setCachedToken;
1988
+ private handleHttpError;
1989
+ private createError;
1990
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopifyTokenService, never>;
1991
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopifyTokenService>;
1992
+ }
1993
+
1994
+ type GraphQLErrorCode = 'GRAPHQL_ERROR' | 'EMPTY_RESPONSE' | 'UNAUTHORIZED' | 'FORBIDDEN' | 'RATE_LIMIT' | 'SERVER_ERROR' | 'NETWORK_ERROR' | 'HTTP_ERROR' | 'TOKEN_ERROR' | 'UNKNOWN_ERROR';
1995
+ interface GraphQLError {
1996
+ code: GraphQLErrorCode;
1997
+ message: string;
1998
+ status?: number;
1999
+ errors?: Array<{
2000
+ message: string;
2001
+ }>;
2002
+ original?: unknown;
2003
+ }
2004
+ declare class ShopifyGraphQLClient {
2005
+ private readonly http;
2006
+ private readonly authService;
2007
+ private readonly shopAuthService;
2008
+ private readonly config;
2009
+ query<T>(query: string, variables?: Record<string, unknown>): Observable<T>;
2010
+ mutate<T>(mutation: string, variables?: Record<string, unknown>): Observable<T>;
2011
+ private executeOperation;
2012
+ private handleResponse;
2013
+ private handleHttpError;
2014
+ private createError;
2015
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopifyGraphQLClient, never>;
2016
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopifyGraphQLClient>;
2017
+ }
2018
+
2019
+ declare const NAMESPACE = "kustomizer";
2020
+ declare const INDEX_KEY = "pages_index";
2021
+ declare const MAX_METAFIELD_SIZE: number;
2022
+ declare const GET_SHOP_METAFIELD_QUERY = "\n query GetShopMetafield($namespace: String!, $key: String!) {\n shop {\n id\n metafield(namespace: $namespace, key: $key) {\n id\n value\n createdAt\n updatedAt\n }\n }\n }\n";
2023
+ declare const SET_METAFIELD_MUTATION = "\n mutation SetMetafield($metafields: [MetafieldsSetInput!]!) {\n metafieldsSet(metafields: $metafields) {\n metafields {\n id\n namespace\n key\n value\n }\n userErrors {\n field\n message\n }\n }\n }\n";
2024
+ declare const DELETE_METAFIELDS_MUTATION = "\n mutation DeleteMetafields($metafields: [MetafieldIdentifierInput!]!) {\n metafieldsDelete(metafields: $metafields) {\n deletedMetafields {\n key\n namespace\n }\n userErrors {\n field\n message\n }\n }\n }\n";
2025
+ declare const GET_SHOP_ID_QUERY = "\n query GetShopId {\n shop {\n id\n }\n }\n";
2026
+ declare class ShopifyMetafieldRepository {
2027
+ private readonly client;
2028
+ private resolveEnvironment;
2029
+ private buildIndexKey;
2030
+ private buildPageKey;
2031
+ getMetafield(namespace: string, key: string): Observable<Metafield | null>;
2032
+ setMetafield(namespace: string, key: string, value: any, ownerId: string): Observable<Metafield>;
2033
+ deleteMetafield(namespace: string, key: string): Observable<void>;
2034
+ getShopId(): Observable<string>;
2035
+ getPageIndex(environment?: string): Observable<PagesIndex>;
2036
+ updatePageIndex(index: PagesIndex, environment?: string): Observable<PagesIndex>;
2037
+ getPageMetafield(pageId: string, environment?: string): Observable<Page | null>;
2038
+ setPageMetafield(pageId: string, page: Page, environment?: string): Observable<Page>;
2039
+ deletePageMetafield(pageId: string, environment?: string): Observable<void>;
2040
+ resetPageIndex(environment?: string): Observable<PagesIndex>;
2041
+ validateSize(data: any): {
2042
+ valid: boolean;
2043
+ size: number;
2044
+ percentUsed: number;
2045
+ };
2046
+ private getDefaultIndex;
2047
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopifyMetafieldRepository, never>;
2048
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopifyMetafieldRepository>;
2049
+ }
2050
+
2051
+ declare class PageShopifyRepository {
2052
+ private readonly metafieldRepo;
2053
+ private resolveEnvironment;
2054
+ getPages(environment?: string): Observable<PageSummary[]>;
2055
+ getPage(id: string, environment?: string): Observable<Page>;
2056
+ getPublishedPageBySlug(slug: string, environment?: string): Observable<Page>;
2057
+ createPage(request: CreatePageRequest, environment?: string): Observable<Page>;
2058
+ updatePage(id: string, request: UpdatePageRequest, environment?: string): Observable<Page>;
2059
+ deletePage(id: string, environment?: string): Observable<void>;
2060
+ publishPage(id: string, request: PublishPageRequest, environment?: string): Observable<Page>;
2061
+ unpublishPage(id: string, request: PublishPageRequest, environment?: string): Observable<Page>;
2062
+ duplicatePage(id: string, environment?: string): Observable<Page>;
2063
+ deletePagesByEnvironment(environment?: string): Observable<void>;
2064
+ private validateUniqueSlug;
2065
+ private generateUniqueSlug;
2066
+ private addPageToIndex;
2067
+ private updatePageInIndex;
2068
+ private removePageFromIndex;
2069
+ private mapIndexEntryToSummary;
2070
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PageShopifyRepository, never>;
2071
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<PageShopifyRepository>;
2072
+ }
2073
+
2074
+ interface TeamMember {
2075
+ email: string;
2076
+ role: 'owner' | 'admin' | 'reader';
2077
+ status: 'active' | 'inactive' | 'suspended';
2078
+ invited_by: string | null;
2079
+ joined_at: string;
2080
+ is_current_user: boolean;
2081
+ }
2082
+ interface PendingInvitation {
2083
+ id: string;
2084
+ email: string;
2085
+ role: 'admin' | 'reader';
2086
+ invited_by: string;
2087
+ created_at: string;
2088
+ expires_at: string;
2089
+ is_expired: boolean;
2090
+ }
2091
+ interface CurrentUser {
2092
+ email: string;
2093
+ role: string;
2094
+ can_invite: boolean;
2095
+ can_remove_members: boolean;
2096
+ }
2097
+ interface TeamData {
2098
+ shop: {
2099
+ id: string;
2100
+ name: string;
2101
+ shopify_domain: string;
2102
+ allowed_domains: string[];
2103
+ };
2104
+ members: TeamMember[];
2105
+ invitations: PendingInvitation[];
2106
+ current_user: CurrentUser;
2107
+ summary: {
2108
+ total_members: number;
2109
+ pending_invitations: number;
2110
+ };
2111
+ }
2112
+ interface InviteResult {
2113
+ invitation_id: string;
2114
+ token: string;
2115
+ expires_at: string;
2116
+ email: string;
2117
+ role: string;
2118
+ }
2119
+ interface AcceptInvitationResult {
2120
+ success: boolean;
2121
+ shop: {
2122
+ id: string;
2123
+ name: string;
2124
+ shopify_domain: string;
2125
+ };
2126
+ role: string;
2127
+ message: string;
2128
+ }
2129
+ declare class ShopTeamService {
2130
+ private http;
2131
+ private config;
2132
+ private authService;
2133
+ private shopAuthService;
2134
+ private _team;
2135
+ private _loading;
2136
+ private _error;
2137
+ readonly team: _angular_core.Signal<TeamData | null>;
2138
+ readonly loading: _angular_core.Signal<boolean>;
2139
+ readonly error: _angular_core.Signal<string | null>;
2140
+ readonly members: _angular_core.Signal<TeamMember[]>;
2141
+ readonly invitations: _angular_core.Signal<PendingInvitation[]>;
2142
+ readonly currentUser: _angular_core.Signal<CurrentUser | null>;
2143
+ readonly activeMembers: _angular_core.Signal<TeamMember[]>;
2144
+ readonly pendingInvitations: _angular_core.Signal<PendingInvitation[]>;
2145
+ readonly canInvite: _angular_core.Signal<boolean>;
2146
+ /**
2147
+ * Carga el equipo de la shop actual
2148
+ */
2149
+ loadTeam(): Promise<TeamData | null>;
2150
+ /**
2151
+ * Invita a un usuario a la shop
2152
+ */
2153
+ inviteUser(email: string, role: 'admin' | 'reader', message?: string): Promise<InviteResult | null>;
2154
+ /**
2155
+ * Acepta una invitación (usado cuando un usuario hace click en el link de invitación)
2156
+ */
2157
+ acceptInvitation(invitationToken: string): Promise<AcceptInvitationResult | null>;
2158
+ /**
2159
+ * Genera el URL de invitación (para copiar/compartir)
2160
+ */
2161
+ getInvitationUrl(token: string, baseUrl?: string): string;
2162
+ /**
2163
+ * Limpia el estado
2164
+ */
2165
+ clear(): void;
2166
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ShopTeamService, never>;
2167
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ShopTeamService>;
2168
+ }
2169
+
2170
+ declare const authGuard: CanActivateFn;
2171
+ declare const noAuthGuard: CanActivateFn;
2172
+
2173
+ declare const licenseGuard: CanActivateFn;
2174
+ declare const noLicenseGuard: CanActivateFn;
2175
+
2176
+ /**
2177
+ * Guard que verifica:
2178
+ * 1. Usuario autenticado
2179
+ * 2. Usuario tiene acceso a la shop del dominio actual
2180
+ * 3. Licencia activa
2181
+ *
2182
+ * Redirige a:
2183
+ * - /login si no está autenticado
2184
+ * - /no-access si no tiene acceso a la shop
2185
+ * - /license-expired si la licencia expiró
2186
+ */
2187
+ declare const shopAuthGuard: CanActivateFn;
2188
+ /**
2189
+ * Guard que solo permite acceso si el usuario NO tiene acceso a una shop.
2190
+ * Útil para páginas como /login que no deberían ser accesibles si ya tienes acceso.
2191
+ */
2192
+ declare const noShopAuthGuard: CanActivateFn;
2193
+ /**
2194
+ * Guard que verifica que el usuario tenga rol de admin o owner.
2195
+ * Requiere que shopAuthGuard se haya ejecutado primero.
2196
+ */
2197
+ declare const shopAdminGuard: CanActivateFn;
2198
+ /**
2199
+ * Guard que verifica que el usuario pueda editar (owner o admin).
2200
+ * Los readers solo pueden ver, no editar.
2201
+ */
2202
+ declare const shopEditorGuard: CanActivateFn;
2203
+
2204
+ declare class DragDropService {
2205
+ private readonly store;
2206
+ private readonly registry;
2207
+ private readonly sections;
2208
+ readonly dragItem: _angular_core.WritableSignal<DragItem | null>;
2209
+ readonly dropTarget: _angular_core.WritableSignal<DropTarget | null>;
2210
+ readonly isDragging: _angular_core.Signal<boolean>;
2211
+ startDrag(item: DragItem, event: DragEvent): void;
2212
+ endDrag(): void;
2213
+ updateDropTarget(target: DropTarget | null): void;
2214
+ computeDropZone(event: DragEvent, element: HTMLElement, canDropInside: boolean): DropZone;
2215
+ validateDrop(item: DragItem, target: DropTarget): boolean;
2216
+ executeDrop(): void;
2217
+ private executeSectionDrop;
2218
+ private executeBlockDrop;
2219
+ private isDropOnSelf;
2220
+ private wouldCreateCircular;
2221
+ private isTypeAllowedInSlot;
2222
+ private findElementInTree;
2223
+ private isDescendant;
2224
+ private pathsEqual;
2225
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DragDropService, never>;
2226
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DragDropService>;
2227
+ }
2228
+
2229
+ declare class VisualEditor {
2230
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<VisualEditor, never>;
2231
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<VisualEditor, "lib-visual-editor", never, {}, {}, never, never, true, never>;
2232
+ }
2233
+
2234
+ export { ActivateLicenseComponent, AppShellComponent, BlockTreeItemComponent, ComponentRegistryService, DEFAULT_ROUTER_NAVIGATION_CONFIG, DEFAULT_VISUAL_EDITOR_CONFIG, DELETE_METAFIELDS_MUTATION, DefaultRouterNavigationService, DragDropService, DynamicRendererComponent, EDITOR_COMPONENT_DEFINITIONS, FILES_QUERY, GET_SHOP_ID_QUERY, GET_SHOP_METAFIELD_QUERY, INDEX_KEY, InputPageLoadingStrategy, LicenseExpiredComponent, LicenseGuardComponent, LoginComponent, MAX_METAFIELD_SIZE, NAMESPACE, NoAccessComponent, PAGE_ENVIRONMENT, PageLoadingStrategy, PageManagerComponent, PageService, PageShopifyRepository, ROUTER_NAVIGATION_CONFIG, RoutePageLoadingStrategy, SET_METAFIELD_MUTATION, SHOPIFY_API_VERSION, SHOPIFY_APP_CONFIG, SHOPIFY_CONFIG, STORE_DOMAIN, SUPABASE_CONFIG, ShopAuthService, ShopTeamService, ShopifyFilePickerComponent, ShopifyFilesService, ShopifyGraphQLClient, ShopifyMetafieldRepository, ShopifyTokenService, SlotRendererComponent, SupabaseAuthService, USE_IN_MEMORY_PAGES, VISUAL_EDITOR_CONFIG, VISUAL_EDITOR_FEATURE_KEY, VisualEditor, VisualEditorActions, VisualEditorComponent, VisualEditorFacade, VisualEditorNavigation, authGuard, initialVisualEditorState, licenseGuard, noAuthGuard, noLicenseGuard, noShopAuthGuard, provideEditorComponents, provideVisualEditor, provideVisualEditorStore, selectBlocksForSection, selectBlocksForSlot, selectCanRedo, selectCanUndo, selectCurrentPage, selectCurrentPageId, selectCurrentPageSlug, selectCurrentPageStatus, selectCurrentPageTitle, selectCurrentPageVersion, selectDraggedElementId, selectElementById, selectHistory, selectHistoryIndex, selectHistoryLength, selectIsDirty, selectIsDragging, selectIsPageLoaded, selectLastAction, selectSectionById, selectSections, selectSelectedBlock, selectSelectedBlockSlotName, selectSelectedElement, selectSelectedElementId, selectSelectedElementType, selectSelectedSection, selectSelectedSectionId, selectSelectedSectionType, selectVisualEditorState, shopAdminGuard, shopAuthGuard, shopEditorGuard, visualEditorReducer };
2235
+ export type { AcceptInvitationResult, BlockPickerTarget, BlockTreeContext, ComponentCategory, ComponentDefinition, ComponentPreset, ConfirmDialogOptions, CreatePageRequest, CurrentUser, DragItem, DragItemKind, DropTarget, DropZone, EditorElement, EditorSection, GraphQLError, GraphQLErrorCode, HistoryEntry, InviteResult, Metafield, Page, PageContext, PageIndexEntry, PageStatus, PageSummary, PagesIndex, PendingInvitation, PresetBlockConfig, PropCondition, PropSchema, PropSchemaMap, PropType, PropValidation, PublishPageRequest, ResolvedPreset, RouterNavigationConfig, SelectOption, Shop, ShopAuthData, ShopAuthError, ShopLicense, ShopUser, ShopifyAppConfig, ShopifyConfig, ShopifyFile, ShopifyFilesPage, ShopifyTokenResponse, SlotConstraints, SlotDefinition, SupabaseConfig, TeamData, TeamMember, TokenError, TokenErrorCode, UpdatePageRequest, VisualEditorConfig, VisualEditorNavigationTarget, VisualEditorState };