@momentumcms/admin 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/fesm2022/{momentumcms-admin-array-field.component-CT5NlIEv.mjs → momentumcms-admin-array-field.component-Bjlcczwg.mjs} +2 -2
  2. package/fesm2022/{momentumcms-admin-array-field.component-CT5NlIEv.mjs.map → momentumcms-admin-array-field.component-Bjlcczwg.mjs.map} +1 -1
  3. package/fesm2022/{momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs → momentumcms-admin-blocks-field.component-4vLqDGbB.mjs} +2 -2
  4. package/fesm2022/{momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs.map → momentumcms-admin-blocks-field.component-4vLqDGbB.mjs.map} +1 -1
  5. package/fesm2022/{momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs → momentumcms-admin-collapsible-field.component-63-9kSgm.mjs} +2 -2
  6. package/fesm2022/{momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs.map → momentumcms-admin-collapsible-field.component-63-9kSgm.mjs.map} +1 -1
  7. package/fesm2022/{momentumcms-admin-global-edit.page-BBUtWCSl.mjs → momentumcms-admin-global-edit.page-DSnkwdgn.mjs} +2 -2
  8. package/fesm2022/{momentumcms-admin-global-edit.page-BBUtWCSl.mjs.map → momentumcms-admin-global-edit.page-DSnkwdgn.mjs.map} +1 -1
  9. package/fesm2022/{momentumcms-admin-group-field.component-BZeG8Oqy.mjs → momentumcms-admin-group-field.component-B48_zbo0.mjs} +2 -2
  10. package/fesm2022/{momentumcms-admin-group-field.component-BZeG8Oqy.mjs.map → momentumcms-admin-group-field.component-B48_zbo0.mjs.map} +1 -1
  11. package/fesm2022/{momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs → momentumcms-admin-momentumcms-admin-D_47TVaR.mjs} +1531 -749
  12. package/fesm2022/momentumcms-admin-momentumcms-admin-D_47TVaR.mjs.map +1 -0
  13. package/fesm2022/{momentumcms-admin-relationship-field.component-BuxtRs2_.mjs → momentumcms-admin-relationship-field.component-D-UQgd7m.mjs} +2 -2
  14. package/fesm2022/{momentumcms-admin-relationship-field.component-BuxtRs2_.mjs.map → momentumcms-admin-relationship-field.component-D-UQgd7m.mjs.map} +1 -1
  15. package/fesm2022/{momentumcms-admin-rich-text-field.component-DKQ6pwp7.mjs → momentumcms-admin-rich-text-field.component-BC8pRU89.mjs} +2 -2
  16. package/fesm2022/{momentumcms-admin-rich-text-field.component-DKQ6pwp7.mjs.map → momentumcms-admin-rich-text-field.component-BC8pRU89.mjs.map} +1 -1
  17. package/fesm2022/{momentumcms-admin-row-field.component-ks3FXd4B.mjs → momentumcms-admin-row-field.component--EOPGDtM.mjs} +2 -2
  18. package/fesm2022/{momentumcms-admin-row-field.component-ks3FXd4B.mjs.map → momentumcms-admin-row-field.component--EOPGDtM.mjs.map} +1 -1
  19. package/fesm2022/{momentumcms-admin-tabs-field.component-mZ4dpZoD.mjs → momentumcms-admin-tabs-field.component-B4X73eCM.mjs} +2 -2
  20. package/fesm2022/{momentumcms-admin-tabs-field.component-mZ4dpZoD.mjs.map → momentumcms-admin-tabs-field.component-B4X73eCM.mjs.map} +1 -1
  21. package/fesm2022/momentumcms-admin.mjs +1 -1
  22. package/package.json +1 -1
  23. package/types/momentumcms-admin.d.ts +92 -29
  24. package/fesm2022/momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs.map +0 -1
@@ -1,12 +1,12 @@
1
1
  import { Routes, CanActivateFn, CanDeactivateFn } from '@angular/router';
2
2
  import * as _angular_core from '@angular/core';
