valtech-components 2.0.717 → 2.0.719

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.
@@ -50,7 +50,7 @@ import 'prismjs/components/prism-json';
50
50
  * Current version of valtech-components.
51
51
  * This is automatically updated during the publish process.
52
52
  */
53
- const VERSION = '2.0.717';
53
+ const VERSION = '2.0.719';
54
54
 
55
55
  /**
56
56
  * Servicio para gestionar presets de componentes.
@@ -3911,6 +3911,9 @@ const VALTECH_DEFAULT_CONTENT = {
3911
3911
  goodMorning: 'Buenos días',
3912
3912
  goodAfternoon: 'Buenas tardes',
3913
3913
  goodEvening: 'Buenas noches',
3914
+ // Auth — confirmación cierre de sesión
3915
+ logoutConfirmTitle: 'Cerrar sesión',
3916
+ logoutConfirmMessage: '¿Seguro que deseas cerrar sesión?',
3914
3917
  // Idiomas
3915
3918
  languageName_es: 'Español',
3916
3919
  languageName_en: 'English',
@@ -4055,6 +4058,9 @@ const VALTECH_DEFAULT_CONTENT = {
4055
4058
  goodMorning: 'Good morning',
4056
4059
  goodAfternoon: 'Good afternoon',
4057
4060
  goodEvening: 'Good evening',
4061
+ // Auth — sign out confirmation
4062
+ logoutConfirmTitle: 'Sign out',
4063
+ logoutConfirmMessage: 'Are you sure you want to sign out?',
4058
4064
  // Languages
4059
4065
  languageName_es: 'Español',
4060
4066
  languageName_en: 'English',
@@ -16203,39 +16209,48 @@ class LinksAccordionComponent {
16203
16209
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LinksAccordionComponent, isStandalone: true, selector: "val-links-accordion", inputs: { props: "props" }, outputs: { navigate: "navigate" }, viewQueries: [{ propertyName: "accordionGroup", first: true, predicate: ["accordionGroup"], descendants: true }], ngImport: i0, template: `
16204
16210
  <div class="links-accordion">
16205
16211
  <ion-accordion-group #accordionGroup>
16206
- <ion-accordion
16207
- *ngFor="let section of props.sections; let i = index"
16208
- [value]="getSectionValue(section, i)"
16209
- [toggleIcon]="section.links?.length ? 'chevron-down-outline' : ''"
16210
- [readonly]="!section.links?.length"
16211
- >
16212
+ <ng-container *ngFor="let section of props.sections; let i = index">
16213
+ <!-- Direct-link section: route + no children -->
16212
16214
  <ion-item
16213
- slot="header"
16215
+ *ngIf="section.route && !section.links?.length"
16216
+ class="direct-link"
16214
16217
  color="light"
16215
16218
  [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16216
- (click)="section.route ? onLinkClick(section.route, $event) : null"
16217
- [button]="!!section.route"
16219
+ (click)="onLinkClick(section.route!, $event)"
16220
+ button
16218
16221
  lines="none"
16219
16222
  >
16220
16223
  <ion-label class="accordion-label">{{ getSectionTitle(section) }}</ion-label>
16221
16224
  </ion-item>
16222
- <div
16223
- slot="content"
16224
- [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16225
+
16226
+ <!-- Accordion section: has children -->
16227
+ <ion-accordion
16225
16228
  *ngIf="section.links?.length"
16229
+ [value]="getSectionValue(section, i)"
16230
+ toggleIcon="chevron-down-outline"
16226
16231
  >
16227
- <ion-list lines="none">
16228
- <ion-item
16229
- *ngFor="let link of section.links"
16230
- [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16231
- (click)="onLinkClick(link.route, $event)"
16232
- button
16233
- >
16234
- <ion-label class="accordion-item-label">{{ getLinkText(link) }}</ion-label>
16235
- </ion-item>
16236
- </ion-list>
16237
- </div>
16238
- </ion-accordion>
16232
+ <ion-item
16233
+ slot="header"
16234
+ color="light"
16235
+ [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16236
+ lines="none"
16237
+ >
16238
+ <ion-label class="accordion-label">{{ getSectionTitle(section) }}</ion-label>
16239
+ </ion-item>
16240
+ <div slot="content" [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }">
16241
+ <ion-list lines="none">
16242
+ <ion-item
16243
+ *ngFor="let link of section.links"
16244
+ [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16245
+ (click)="onLinkClick(link.route, $event)"
16246
+ button
16247
+ >
16248
+ <ion-label class="accordion-item-label">{{ getLinkText(link) }}</ion-label>
16249
+ </ion-item>
16250
+ </ion-list>
16251
+ </div>
16252
+ </ion-accordion>
16253
+ </ng-container>
16239
16254
  </ion-accordion-group>
16240
16255
  </div>
16241
16256
  `, isInline: true, styles: [".links-accordion .accordion-label{font-size:1.3rem}.links-accordion .accordion-item-label{font-size:1.1rem}.links-accordion ion-item{--background: var(--ion-color-light-tint)}.links-accordion ion-accordion{background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }] }); }
@@ -16245,39 +16260,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16245
16260
  args: [{ selector: 'val-links-accordion', standalone: true, imports: [CommonModule, IonAccordionGroup, IonAccordion, IonItem, IonLabel, IonList], template: `
16246
16261
  <div class="links-accordion">
16247
16262
  <ion-accordion-group #accordionGroup>
16248
- <ion-accordion
16249
- *ngFor="let section of props.sections; let i = index"
16250
- [value]="getSectionValue(section, i)"
16251
- [toggleIcon]="section.links?.length ? 'chevron-down-outline' : ''"
16252
- [readonly]="!section.links?.length"
16253
- >
16263
+ <ng-container *ngFor="let section of props.sections; let i = index">
16264
+ <!-- Direct-link section: route + no children -->
16254
16265
  <ion-item
16255
- slot="header"
16266
+ *ngIf="section.route && !section.links?.length"
16267
+ class="direct-link"
16256
16268
  color="light"
16257
16269
  [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16258
- (click)="section.route ? onLinkClick(section.route, $event) : null"
16259
- [button]="!!section.route"
16270
+ (click)="onLinkClick(section.route!, $event)"
16271
+ button
16260
16272
  lines="none"
16261
16273
  >
16262
16274
  <ion-label class="accordion-label">{{ getSectionTitle(section) }}</ion-label>
16263
16275
  </ion-item>
16264
- <div
16265
- slot="content"
16266
- [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16276
+
16277
+ <!-- Accordion section: has children -->
16278
+ <ion-accordion
16267
16279
  *ngIf="section.links?.length"
16280
+ [value]="getSectionValue(section, i)"
16281
+ toggleIcon="chevron-down-outline"
16268
16282
  >
16269
- <ion-list lines="none">
16270
- <ion-item
16271
- *ngFor="let link of section.links"
16272
- [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16273
- (click)="onLinkClick(link.route, $event)"
16274
- button
16275
- >
16276
- <ion-label class="accordion-item-label">{{ getLinkText(link) }}</ion-label>
16277
- </ion-item>
16278
- </ion-list>
16279
- </div>
16280
- </ion-accordion>
16283
+ <ion-item
16284
+ slot="header"
16285
+ color="light"
16286
+ [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16287
+ lines="none"
16288
+ >
16289
+ <ion-label class="accordion-label">{{ getSectionTitle(section) }}</ion-label>
16290
+ </ion-item>
16291
+ <div slot="content" [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }">
16292
+ <ion-list lines="none">
16293
+ <ion-item
16294
+ *ngFor="let link of section.links"
16295
+ [ngStyle]="{ background: props.backgroundColor || 'var(--ion-background-color)' }"
16296
+ (click)="onLinkClick(link.route, $event)"
16297
+ button
16298
+ >
16299
+ <ion-label class="accordion-item-label">{{ getLinkText(link) }}</ion-label>
16300
+ </ion-item>
16301
+ </ion-list>
16302
+ </div>
16303
+ </ion-accordion>
16304
+ </ng-container>
16281
16305
  </ion-accordion-group>
16282
16306
  </div>
16283
16307
  `, styles: [".links-accordion .accordion-label{font-size:1.3rem}.links-accordion .accordion-item-label{font-size:1.1rem}.links-accordion ion-item{--background: var(--ion-color-light-tint)}.links-accordion ion-accordion{background:transparent}\n"] }]
@@ -28719,6 +28743,196 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
28719
28743
  args: [VALTECH_AUTH_CONFIG]
28720
28744
  }] }, { type: i1$8.HttpClient }, { type: i0.NgZone }] });
28721
28745
 
28746
+ /**
28747
+ * Default confirmation dialog options.
28748
+ */
28749
+ const DEFAULT_CONFIRM_BUTTON = {
28750
+ text: 'Confirm',
28751
+ role: 'confirm',
28752
+ color: 'primary',
28753
+ };
28754
+ const DEFAULT_CANCEL_BUTTON = {
28755
+ text: 'Cancel',
28756
+ role: 'cancel',
28757
+ color: 'medium',
28758
+ };
28759
+
28760
+ /**
28761
+ * Service for displaying confirmation dialogs.
28762
+ *
28763
+ * @example Basic usage
28764
+ * const result = await confirmationService.confirm({
28765
+ * title: 'Delete Item',
28766
+ * message: 'Are you sure you want to delete this item?',
28767
+ * });
28768
+ *
28769
+ * if (result.confirmed) {
28770
+ * // User confirmed
28771
+ * }
28772
+ *
28773
+ * @example Custom buttons
28774
+ * const result = await confirmationService.confirm({
28775
+ * title: 'Save Changes',
28776
+ * message: 'Do you want to save your changes before leaving?',
28777
+ * confirmButton: { text: 'Save', color: 'success' },
28778
+ * cancelButton: { text: 'Discard', color: 'danger' },
28779
+ * extraButtons: [{ text: 'Cancel', role: 'cancel' }]
28780
+ * });
28781
+ *
28782
+ * @example Destructive action
28783
+ * const result = await confirmationService.confirmDestructive({
28784
+ * title: 'Delete Account',
28785
+ * message: 'This action cannot be undone. Are you sure?',
28786
+ * });
28787
+ */
28788
+ class ConfirmationDialogService {
28789
+ constructor() {
28790
+ this.alertController = inject(AlertController);
28791
+ }
28792
+ /**
28793
+ * Shows a confirmation dialog and returns the result.
28794
+ * @param options - Configuration for the dialog
28795
+ * @returns Promise resolving to the confirmation result
28796
+ */
28797
+ async confirm(options) {
28798
+ const buttons = this.buildButtons(options);
28799
+ const alert = await this.alertController.create({
28800
+ header: options.title,
28801
+ subHeader: options.subHeader,
28802
+ message: options.message,
28803
+ buttons,
28804
+ backdropDismiss: options.backdropDismiss ?? false,
28805
+ cssClass: options.cssClass,
28806
+ mode: options.mode,
28807
+ translucent: options.translucent ?? false,
28808
+ animated: options.animated ?? true,
28809
+ });
28810
+ await alert.present();
28811
+ const { role, data } = await alert.onDidDismiss();
28812
+ return {
28813
+ confirmed: role === 'confirm',
28814
+ role,
28815
+ data,
28816
+ };
28817
+ }
28818
+ /**
28819
+ * Shows a simple confirmation dialog with default buttons.
28820
+ * @param title - Dialog title
28821
+ * @param message - Dialog message
28822
+ * @returns Promise resolving to true if confirmed, false otherwise
28823
+ */
28824
+ async confirmSimple(title, message) {
28825
+ const result = await this.confirm({ title, message });
28826
+ return result.confirmed;
28827
+ }
28828
+ /**
28829
+ * Shows a destructive action confirmation with red confirm button.
28830
+ * @param options - Configuration for the dialog
28831
+ * @returns Promise resolving to the confirmation result
28832
+ */
28833
+ async confirmDestructive(options) {
28834
+ return this.confirm({
28835
+ ...options,
28836
+ confirmButton: {
28837
+ text: options.confirmButton?.text || 'Delete',
28838
+ role: 'destructive',
28839
+ color: 'danger',
28840
+ cssClass: 'destructive-button',
28841
+ ...options.confirmButton,
28842
+ },
28843
+ });
28844
+ }
28845
+ /**
28846
+ * Shows an info alert with just an OK button.
28847
+ * @param title - Alert title
28848
+ * @param message - Alert message
28849
+ */
28850
+ async alert(title, message) {
28851
+ const alert = await this.alertController.create({
28852
+ header: title,
28853
+ message,
28854
+ buttons: [{ text: 'OK', role: 'confirm' }],
28855
+ });
28856
+ await alert.present();
28857
+ await alert.onDidDismiss();
28858
+ }
28859
+ /**
28860
+ * Shows a three-option dialog (Save, Discard, Cancel).
28861
+ * Common for unsaved changes scenarios.
28862
+ * @param title - Dialog title
28863
+ * @param message - Dialog message
28864
+ * @returns Promise resolving to 'save' | 'discard' | 'cancel'
28865
+ */
28866
+ async confirmSaveDiscard(title, message) {
28867
+ const alert = await this.alertController.create({
28868
+ header: title,
28869
+ message,
28870
+ backdropDismiss: false,
28871
+ buttons: [
28872
+ {
28873
+ text: 'Cancel',
28874
+ role: 'cancel',
28875
+ },
28876
+ {
28877
+ text: 'Discard',
28878
+ role: 'destructive',
28879
+ cssClass: 'text-danger',
28880
+ },
28881
+ {
28882
+ text: 'Save',
28883
+ role: 'confirm',
28884
+ },
28885
+ ],
28886
+ });
28887
+ await alert.present();
28888
+ const { role } = await alert.onDidDismiss();
28889
+ if (role === 'confirm')
28890
+ return 'save';
28891
+ if (role === 'destructive')
28892
+ return 'discard';
28893
+ return 'cancel';
28894
+ }
28895
+ buildButtons(options) {
28896
+ const buttons = [];
28897
+ // Cancel button
28898
+ const cancelBtn = options.cancelButton || DEFAULT_CANCEL_BUTTON;
28899
+ buttons.push({
28900
+ text: cancelBtn.text,
28901
+ role: cancelBtn.role || 'cancel',
28902
+ cssClass: cancelBtn.cssClass || `button-${cancelBtn.color || 'medium'}`,
28903
+ handler: cancelBtn.handler,
28904
+ });
28905
+ // Extra buttons (if any)
28906
+ if (options.extraButtons) {
28907
+ options.extraButtons.forEach((btn) => {
28908
+ buttons.push({
28909
+ text: btn.text,
28910
+ role: btn.role,
28911
+ cssClass: btn.cssClass || `button-${btn.color || 'medium'}`,
28912
+ handler: btn.handler,
28913
+ });
28914
+ });
28915
+ }
28916
+ // Confirm button
28917
+ const confirmBtn = options.confirmButton || DEFAULT_CONFIRM_BUTTON;
28918
+ buttons.push({
28919
+ text: confirmBtn.text,
28920
+ role: confirmBtn.role || 'confirm',
28921
+ cssClass: confirmBtn.cssClass || `button-${confirmBtn.color || 'primary'}`,
28922
+ handler: confirmBtn.handler,
28923
+ });
28924
+ return buttons;
28925
+ }
28926
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
28927
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, providedIn: 'root' }); }
28928
+ }
28929
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, decorators: [{
28930
+ type: Injectable,
28931
+ args: [{
28932
+ providedIn: 'root',
28933
+ }]
28934
+ }] });
28935
+
28722
28936
  /**
28723
28937
  * Servicio principal de autenticación.
28724
28938
  *
@@ -28742,7 +28956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
28742
28956
  * ```
28743
28957
  */
