@ardimedia/angular-portal-azure 0.3.25 → 0.3.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@ardimedia/angular-portal-azure",
3
- "version": "0.3.25",
3
+ "version": "0.3.27",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.1.0",
6
- "@angular/core": "^21.1.0"
6
+ "@angular/core": "^21.1.0",
7
+ "@angular/forms": "^21.1.0"
7
8
  },
8
9
  "dependencies": {
9
10
  "tslib": "^2.3.0"
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { WritableSignal, Type, EnvironmentProviders } from '@angular/core';
2
+ import { WritableSignal, Type, EnvironmentProviders, InjectionToken, AfterContentInit, OnDestroy } from '@angular/core';
3
3
  import * as _ardimedia_angular_portal_azure from '@ardimedia/angular-portal-azure';
4
4
 
5
5
  /**
@@ -117,6 +117,7 @@ interface PortalLabels {
117
117
  settings: string;
118
118
  language: string;
119
119
  appearance: string;
120
+ unsavedChangesConfirm: string;
120
121
  }
121
122
  /** Language preset definition for the built-in language registry. */
122
123
  interface LanguagePreset {
@@ -186,6 +187,7 @@ interface BladeDataLifecycle<T> {
186
187
  onExecuted?: () => void;
187
188
  onExecuteError?: (ex: ApiException) => void;
188
189
  isFormValid?: () => boolean;
190
+ isDirty?: () => boolean;
189
191
  }
190
192
  /**
191
193
  * Extended blade definition for data-driven blades with CRUD operations.
@@ -510,6 +512,31 @@ declare class PortalService {
510
512
  declare class BladeService {
511
513
  private readonly portal;
512
514
  private readonly registry;
515
+ /**
516
+ * Unsaved-changes guard registry: blade path -> predicate returning true when the blade has
517
+ * unsaved edits. Populated by apa-blade-detail (from the projected NgForm). Consulted before a
518
+ * blade is closed/replaced or the page is left, so the user can confirm discarding changes.
519
+ * Message can be localised via PortalLabels.unsavedChangesConfirm; the navigation flow is
520
+ * synchronous, so a synchronous window.confirm is used.
521
+ */
522
+ private readonly dirtyChecks;
523
+ /** Optional override for the confirmation message (defaults to the de-CH label). */
524
+ unsavedChangesMessage: string;
525
+ constructor();
526
+ /** Register a blade's unsaved-changes predicate (called by apa-blade-detail). */
527
+ registerDirtyCheck(path: string, isDirty: () => boolean): void;
528
+ /** Remove a blade's unsaved-changes predicate (called when the detail is destroyed). */
529
+ unregisterDirtyCheck(path: string): void;
530
+ private isPathDirty;
531
+ private anyDirty;
532
+ /**
533
+ * Returns true if it's OK to proceed with removing the given blade paths: none of them is dirty,
534
+ * or the user confirmed discarding the changes. Shows one confirmation regardless of how many
535
+ * dirty blades are affected.
536
+ */
537
+ private mayDiscard;
538
+ /** Drop dirty-check entries for paths that are no longer open. */
539
+ private pruneDirtyChecks;
513
540
  /**
514
541
  * Set the first blade (e.g., when opening a top-level item from a tile).
515
542
  * Clears all existing blades, hides panorama, and adds the new blade.
@@ -540,14 +567,14 @@ declare class BladeService {
540
567
  *
541
568
  * Ported from AreaBlades.clearPath() in v0.2.346.
542
569
  */
543
- clearPath(path: string): void;
570
+ clearPath(path: string): boolean;
544
571
  /**
545
572
  * Remove all blades AFTER a given path (keeps the blade itself).
546
573
  * Used for cascade close when a blade opens a child.
547
574
  *
548
575
  * Ported from AreaBlades.clearChild() in v0.2.346.
549
576
  */
550
- clearChild(path: string): void;
577
+ clearChild(path: string): boolean;
551
578
  /**
552
579
  * Remove blades at and beyond a specific 1-based level.
553
580
  * Ported from AreaBlades.clearLevel() in v0.2.346.
@@ -646,6 +673,7 @@ declare class BladeRouterService {
646
673
  private readonly portal;
647
674
  private readonly registry;
648
675
  private readonly destroyRef;
676
+ private readonly config;
649
677
  private _syncingFromUrl;
650
678
  private _initialRestoreDone;
651
679
  constructor();
@@ -688,6 +716,12 @@ declare class BladeRouterService {
688
716
  private extractLegacyBladesParam;
689
717
  /** Handle legacy ?blades= URL by redirecting to new path format */
690
718
  private handleLegacyUrl;
719
+ /**
720
+ * Return the effective route prefix. If a prefix was configured via
721
+ * `provideBladeRouter({ prefix })`, use it (including empty string).
722
+ * Otherwise fall back to dynamically reading the first URL segment.
723
+ */
724
+ private getEffectivePrefix;
691
725
  static ɵfac: i0.ɵɵFactoryDeclaration<BladeRouterService, never>;
692
726
  static ɵprov: i0.ɵɵInjectableDeclaration<BladeRouterService>;
693
727
  }
@@ -712,6 +746,19 @@ declare class BladeRouterService {
712
746
  */
713
747
  declare function providePortalAzure(config: PortalConfig): EnvironmentProviders;
714
748
 
749
+ /** Configuration for `provideBladeRouter()`. */
750
+ interface BladeRouterConfig {
751
+ /**
752
+ * Fixed URL prefix for blade path segments.
753
+ *
754
+ * - When omitted, the prefix is read dynamically from the first URL segment (default).
755
+ * - When set to a non-empty string (e.g. `'app'`), that string is used as the fixed prefix.
756
+ * - When set to `''` (empty string), blade paths are encoded directly at the URL root with no prefix.
757
+ */
758
+ prefix?: string;
759
+ }
760
+ /** @internal */
761
+ declare const BLADE_ROUTER_CONFIG: InjectionToken<BladeRouterConfig>;
715
762
  /**
716
763
  * Enables opt-in URL synchronization for the blade stack.
717
764
  *
@@ -726,12 +773,15 @@ declare function providePortalAzure(config: PortalConfig): EnvironmentProviders;
726
773
  * };
727
774
  * ```
728
775
  *
729
- * When enabled, blade paths sync to the URL as a query parameter:
730
- * `?blades=customers,customers/list,customers/1`
776
+ * Optionally pass a config to set a fixed route prefix:
777
+ * ```typescript
778
+ * provideBladeRouter({ prefix: 'app' }) // → /app/customers/list
779
+ * provideBladeRouter({ prefix: '' }) // → /customers/list (no prefix)
780
+ * ```
731
781
  *
732
782
  * Without this provider, blade navigation remains purely in-memory.
733
783
  */
734
- declare function provideBladeRouter(): EnvironmentProviders;
784
+ declare function provideBladeRouter(config?: BladeRouterConfig): EnvironmentProviders;
735
785
 
736
786
  /**
737
787
  * Individual dashboard tile.
@@ -878,15 +928,21 @@ declare class BladeComponent {
878
928
  *
879
929
  * Usage:
880
930
  * ```html
931
+ * <!-- Default: each component is wrapped in <apa-blade> -->
881
932
  * <apa-blade-host />
933
+ *
934
+ * <!-- No wrapper: components render directly (they manage their own blade chrome) -->
935
+ * <apa-blade-host [wrapBlade]="false" />
882
936
  * ```
883
937
  */
884
938
  declare class BladeHostComponent {
939
+ /** Whether to wrap each component in an `<apa-blade>` element. Default: true. */
940
+ readonly wrapBlade: i0.InputSignal<boolean>;
885
941
  protected readonly portal: PortalService;
886
942
  private readonly registry;
887
943
  getComponent(path: string): i0.Type<unknown> | null;
888
944
  static ɵfac: i0.ɵɵFactoryDeclaration<BladeHostComponent, never>;
889
- static ɵcmp: i0.ɵɵComponentDeclaration<BladeHostComponent, "apa-blade-host", never, {}, {}, never, never, true, never>;
945
+ static ɵcmp: i0.ɵɵComponentDeclaration<BladeHostComponent, "apa-blade-host", never, { "wrapBlade": { "alias": "wrapBlade"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
890
946
  }
891
947
 
892
948
  /**
@@ -973,10 +1029,15 @@ declare class BladeGridComponent {
973
1029
  * </apa-blade>
974
1030
  * ```
975
1031
  */
976
- declare class BladeDetailComponent {
1032
+ declare class BladeDetailComponent implements AfterContentInit, OnDestroy {
977
1033
  readonly blade: i0.InputSignal<BladeDataDefinition<any>>;
1034
+ private readonly bladeService;
1035
+ /** The template-driven form projected into this detail, if any (auto-discovered). */
1036
+ private readonly form;
1037
+ ngAfterContentInit(): void;
1038
+ ngOnDestroy(): void;
978
1039
  static ɵfac: i0.ɵɵFactoryDeclaration<BladeDetailComponent, never>;
979
- static ɵcmp: i0.ɵɵComponentDeclaration<BladeDetailComponent, "apa-blade-detail", never, { "blade": { "alias": "blade"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1040
+ static ɵcmp: i0.ɵɵComponentDeclaration<BladeDetailComponent, "apa-blade-detail", never, { "blade": { "alias": "blade"; "required": true; "isSignal": true; }; }, {}, ["form"], ["*"], true, never>;
980
1041
  }
981
1042
  /**
982
1043
  * Create standard detail blade commands (new, save, delete, cancel).
@@ -1057,5 +1118,5 @@ declare class SidebarComponent {
1057
1118
  static ɵcmp: i0.ɵɵComponentDeclaration<SidebarComponent, "apa-sidebar", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "collapsedWidth": { "alias": "collapsedWidth"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1058
1119
  }
1059
1120
 
1060
- export { AvatarMenuComponent, BladeComponent, BladeDetailComponent, BladeGridComponent, BladeHostComponent, BladeNavComponent, BladeRegistry, BladeRouterService, BladeService, CommandBarComponent, DEFAULT_LABELS, LABELS_DE_CH, LABELS_DE_DE, LABELS_EN, LABELS_ES, LABELS_FR, LABELS_IT, LANGUAGE_PRESETS, NotificationPanelComponent, PanoramaComponent, PortalLayoutComponent, PortalService, SidebarComponent, TILE_DIMENSIONS, TileComponent, TileSize, clearStatusBar, createAvatarMenu, createBlade, createCommand, createDataBlade, createDetailCommands, createNavItem, createNotificationPanel, createPanorama, createTile, executeDeleteItem, executeLoadItem, executeLoadItems, executeSaveItem, filterItems, getUserDisplayName, layoutTiles, nextBladeUid, provideBladeRouter, providePortalAzure, registerLanguagePreset, statusBarError, statusBarInfo, statusBarSuccess };
1061
- export type { AddBladeEventArgs, ApiException, AvatarMenuDefinition, AvatarMenuItem, BladeCommand, BladeDataDefinition, BladeDataLifecycle, BladeDefinition, BladeNavItem, BladeParameter, BladeRegistryEntry, LanguagePreset, NotificationDefinition, NotificationLifecycle, PanoramaDefinition, PortalConfig, PortalLabels, PositionedTile, StandardCommandKey, StatusBarState, StatusBarStyle, TileDefinition, UserAccount };
1121
+ export { AvatarMenuComponent, BLADE_ROUTER_CONFIG, BladeComponent, BladeDetailComponent, BladeGridComponent, BladeHostComponent, BladeNavComponent, BladeRegistry, BladeRouterService, BladeService, CommandBarComponent, DEFAULT_LABELS, LABELS_DE_CH, LABELS_DE_DE, LABELS_EN, LABELS_ES, LABELS_FR, LABELS_IT, LANGUAGE_PRESETS, NotificationPanelComponent, PanoramaComponent, PortalLayoutComponent, PortalService, SidebarComponent, TILE_DIMENSIONS, TileComponent, TileSize, clearStatusBar, createAvatarMenu, createBlade, createCommand, createDataBlade, createDetailCommands, createNavItem, createNotificationPanel, createPanorama, createTile, executeDeleteItem, executeLoadItem, executeLoadItems, executeSaveItem, filterItems, getUserDisplayName, layoutTiles, nextBladeUid, provideBladeRouter, providePortalAzure, registerLanguagePreset, statusBarError, statusBarInfo, statusBarSuccess };
1122
+ export type { AddBladeEventArgs, ApiException, AvatarMenuDefinition, AvatarMenuItem, BladeCommand, BladeDataDefinition, BladeDataLifecycle, BladeDefinition, BladeNavItem, BladeParameter, BladeRegistryEntry, BladeRouterConfig, LanguagePreset, NotificationDefinition, NotificationLifecycle, PanoramaDefinition, PortalConfig, PortalLabels, PositionedTile, StandardCommandKey, StatusBarState, StatusBarStyle, TileDefinition, UserAccount };