3
- import { Type, InjectionToken, Signal, Provider, OnInit, WritableSignal, ElementRef, makeEnvironmentProviders } from '@angular/core';
3
+ import { Type, InjectionToken, Signal, Provider, OnInit, WritableSignal, makeEnvironmentProviders } from '@angular/core';
4
4
  import { CollectionConfig, GlobalConfig, PluginAdminRouteDescriptor, MomentumPlugin, MomentumConfig, MomentumAdminConfig, MediaDocument, AdminConfig, Field, DocumentStatus as DocumentStatus$1, BlockConfig, UploadField } from '@momentumcms/core';
5
5
  import { HttpContextToken, HttpInterceptorFn } from '@angular/common/http';
6
6
  import { Observable } from 'rxjs';
7
+ import * as _momentumcms_admin from '@momentumcms/admin';
7
8
  import { DataTableColumn, DataTableSort, DataTableRowAction, DataTableRowActionEvent, FieldDisplayType, FieldDisplayFieldMeta, FieldDisplayNumberFormat, FieldDisplayDateFormat, PopoverTrigger, ValidationError, SelectOption } from '@momentumcms/ui';
8
9
  import * as _angular_forms_signals from '@angular/forms/signals';
9
- import { SafeResourceUrl } from '@angular/platform-browser';
10
10
  import { CdkDragDrop } from '@angular/cdk/drag-drop';
11
11
 
12
12
  /**
@@ -476,6 +476,16 @@ declare class UploadService {
476
476
  * @returns Observable emitting upload progress
477
477
  */
478
478
  upload(file: File, alt?: string): Observable<UploadProgress>;
479
+ /**
480
+ * Upload a file to a specific upload collection.
481
+ * POSTs multipart/form-data to /api/{collectionSlug} with file + additional fields.
482
+ *
483
+ * @param collectionSlug - Target collection (e.g., 'media', 'documents')
484
+ * @param file - The file to upload
485
+ * @param fields - Additional form fields to include (e.g., alt, title)
486
+ * @returns Observable emitting upload progress
487
+ */
488
+ uploadToCollection(collectionSlug: string, file: File, fields?: Record<string, string>): Observable<UploadProgress>;
479
489
  /**
480
490
  * Upload multiple files.
481
491
  *
@@ -943,6 +953,17 @@ interface Entity {
943
953
  updatedAt?: string;
944
954
  [key: string]: unknown;
945
955
  }
956
+ /**
957
+ * A named group of collections for display in admin UI.
958
+ * Used by the dashboard and sidebar to render grouped sections.
959
+ */
960
+ interface CollectionGroup {
961
+ /** Slugified identifier safe for use as an HTML id attribute */
962
+ id: string;
963
+ /** Original display name */
964
+ name: string;
965
+ collections: CollectionConfig[];
966
+ }
946
967
 
947
968
  /**
948
969
  * Result emitted when the entity sheet closes.
@@ -1747,6 +1768,8 @@ declare class DashboardPage {
1747
1768
  private readonly allCollections;
1748
1769
  /** Collections filtered by visibility and access permissions */
1749
1770
  readonly collections: _angular_core.Signal<CollectionConfig[]>;
1771
+ /** Visible collections grouped by admin.group. Named groups first, default last. */
1772
+ readonly collectionGroups: _angular_core.Signal<_momentumcms_admin.CollectionGroup[]>;
1750
1773
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DashboardPage, never>;
1751
1774
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DashboardPage, "mcms-dashboard", never, {}, {}, never, never, true, never>;
1752
1775
  }