28744
28958
  class AuthService {
28745
- constructor(config, http, router, stateService, tokenService, storageService, syncService, firebaseService, oauthService, messagingService, i18nService) {
28959
+ constructor(config, http, router, stateService, tokenService, storageService, syncService, firebaseService, oauthService, messagingService, i18nService, confirmationService) {
28746
28960
  this.config = config;
28747
28961
  this.http = http;
28748
28962
  this.router = router;
@@ -28754,6 +28968,7 @@ class AuthService {
28754
28968
  this.oauthService = oauthService;
28755
28969
  this.messagingService = messagingService;
28756
28970
  this.i18nService = i18nService;
28971
+ this.confirmationService = confirmationService;
28757
28972
  // Timer para refresh proactivo
28758
28973
  this.refreshTimerId = null;
28759
28974
  this.syncSubscription = null;
@@ -29079,6 +29294,34 @@ class AuthService {
29079
29294
  tokenType: 'Bearer',
29080
29295
  });
29081
29296
  }
29297
+ /**
29298
+ * Cierra sesión tras pedir confirmación al usuario.
29299
+ *
29300
+ * Muestra un diálogo nativo (estilo destructivo). Si el usuario confirma,
29301
+ * ejecuta `logout()`. Si cancela, no pasa nada.
29302
+ *
29303
+ * Texto por defecto desde `_global` i18n: `logoutConfirmTitle`,
29304
+ * `logoutConfirmMessage`, `logout`, `cancel`. Override via `opts`.
29305
+ *
29306
+ * @returns true si el usuario confirmó (logout ejecutado), false si canceló.
29307
+ *
29308
+ * @example
29309
+ * onLogoutClick() { this.auth.logoutWithConfirmation(); }
29310
+ */
29311
+ async logoutWithConfirmation(opts) {
29312
+ const t = (key, fallback) => this.i18nService?.t(key) || fallback;
29313
+ const result = await this.confirmationService.confirmDestructive({
29314
+ title: opts?.title ?? t('logoutConfirmTitle', 'Cerrar sesión'),
29315
+ message: opts?.message ?? t('logoutConfirmMessage', '¿Seguro que deseas cerrar sesión?'),
29316
+ confirmButton: { text: opts?.confirmText ?? t('logout', 'Cerrar sesión') },
29317
+ cancelButton: { text: opts?.cancelText ?? t('cancel', 'Cancelar') },
29318
+ });
29319
+ if (result.confirmed) {
29320
+ await this.logout();
29321
+ return true;
29322
+ }
29323
+ return false;
29324
+ }
29082
29325
  /**
29083
29326
  * Cierra sesión.
29084
29327
  */
@@ -29793,7 +30036,7 @@ class AuthService {
29793
30036
  }
29794
30037
  return { platform: 'web', browser, os };
29795
30038
  }
29796
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1$8.HttpClient }, { token: i1$1.Router }, { token: AuthStateService }, { token: TokenService }, { token: AuthStorageService }, { token: AuthSyncService }, { token: FirebaseService }, { token: OAuthService }, { token: MessagingService, optional: true }, { token: I18nService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
30039
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1$8.HttpClient }, { token: i1$1.Router }, { token: AuthStateService }, { token: TokenService }, { token: AuthStorageService }, { token: AuthSyncService }, { token: FirebaseService }, { token: OAuthService }, { token: MessagingService, optional: true }, { token: I18nService, optional: true }, { token: ConfirmationDialogService }], target: i0.ɵɵFactoryTarget.Injectable }); }
29797
30040
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthService, providedIn: 'root' }); }
29798
30041
  }
29799
30042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthService, decorators: [{
@@ -29806,7 +30049,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
29806
30049
  type: Optional
29807
30050
  }] }, { type: I18nService, decorators: [{
29808
30051
  type: Optional
29809
- }] }] });
30052
+ }] }, { type: ConfirmationDialogService }] });
29810
30053
 
29811
30054
  // Control de estado de refresco (singleton a nivel de módulo)
29812
30055
  let isRefreshing = false;
@@ -33820,196 +34063,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
33820
34063
  // ValtechConfig and LangProvider have been removed in v3.0.0
33821
34064
  // Use LocaleService for language management instead
33822
34065
 
33823
- /**
33824
- * Default confirmation dialog options.
33825
- */
33826
- const DEFAULT_CONFIRM_BUTTON = {
33827
- text: 'Confirm',
33828
- role: 'confirm',
33829
- color: 'primary',
33830
- };
33831
- const DEFAULT_CANCEL_BUTTON = {
33832
- text: 'Cancel',
33833
- role: 'cancel',
33834
- color: 'medium',
33835
- };
33836
-
33837
- /**
33838
- * Service for displaying confirmation dialogs.
33839
- *
33840
- * @example Basic usage
33841
- * const result = await confirmationService.confirm({
33842
- * title: 'Delete Item',
33843
- * message: 'Are you sure you want to delete this item?',
33844
- * });
33845
- *
33846
- * if (result.confirmed) {
33847
- * // User confirmed
33848
- * }
33849
- *
33850
- * @example Custom buttons
33851
- * const result = await confirmationService.confirm({
33852
- * title: 'Save Changes',
33853
- * message: 'Do you want to save your changes before leaving?',
33854
- * confirmButton: { text: 'Save', color: 'success' },
33855
- * cancelButton: { text: 'Discard', color: 'danger' },
33856
- * extraButtons: [{ text: 'Cancel', role: 'cancel' }]
33857
- * });
33858
- *
33859
- * @example Destructive action
33860
- * const result = await confirmationService.confirmDestructive({
33861
- * title: 'Delete Account',
33862
- * message: 'This action cannot be undone. Are you sure?',
33863
- * });
33864
- */
33865
- class ConfirmationDialogService {
33866
- constructor() {
33867
- this.alertController = inject(AlertController);
33868
- }
33869
- /**
33870
- * Shows a confirmation dialog and returns the result.
33871
- * @param options - Configuration for the dialog
33872
- * @returns Promise resolving to the confirmation result
33873
- */
33874
- async confirm(options) {
33875
- const buttons = this.buildButtons(options);
33876
- const alert = await this.alertController.create({
33877
- header: options.title,
33878
- subHeader: options.subHeader,
33879
- message: options.message,
33880
- buttons,
33881
- backdropDismiss: options.backdropDismiss ?? false,
33882
- cssClass: options.cssClass,
33883
- mode: options.mode,
33884
- translucent: options.translucent ?? false,
33885
- animated: options.animated ?? true,
33886
- });
33887
- await alert.present();
33888
- const { role, data } = await alert.onDidDismiss();
33889
- return {
33890
- confirmed: role === 'confirm',
33891
- role,
33892
- data,
33893
- };
33894
- }
33895
- /**
33896
- * Shows a simple confirmation dialog with default buttons.
33897
- * @param title - Dialog title
33898
- * @param message - Dialog message
33899
- * @returns Promise resolving to true if confirmed, false otherwise
33900
- */
33901
- async confirmSimple(title, message) {
33902
- const result = await this.confirm({ title, message });
33903
- return result.confirmed;
33904
- }
33905
- /**
33906
- * Shows a destructive action confirmation with red confirm button.
33907
- * @param options - Configuration for the dialog
33908
- * @returns Promise resolving to the confirmation result
33909
- */
33910
- async confirmDestructive(options) {
33911
- return this.confirm({
33912
- ...options,
33913
- confirmButton: {
33914
- text: options.confirmButton?.text || 'Delete',
33915
- role: 'destructive',
33916
- color: 'danger',
33917
- cssClass: 'destructive-button',
33918
- ...options.confirmButton,
33919
- },
33920
- });
33921
- }
33922
- /**
33923
- * Shows an info alert with just an OK button.
33924
- * @param title - Alert title
33925
- * @param message - Alert message
33926
- */
33927
- async alert(title, message) {
33928
- const alert = await this.alertController.create({
33929
- header: title,
33930
- message,
33931
- buttons: [{ text: 'OK', role: 'confirm' }],
33932
- });
33933
- await alert.present();
33934
- await alert.onDidDismiss();
33935
- }
33936
- /**
33937
- * Shows a three-option dialog (Save, Discard, Cancel).
33938
- * Common for unsaved changes scenarios.
33939
- * @param title - Dialog title
33940
- * @param message - Dialog message
33941
- * @returns Promise resolving to 'save' | 'discard' | 'cancel'
33942
- */
33943
- async confirmSaveDiscard(title, message) {
33944
- const alert = await this.alertController.create({
33945
- header: title,
33946
- message,
33947
- backdropDismiss: false,
33948
- buttons: [
33949
- {
33950
- text: 'Cancel',
33951
- role: 'cancel',
33952
- },
33953
- {
33954
- text: 'Discard',
33955
- role: 'destructive',
33956
- cssClass: 'text-danger',
33957
- },
33958
- {
33959
- text: 'Save',
33960
- role: 'confirm',
33961
- },
33962
- ],
33963
- });
33964
- await alert.present();
33965
- const { role } = await alert.onDidDismiss();
33966
- if (role === 'confirm')
33967
- return 'save';
33968
- if (role === 'destructive')
33969
- return 'discard';
33970
- return 'cancel';
33971
- }
33972
- buildButtons(options) {
33973
- const buttons = [];
33974
- // Cancel button
33975
- const cancelBtn = options.cancelButton || DEFAULT_CANCEL_BUTTON;
33976
- buttons.push({
33977
- text: cancelBtn.text,
33978
- role: cancelBtn.role || 'cancel',
33979
- cssClass: cancelBtn.cssClass || `button-${cancelBtn.color || 'medium'}`,
33980
- handler: cancelBtn.handler,
33981
- });
33982
- // Extra buttons (if any)
33983
- if (options.extraButtons) {
33984
- options.extraButtons.forEach((btn) => {
33985
- buttons.push({
33986
- text: btn.text,
33987
- role: btn.role,
33988
- cssClass: btn.cssClass || `button-${btn.color || 'medium'}`,
33989
- handler: btn.handler,
33990
- });
33991
- });
33992
- }
33993
- // Confirm button
33994
- const confirmBtn = options.confirmButton || DEFAULT_CONFIRM_BUTTON;
33995
- buttons.push({
33996
- text: confirmBtn.text,
33997
- role: confirmBtn.role || 'confirm',
33998
- cssClass: confirmBtn.cssClass || `button-${confirmBtn.color || 'primary'}`,
33999
- handler: confirmBtn.handler,
34000
- });
34001
- return buttons;
34002
- }
34003
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
34004
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, providedIn: 'root' }); }
34005
- }
34006
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConfirmationDialogService, decorators: [{
34007
- type: Injectable,
34008
- args: [{
34009
- providedIn: 'root',
34010
- }]
34011
- }] });
34012
-
34013
34066
  /**
34014
34067
  * Default modal sizes.
34015
34068
  */