@@ -2007,23 +2030,17 @@ declare class CollectionListPage {
2007
2030
  * Collection View Page Component
2008
2031
  *
2009
2032
  * Displays a read-only view of a document using the EntityViewWidget.
2010
- * When preview is enabled, shows a toggleable live preview panel.
2033
+ * Preview is available via the "Open Page" link in the entity header
2034
+ * (opens in a new tab). Live preview iframe is only on the edit page,
2035
+ * since the view page is read-only and has no changes to preview live.
2011
2036
  */
2012
2037
  declare class CollectionViewPage {
2013
2038
  private readonly route;
2014
2039
  private readonly router;
2015
2040
  readonly basePath = "/admin/collections";
2016
- /** Whether the live preview panel is visible */
2017
- readonly showPreview: _angular_core.WritableSignal<boolean>;
2018
- /** Reference to the entity view widget to read its entity data */
2019
- private readonly entityViewRef;
2020
2041
  private readonly slug;
2021
2042
  readonly entityId: _angular_core.Signal<string>;
2022
2043
  readonly collection: _angular_core.Signal<CollectionConfig | undefined>;
2023
- /** Preview config from collection admin settings */
2024
- readonly previewConfig: _angular_core.Signal<boolean | ((doc: Record<string, unknown>) => string) | undefined>;
2025
- /** Entity data from the entity view widget (for live preview) */
2026
- readonly viewEntityData: _angular_core.Signal<Record<string, unknown>>;
2027
2044
  onEdit(entity: Entity): void;
2028
2045
  onDelete(_entity: Entity): void;
2029
2046
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<CollectionViewPage, never>;
@@ -2090,7 +2107,7 @@ declare class CollectionEditPage implements HasUnsavedChanges {
2090
2107
  readonly mode: _angular_core.Signal<EntityFormMode>;
2091
2108
  readonly collection: _angular_core.Signal<CollectionConfig | undefined>;
2092
2109
  /** Preview config from collection admin settings (false-y when not configured) */
2093
- readonly previewConfig: _angular_core.Signal<boolean | ((doc: Record<string, unknown>) => string) | undefined>;
2110
+ readonly previewConfig: _angular_core.Signal<string | boolean | ((doc: Record<string, unknown>) => string) | undefined>;
2094
2111
  /** Reactive form data from the entity form widget */
2095
2112
  readonly formData: _angular_core.Signal<Record<string, unknown>>;
2096
2113
  /** HasUnsavedChanges implementation for the route guard */
@@ -2298,10 +2315,6 @@ declare class ResetPasswordPage implements OnInit {
2298
2315
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ResetPasswordPage, "mcms-reset-password-page", never, {}, {}, never, never, true, never>;
2299
2316
  }
2300
2317
 
2301
- interface CollectionGroup {
2302
- name: string;
2303
- collections: CollectionConfig[];
2304
- }
2305
2318
  interface GlobalGroup {
2306
2319
  name: string;
2307
2320
  globals: GlobalConfig[];
@@ -2355,7 +2368,7 @@ declare class AdminSidebarWidget {
2355
2368
  /** Computed collections base path */
2356
2369
  readonly collectionsBasePath: _angular_core.Signal<string>;
2357
2370
  /** Collections grouped by admin.group field */
2358
- readonly collectionGroups: _angular_core.Signal<CollectionGroup[]>;
2371
+ readonly collectionGroups: _angular_core.Signal<_momentumcms_admin.CollectionGroup[]>;
2359
2372
  /** Globals grouped by admin.group field */
2360
2373
  readonly globalGroups: _angular_core.Signal<GlobalGroup[]>;
2361
2374
  /** Plugin routes grouped by group field */
@@ -2464,6 +2477,7 @@ declare class CollectionCardWidget {
2464
2477
  declare class EntityFormWidget<T extends Entity = Entity> {
2465
2478
  private readonly api;
2466
2479
  private readonly injector;
2480
+ private readonly uploadService;
2467
2481
  private readonly versionService;
2468
2482
  private readonly collectionAccess;
2469
2483
  private readonly feedback;
@@ -2504,6 +2518,13 @@ declare class EntityFormWidget<T extends Entity = Entity> {
2504
2518
  readonly isSubmitting: _angular_core.WritableSignal<boolean>;
2505
2519
  readonly isSavingDraft: _angular_core.WritableSignal<boolean>;
2506
2520
  readonly formError: _angular_core.WritableSignal<string | null>;
2521
+ /** Upload collection state */
2522
+ readonly pendingFile: _angular_core.WritableSignal<File | null>;
2523
+ readonly isUploadingFile: _angular_core.WritableSignal<boolean>;
2524
+ readonly uploadFileProgress: _angular_core.WritableSignal<number>;
2525
+ readonly uploadFileError: _angular_core.WritableSignal<string | null>;
2526
+ /** Whether the collection is an upload collection */
2527
+ readonly isUploadCol: _angular_core.Signal<boolean>;
2507
2528
  /** Whether the form has been set up */
2508
2529
  private formCreated;
2509
2530
  /** Whether the form has unsaved changes (from signal forms dirty tracking) */
@@ -2539,11 +2560,32 @@ declare class EntityFormWidget<T extends Entity = Entity> {
2539
2560
  * Load global singleton document.
2540
2561
  */
2541
2562
  private loadGlobal;
2563
+ /**
2564
+ * Handle file selected in the upload zone.
2565
+ * Auto-populates metadata fields in the form model.
2566
+ */
2567
+ onFileSelected(file: File): void;
2568
+ /**
2569
+ * Handle file removed from the upload zone.
2570
+ */
2571
+ onFileRemoved(): void;
2542
2572
  /**
2543
2573
  * Handle form submission using Angular Signal Forms submit().
2544
2574
  * submit() marks all fields as touched, then only calls the callback if valid.
2575
+ * For upload collections with a pending file, uses multipart upload via UploadService.
2545
2576
  */
2546
2577
  onSubmit(): Promise<void>;
2578
+ /**
2579
+ * For upload/relationship fields, the form may store a full document object
2580
+ * (e.g., after upload completes) but the DB expects just the UUID.
2581
+ * Extract the `id` property from any upload field values that are objects.
2582
+ */
2583
+ private normalizeUploadFieldValues;
2584
+ /**
2585
+ * Submit an upload collection form with file via multipart.
2586
+ * Converts non-file form fields to string key-value pairs for the FormData.
2587
+ */
2588
+ private submitUploadCollection;
2547
2589
  /**
2548
2590
  * Handle cancel.
2549
2591
  */
@@ -2723,7 +2765,7 @@ declare class EntityViewWidget<T extends Entity = Entity> {
2723
2765
  */
2724
2766
  onVersionRestored(): void;
2725
2767
  /**
2726
- * Resolve relationship field values from IDs to display labels.
2768
+ * Resolve relationship and upload field values from IDs to display labels.
2727
2769
  */
2728
2770
  private resolveRelationships;
2729
2771
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityViewWidget<any>, never>;
@@ -3036,7 +3078,7 @@ declare class MediaPreviewComponent {
3036
3078
  /** Image URL for preview */
3037
3079
  readonly imageUrl: _angular_core.Signal<string>;
3038
3080
  /** Icon name based on media type */
3039
- readonly iconName: _angular_core.Signal<"<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.375 19.5h17.25m-17.25 0a1.125 1.125 0 0 1-1.125-1.125M3.375 19.5h1.5C5.496 19.5 6 18.996 6 18.375m-3.75 0V5.625m0 12.75v-1.5c0-.621.504-1.125 1.125-1.125m18.375 2.625V5.625m0 12.75c0 .621-.504 1.125-1.125 1.125m1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125m0 3.75h-1.5A1.125 1.125 0 0 1 18 18.375M20.625 4.5H3.375m17.25 0c.621 0 1.125.504 1.125 1.125M20.625 4.5h-1.5C18.504 4.5 18 5.004 18 5.625m3.75 0v1.5c0 .621-.504 1.125-1.125 1.125M3.375 4.5c-.621 0-1.125.504-1.125 1.125M3.375 4.5h1.5C5.496 4.5 6 5.004 6 5.625m-3.75 0v1.5c0 .621.504 1.125 1.125 1.125m0 0h1.5m-1.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125m1.5-3.75C5.496 8.25 6 7.746 6 7.125v-1.5M4.875 8.25C5.496 8.25 6 8.754 6 9.375v1.5m0-5.25v5.25m0-5.25C6 5.004 6.504 4.5 7.125 4.5h9.75c.621 0 1.125.504 1.125 1.125m1.125 2.625h1.5m-1.5 0A1.125 1.125 0 0 1 18 7.125v-1.5m1.125 2.625c-.621 0-1.125.504-1.125 1.125v1.5m2.625-2.625c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125M18 5.625v5.25M7.125 12h9.75m-9.75 0A1.125 1.125 0 0 1 6 10.875M7.125 12C6.504 12 6 12.504 6 13.125m0-2.25C6 11.496 5.496 12 4.875 12M18 10.875c0 .621-.504 1.125-1.125 1.125M18 10.875c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125m-12 5.25v-5.25m0 5.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125m-12 0v-1.5c0-.621-.504-1.125-1.125-1.125M18 18.375v-5.25m0 5.25v-1.5c0-.621.504-1.125 1.125-1.125M18 13.125v1.5c0 .621.504 1.125 1.125 1.125M18 13.125c0-.621.504-1.125 1.125-1.125M6 13.125v1.5c0 .621-.504 1.125-1.125 1.125M6 13.125C6 12.504 5.496 12 4.875 12m-1.5 0h1.5m-1.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125M19.125 12h1.5m0 0c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h1.5m14.25 0h1.5\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m9 9 10.5-3m0 6.553v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 1 1-.99-3.467l2.31-.66a2.25 2.25 0 0 0 1.632-2.163Zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 0 1-.99-3.467l2.31-.66A2.25 2.25 0 0 0 9 15.553Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m20.25 7.5-.625 10.632a2.25 2.25 0 0 1-2.247 2.118H6.622a2.25 2.25 0 0 1-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125Z\"></path></svg>">;
3081
+ readonly iconName: _angular_core.Signal<"<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.375 19.5h17.25m-17.25 0a1.125 1.125 0 0 1-1.125-1.125M3.375 19.5h1.5C5.496 19.5 6 18.996 6 18.375m-3.75 0V5.625m0 12.75v-1.5c0-.621.504-1.125 1.125-1.125m18.375 2.625V5.625m0 12.75c0 .621-.504 1.125-1.125 1.125m1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125m0 3.75h-1.5A1.125 1.125 0 0 1 18 18.375M20.625 4.5H3.375m17.25 0c.621 0 1.125.504 1.125 1.125M20.625 4.5h-1.5C18.504 4.5 18 5.004 18 5.625m3.75 0v1.5c0 .621-.504 1.125-1.125 1.125M3.375 4.5c-.621 0-1.125.504-1.125 1.125M3.375 4.5h1.5C5.496 4.5 6 5.004 6 5.625m-3.75 0v1.5c0 .621.504 1.125 1.125 1.125m0 0h1.5m-1.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125m1.5-3.75C5.496 8.25 6 7.746 6 7.125v-1.5M4.875 8.25C5.496 8.25 6 8.754 6 9.375v1.5m0-5.25v5.25m0-5.25C6 5.004 6.504 4.5 7.125 4.5h9.75c.621 0 1.125.504 1.125 1.125m1.125 2.625h1.5m-1.5 0A1.125 1.125 0 0 1 18 7.125v-1.5m1.125 2.625c-.621 0-1.125.504-1.125 1.125v1.5m2.625-2.625c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125M18 5.625v5.25M7.125 12h9.75m-9.75 0A1.125 1.125 0 0 1 6 10.875M7.125 12C6.504 12 6 12.504 6 13.125m0-2.25C6 11.496 5.496 12 4.875 12M18 10.875c0 .621-.504 1.125-1.125 1.125M18 10.875c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125m-12 5.25v-5.25m0 5.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125m-12 0v-1.5c0-.621-.504-1.125-1.125-1.125M18 18.375v-5.25m0 5.25v-1.5c0-.621.504-1.125 1.125-1.125M18 13.125v1.5c0 .621.504 1.125 1.125 1.125M18 13.125c0-.621.504-1.125 1.125-1.125M6 13.125v1.5c0 .621-.504 1.125-1.125 1.125M6 13.125C6 12.504 5.496 12 4.875 12m-1.5 0h1.5m-1.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125M19.125 12h1.5m0 0c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h1.5m14.25 0h1.5\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m9 9 10.5-3m0 6.553v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 1 1-.99-3.467l2.31-.66a2.25 2.25 0 0 0 1.632-2.163Zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 0 1-1.632 2.163l-1.32.377a1.803 1.803 0 0 1-.99-3.467l2.31-.66A2.25 2.25 0 0 0 9 15.553Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m20.25 7.5-.625 10.632a2.25 2.25 0 0 1-2.247 2.118H6.622a2.25 2.25 0 0 1-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z\"></path></svg>" | "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\" style=\"stroke-width:var(--ng-icon__stroke-width, 1.5)\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"></path></svg>">;
3040
3082
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MediaPreviewComponent, never>;
3041
3083
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MediaPreviewComponent, "mcms-media-preview", never, { "media": { "alias": "media"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "class": { "alias": "class"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3042
3084
  }
@@ -3047,14 +3089,23 @@ type DeviceSize = 'desktop' | 'tablet' | 'mobile';
3047
3089
  * Live Preview Widget
3048
3090
  *
3049
3091
  * Displays an iframe that shows a live preview of the document being edited.
3050
- * Sends form data to the iframe via postMessage on each change.
3092
+ *
3093
+ * Two modes based on preview config type:
3094
+ * - `preview: true` (server-rendered HTML): iframe loads API endpoint with scripts enabled
3095
+ * for postMessage live updates.
3096
+ * - `preview: string/function` (URL-based): iframe loads the page URL with scripts DISABLED.
3097
+ * This prevents loading a second Angular app instance (with Vite HMR, SSR hydration, etc.)
3098
+ * which causes tab crashes in dev mode. The SSR-rendered HTML displays correctly without JS.
3099
+ * Use the Refresh button to see form changes reflected in the preview.
3100
+ *
3101
+ * The iframe is declared statically in the template (no dynamic bindings) to avoid NG0910.
3102
+ * Its src/sandbox attributes are set via nativeElement in an effect().
3051
3103
  */
3052
3104
  declare class LivePreviewComponent {
3053
3105
  private readonly document;
3054
- private readonly sanitizer;
3055
3106
  private readonly destroyRef;
3056
3107
  /** Preview configuration from collection admin config */
3057
- readonly preview: _angular_core.InputSignal<boolean | ((doc: Record<string, unknown>) => string)>;
3108
+ readonly preview: _angular_core.InputSignal<string | boolean | ((doc: Record<string, unknown>) => string)>;
3058
3109
  /** Current document data from the form */
3059
3110
  readonly documentData: _angular_core.InputSignal<Record<string, unknown>>;
3060
3111
  /** Collection slug */
@@ -3067,14 +3118,14 @@ declare class LivePreviewComponent {
3067
3118
  readonly deviceSize: _angular_core.WritableSignal<DeviceSize>;
3068
3119
  /** Refresh counter to force iframe reload */
3069
3120
  private readonly refreshCounter;
3070
- /** Reference to the iframe element */
3071
- readonly previewFrame: _angular_core.Signal<ElementRef<HTMLIFrameElement> | undefined>;
3121
+ /** Reference to the static iframe element (available when previewUrl is non-null) */
3122
+ private readonly previewIframe;
3072
3123
  /** Compute the raw preview URL */
3073
3124
  readonly previewUrl: _angular_core.Signal<string | null>;
3074
- /** Sanitized preview URL for iframe binding */
3075
- readonly safePreviewUrl: _angular_core.Signal<SafeResourceUrl | null>;
3076
3125
  /** Computed iframe width based on device size */
3077
3126
  readonly iframeWidth: _angular_core.Signal<string>;
3127
+ /** Sandbox attribute value based on preview mode */
3128
+ private readonly sandboxValue;
3078
3129
  /** Debounce timer for postMessage updates */
3079
3130
  private debounceTimer;
3080
3131
  constructor();
@@ -3341,7 +3392,7 @@ declare class FieldRenderer {
3341
3392
  /** Error from lazy loading failure */
3342
3393
  readonly loadError: _angular_core.WritableSignal<Error | null>;
3343
3394
  /** Registry key: 'blocks-visual' when blocks field has visual editor, otherwise field.type */
3344
- readonly registryKey: _angular_core.Signal<"number" | "slug" | "email" | "text" | "textarea" | "richText" | "date" | "checkbox" | "select" | "radio" | "password" | "upload" | "relationship" | "array" | "group" | "blocks" | "json" | "point" | "tabs" | "collapsible" | "row" | "blocks-visual">;
3395
+ readonly registryKey: _angular_core.Signal<"number" | "slug" | "email" | "json" | "text" | "textarea" | "richText" | "date" | "checkbox" | "select" | "radio" | "password" | "upload" | "relationship" | "array" | "group" | "blocks" | "point" | "tabs" | "collapsible" | "row" | "blocks-visual">;
3345
3396
  /** Inputs to pass to the dynamically loaded component via NgComponentOutlet */
3346
3397
  readonly rendererInputs: _angular_core.Signal<{
3347
3398
  field: Field;
@@ -3606,9 +3657,10 @@ declare class DateFieldRenderer {
3606
3657
  * a FieldTree node's FieldState rather than event-based I/O.
3607
3658
  */
3608
3659
  declare class UploadFieldRenderer {
3609
- private readonly document;
3660
+ private readonly fileInputRef;
3610
3661
  private readonly uploadService;
3611
3662
  private readonly dialogService;
3663
+ private readonly api;
3612
3664
  /** Field definition */
3613
3665
  readonly field: _angular_core.InputSignal<Field>;
3614
3666
  /** Signal forms FieldTree node for this field */
@@ -3630,6 +3682,10 @@ declare class UploadFieldRenderer {
3630
3682
  readonly uploadingFilename: _angular_core.WritableSignal<string>;
3631
3683
  readonly uploadError: _angular_core.WritableSignal<string | null>;
3632
3684
  readonly uploadingFile: _angular_core.WritableSignal<File | null>;
3685
+ /** Resolved media document fetched from API when value is just an ID string */
3686
+ private readonly resolvedMedia;
3687
+ private resolvedMediaId;
3688
+ constructor();
3633
3689
  /** Unique field ID */
3634
3690
  readonly fieldId: _angular_core.Signal<string>;
3635
3691
  /** Computed label */
@@ -3644,6 +3700,8 @@ declare class UploadFieldRenderer {
3644
3700
  private readonly currentValue;
3645
3701
  /** Whether we have a value */
3646
3702
  readonly hasValue: _angular_core.Signal<boolean>;
3703
+ /** Effective media document — full object from value, or resolved from API */
3704
+ private readonly effectiveMedia;
3647
3705
  /** Media preview data from value */
3648
3706
  readonly mediaPreviewData: _angular_core.Signal<MediaPreviewData | null>;
3649
3707
  /** Media filename from value */
@@ -3674,6 +3732,11 @@ declare class UploadFieldRenderer {
3674
3732
  * Trigger hidden file input click.
3675
3733
  */
3676
3734
  triggerFileInput(): void;
3735
+ /**
3736
+ * Handle Space keydown on drop zone.
3737
+ * Prevents default scroll behavior and triggers file input.
3738
+ */
3739
+ onDropZoneSpace(event: Event): void;
3677
3740
  /**
3678
3741
  * Handle file selection from input.
3679
3742
  */
@@ -3769,4 +3832,4 @@ declare class MediaPickerDialog {
3769
3832
  }
3770
3833
 
3771
3834
  export { AdminShellComponent, AdminSidebarWidget, BlockEditDialog, BlockInserterComponent, BlockWrapperComponent, CheckboxFieldRenderer, CollectionAccessService, CollectionCardWidget, CollectionEditPage, CollectionListPage, CollectionViewPage, DashboardPage, DateFieldRenderer, EntityFormWidget, EntityListWidget, EntitySheetService, EntityViewWidget, FeedbackService, FieldRenderer, FieldRendererRegistry, ForgotPasswordFormComponent, ForgotPasswordPage, LivePreviewComponent, LoginPage, MOMENTUM_API, MOMENTUM_API_CONTEXT, McmsThemeService, MediaLibraryPage, MediaPickerDialog, MediaPreviewComponent, MomentumApiService, MomentumAuthService, NumberFieldRenderer, PublishControlsWidget, ResetPasswordFormComponent, ResetPasswordPage, SHEET_QUERY_PARAMS, SKIP_AUTO_TOAST, SelectFieldRenderer, SetupPage, TextFieldRenderer, UploadFieldRenderer, UploadService, VersionHistoryWidget, VersionService, VisualBlockEditorComponent, adminGuard, authGuard, collectionAccessGuard, crudToastInterceptor, getFieldNodeState, getSubNode, getTitleField, guestGuard, injectHasAnyRole, injectHasRole, injectIsAdmin, injectIsAuthenticated, injectMomentumAPI, injectTypedMomentumAPI, injectUser, injectUserRole, injectVersionService, momentumAdminRoutes, provideFieldRenderer, provideMomentumAPI, provideMomentumFieldRenderers, setupGuard, unsavedChangesGuard };
3772
- export type { AdminBranding, AdminNavItem, AdminNavSection, AdminPluginRoute, AdminUser, AuthResult, AuthSession, AuthUser, BaseUser, BlockEditDialogData, BlockItem, BreadcrumbItem, CollectionPermissions, CollectionWithCount, DeleteResult, DeviceSize, DocumentStatus, DocumentVersionParsed, DraftSaveResult, Entity, EntityAction, EntityFormMode, EntityListActionEvent, EntityListBulkActionEvent, EntityListColumn, EntityListFindResult, EntitySheetResult, EntityViewActionEvent, EntityViewFieldConfig, FieldNodeState, FindByIdOptions, FindOptions, FindResult, HasUnsavedChanges, McmsTheme, MediaPickerDialogData, MediaPickerResult, MediaPreviewData, MomentumAPIContext, MomentumAPIServer, MomentumAdminBranding, MomentumAdminOptions, MomentumAdminRouteData, MomentumClientAPI, MomentumCollectionAPI, PublishResult, RestoreResult, RestoreVersionOptions, SetupStatus, StatusResult, TypedCollectionAPI, TypedFindByIdOptions, TypedFindOptions, TypedMomentumClientAPI, UploadProgress, UserContext, VersionFindOptions, VersionQueryResult, VisualEditorState };
3835
+ export type { AdminBranding, AdminNavItem, AdminNavSection, AdminPluginRoute, AdminUser, AuthResult, AuthSession, AuthUser, BaseUser, BlockEditDialogData, BlockItem, BreadcrumbItem, CollectionGroup, CollectionPermissions, CollectionWithCount, DeleteResult, DeviceSize, DocumentStatus, DocumentVersionParsed, DraftSaveResult, Entity, EntityAction, EntityFormMode, EntityListActionEvent, EntityListBulkActionEvent, EntityListColumn, EntityListFindResult, EntitySheetResult, EntityViewActionEvent, EntityViewFieldConfig, FieldNodeState, FindByIdOptions, FindOptions, FindResult, HasUnsavedChanges, McmsTheme, MediaPickerDialogData, MediaPickerResult, MediaPreviewData, MomentumAPIContext, MomentumAPIServer, MomentumAdminBranding, MomentumAdminOptions, MomentumAdminRouteData, MomentumClientAPI, MomentumCollectionAPI, PublishResult, RestoreResult, RestoreVersionOptions, SetupStatus, StatusResult, TypedCollectionAPI, TypedFindByIdOptions, TypedFindOptions, TypedMomentumClientAPI, UploadProgress, UserContext, VersionFindOptions, VersionQueryResult, VisualEditorState };