ngx-com 0.0.3 → 0.0.5

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 (33) hide show
  1. package/fesm2022/ngx-com-components-avatar.mjs +772 -0
  2. package/fesm2022/ngx-com-components-avatar.mjs.map +1 -0
  3. package/fesm2022/ngx-com-components-calendar.mjs +33 -130
  4. package/fesm2022/ngx-com-components-calendar.mjs.map +1 -1
  5. package/fesm2022/ngx-com-components-confirm.mjs +562 -0
  6. package/fesm2022/ngx-com-components-confirm.mjs.map +1 -0
  7. package/fesm2022/ngx-com-components-dropdown.mjs +119 -25
  8. package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -1
  9. package/fesm2022/ngx-com-components-empty-state.mjs +382 -0
  10. package/fesm2022/ngx-com-components-empty-state.mjs.map +1 -0
  11. package/fesm2022/ngx-com-components-form-field.mjs +16 -15
  12. package/fesm2022/ngx-com-components-form-field.mjs.map +1 -1
  13. package/fesm2022/ngx-com-components-item.mjs +578 -0
  14. package/fesm2022/ngx-com-components-item.mjs.map +1 -0
  15. package/fesm2022/ngx-com-components-paginator.mjs +823 -0
  16. package/fesm2022/ngx-com-components-paginator.mjs.map +1 -0
  17. package/fesm2022/ngx-com-components-segmented-control.mjs +538 -0
  18. package/fesm2022/ngx-com-components-segmented-control.mjs.map +1 -0
  19. package/fesm2022/ngx-com-components-spinner.mjs +189 -0
  20. package/fesm2022/ngx-com-components-spinner.mjs.map +1 -0
  21. package/fesm2022/ngx-com-components-tooltip.mjs +625 -0
  22. package/fesm2022/ngx-com-components-tooltip.mjs.map +1 -0
  23. package/package.json +33 -1
  24. package/types/ngx-com-components-avatar.d.ts +409 -0
  25. package/types/ngx-com-components-calendar.d.ts +5 -0
  26. package/types/ngx-com-components-confirm.d.ts +160 -0
  27. package/types/ngx-com-components-dropdown.d.ts +52 -28
  28. package/types/ngx-com-components-empty-state.d.ts +269 -0
  29. package/types/ngx-com-components-item.d.ts +336 -0
  30. package/types/ngx-com-components-paginator.d.ts +265 -0
  31. package/types/ngx-com-components-segmented-control.d.ts +274 -0
  32. package/types/ngx-com-components-spinner.d.ts +120 -0
  33. package/types/ngx-com-components-tooltip.d.ts +200 -0
@@ -0,0 +1,562 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, viewChild, signal, computed, ChangeDetectionStrategy, Component, ElementRef, ViewContainerRef, Injector, DestroyRef, PLATFORM_ID, input, booleanAttribute, output, Directive } from '@angular/core';
3
+ import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
4
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import { Overlay } from '@angular/cdk/overlay';
6
+ import { ComponentPortal } from '@angular/cdk/portal';
7
+ import { filter } from 'rxjs/operators';
8
+ import { FocusTrapFactory } from '@angular/cdk/a11y';
9
+ import { ComButton } from 'ngx-com/components/button';
10
+ import { cva } from 'class-variance-authority';
11
+ import { mergeClasses } from 'ngx-com/utils';
12
+
13
+ /**
14
+ * CVA variants for the confirmation panel backdrop.
15
+ *
16
+ * @tokens `--color-background`
17
+ */
18
+ const confirmBackdropVariants = cva([
19
+ 'fixed',
20
+ 'inset-0',
21
+ 'z-50',
22
+ 'bg-background/80',
23
+ 'backdrop-blur-sm',
24
+ ], {
25
+ variants: {
26
+ visible: {
27
+ true: 'animate-in fade-in-0',
28
+ false: 'animate-out fade-out-0',
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ visible: true,
33
+ },
34
+ });
35
+ /**
36
+ * CVA variants for the confirmation panel container.
37
+ *
38
+ * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`, `--shadow-lg`, `--radius-popover`
39
+ */
40
+ const confirmPanelVariants = cva([
41
+ 'com-confirm-panel',
42
+ 'fixed',
43
+ 'left-1/2',
44
+ 'top-1/2',
45
+ '-translate-x-1/2',
46
+ '-translate-y-1/2',
47
+ 'z-50',
48
+ 'grid',
49
+ 'w-full',
50
+ 'max-w-lg',
51
+ 'gap-4',
52
+ 'border',
53
+ 'border-border',
54
+ 'bg-popover',
55
+ 'text-popover-foreground',
56
+ 'p-6',
57
+ 'shadow-lg',
58
+ 'rounded-popover',
59
+ 'outline-none',
60
+ ], {
61
+ variants: {
62
+ visible: {
63
+ true: 'animate-in fade-in-0 zoom-in-95',
64
+ false: 'animate-out fade-out-0 zoom-out-95',
65
+ },
66
+ },
67
+ defaultVariants: {
68
+ visible: true,
69
+ },
70
+ });
71
+ /**
72
+ * CVA variants for the confirmation panel title.
73
+ *
74
+ * @tokens `--color-foreground`
75
+ */
76
+ const confirmTitleVariants = cva([
77
+ 'text-lg',
78
+ 'font-semibold',
79
+ 'text-foreground',
80
+ 'leading-none',
81
+ 'tracking-tight',
82
+ ]);
83
+ /**
84
+ * CVA variants for the confirmation panel message.
85
+ *
86
+ * @tokens `--color-muted-foreground`
87
+ */
88
+ const confirmMessageVariants = cva([
89
+ 'text-sm',
90
+ 'text-muted-foreground',
91
+ ]);
92
+ /**
93
+ * CVA variants for the confirmation panel footer.
94
+ */
95
+ const confirmFooterVariants = cva([
96
+ 'flex',
97
+ 'flex-col-reverse',
98
+ 'sm:flex-row',
99
+ 'sm:justify-end',
100
+ 'sm:space-x-2',
101
+ ]);
102
+
103
+ let confirmIdCounter = 0;
104
+ /**
105
+ * Generate a unique ID for a confirmation dialog title.
106
+ */
107
+ function generateConfirmTitleId() {
108
+ return `confirm-title-${++confirmIdCounter}`;
109
+ }
110
+ /**
111
+ * Generate a unique ID for a confirmation dialog description.
112
+ */
113
+ function generateConfirmDescriptionId() {
114
+ return `confirm-desc-${++confirmIdCounter}`;
115
+ }
116
+
117
+ /**
118
+ * Internal confirmation panel component rendered inside the CDK overlay.
119
+ * Receives configuration from the directive and manages the dialog UI.
120
+ *
121
+ * @internal Not exported in public API
122
+ *
123
+ * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`,
124
+ * `--color-foreground`, `--color-muted-foreground`, `--shadow-lg`, `--radius-popover`
125
+ */
126
+ class ConfirmPanelComponent {
127
+ focusTrapFactory = inject(FocusTrapFactory);
128
+ focusTrap = null;
129
+ /** Reference to the panel element for focus trap. */
130
+ panelElement = viewChild('panelElement', ...(ngDevMode ? [{ debugName: "panelElement" }] : []));
131
+ /** Reference to the cancel button for initial focus. */
132
+ cancelButton = viewChild('cancelButton', ...(ngDevMode ? [{ debugName: "cancelButton" }] : []));
133
+ /** Panel configuration passed from the directive. */
134
+ config = signal(null, ...(ngDevMode ? [{ debugName: "config" }] : []));
135
+ /** Whether the panel is visible (for animation state). */
136
+ visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
137
+ /** Internal loading state for async operations. */
138
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
139
+ /** Function to confirm the action, set by directive. */
140
+ confirmFn = signal(() => { }, ...(ngDevMode ? [{ debugName: "confirmFn" }] : []));
141
+ /** Function to cancel the action, set by directive. */
142
+ cancelFn = signal(() => { }, ...(ngDevMode ? [{ debugName: "cancelFn" }] : []));
143
+ /** Computed template context for custom templates. */
144
+ templateContext = computed(() => ({
145
+ $implicit: this.config()?.message ?? '',
146
+ title: this.config()?.title,
147
+ confirm: () => this.onConfirm(),
148
+ cancel: () => this.onCancel(),
149
+ loading: this.loading(),
150
+ setLoading: (value) => this.loading.set(value),
151
+ }), ...(ngDevMode ? [{ debugName: "templateContext" }] : []));
152
+ /** Computed backdrop CSS classes. */
153
+ backdropClasses = computed(() => mergeClasses(confirmBackdropVariants({ visible: this.visible() })), ...(ngDevMode ? [{ debugName: "backdropClasses" }] : []));
154
+ /** Computed panel CSS classes. */
155
+ panelClasses = computed(() => mergeClasses(confirmPanelVariants({ visible: this.visible() })), ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
156
+ /** Computed title CSS classes. */
157
+ titleClasses = computed(() => mergeClasses(confirmTitleVariants()), ...(ngDevMode ? [{ debugName: "titleClasses" }] : []));
158
+ /** Computed message CSS classes. */
159
+ messageClasses = computed(() => mergeClasses(confirmMessageVariants()), ...(ngDevMode ? [{ debugName: "messageClasses" }] : []));
160
+ /** Computed footer CSS classes. */
161
+ footerClasses = computed(() => mergeClasses(confirmFooterVariants()), ...(ngDevMode ? [{ debugName: "footerClasses" }] : []));
162
+ ngAfterViewInit() {
163
+ this.setupFocusTrap();
164
+ this.focusCancelButton();
165
+ }
166
+ /** Handle confirm button click. */
167
+ onConfirm() {
168
+ this.confirmFn()();
169
+ }
170
+ /** Handle cancel button click. */
171
+ onCancel() {
172
+ this.cancelFn()();
173
+ }
174
+ /** Clean up focus trap on destroy. */
175
+ destroyFocusTrap() {
176
+ this.focusTrap?.destroy();
177
+ this.focusTrap = null;
178
+ }
179
+ setupFocusTrap() {
180
+ const panelEl = this.panelElement()?.nativeElement;
181
+ if (panelEl) {
182
+ this.focusTrap = this.focusTrapFactory.create(panelEl);
183
+ this.focusTrap.focusInitialElementWhenReady();
184
+ }
185
+ }
186
+ focusCancelButton() {
187
+ // Focus cancel button as safer default (prevents accidental confirmation)
188
+ // Use setTimeout to ensure DOM is ready
189
+ setTimeout(() => {
190
+ const cancelBtn = this.cancelButton()?.nativeElement;
191
+ if (cancelBtn) {
192
+ cancelBtn.focus();
193
+ }
194
+ }, 0);
195
+ }
196
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ConfirmPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
197
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ConfirmPanelComponent, isStandalone: true, selector: "com-confirm-panel", viewQueries: [{ propertyName: "panelElement", first: true, predicate: ["panelElement"], descendants: true, isSignal: true }, { propertyName: "cancelButton", first: true, predicate: ["cancelButton"], descendants: true, isSignal: true }], ngImport: i0, template: `
198
+ @if (config()?.hasBackdrop) {
199
+ <div
200
+ [class]="backdropClasses()"
201
+ [attr.data-state]="visible() ? 'open' : 'closed'"
202
+ aria-hidden="true"
203
+ ></div>
204
+ }
205
+ <div
206
+ #panelElement
207
+ [class]="panelClasses()"
208
+ role="alertdialog"
209
+ aria-modal="true"
210
+ [attr.aria-labelledby]="config()?.title ? config()?.titleId : null"
211
+ [attr.aria-describedby]="config()?.descriptionId"
212
+ [attr.data-state]="visible() ? 'open' : 'closed'"
213
+ tabindex="-1"
214
+ >
215
+ @if (config()?.customTemplate) {
216
+ <ng-container
217
+ [ngTemplateOutlet]="config()!.customTemplate!"
218
+ [ngTemplateOutletContext]="templateContext()"
219
+ />
220
+ } @else {
221
+ <div class="flex flex-col space-y-2">
222
+ @if (config()?.title) {
223
+ <h2 [id]="config()?.titleId" [class]="titleClasses()">
224
+ {{ config()?.title }}
225
+ </h2>
226
+ }
227
+ <p [id]="config()?.descriptionId" [class]="messageClasses()">
228
+ {{ config()?.message }}
229
+ </p>
230
+ </div>
231
+ <div [class]="footerClasses()">
232
+ <button
233
+ #cancelButton
234
+ comButton
235
+ variant="outline"
236
+ (click)="onCancel()"
237
+ type="button"
238
+ >
239
+ {{ config()?.cancelLabel }}
240
+ </button>
241
+ <button
242
+ comButton
243
+ [color]="config()?.confirmColor ?? 'primary'"
244
+ (click)="onConfirm()"
245
+ type="button"
246
+ >
247
+ {{ config()?.confirmLabel }}
248
+ </button>
249
+ </div>
250
+ }
251
+ </div>
252
+ `, isInline: true, styles: [":host{display:contents}[data-state=open]{--tw-enter-opacity: 0;--tw-enter-scale: .95}[data-state=closed]{--tw-exit-opacity: 0;--tw-exit-scale: .95}@media(prefers-reduced-motion:reduce){[data-state=open],[data-state=closed]{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ComButton, selector: "button[comButton], a[comButton]", inputs: ["variant", "color", "size", "fullWidth", "disabled", "class"], exportAs: ["comButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
253
+ }
254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ConfirmPanelComponent, decorators: [{
255
+ type: Component,
256
+ args: [{ selector: 'com-confirm-panel', template: `
257
+ @if (config()?.hasBackdrop) {
258
+ <div
259
+ [class]="backdropClasses()"
260
+ [attr.data-state]="visible() ? 'open' : 'closed'"
261
+ aria-hidden="true"
262
+ ></div>
263
+ }
264
+ <div
265
+ #panelElement
266
+ [class]="panelClasses()"
267
+ role="alertdialog"
268
+ aria-modal="true"
269
+ [attr.aria-labelledby]="config()?.title ? config()?.titleId : null"
270
+ [attr.aria-describedby]="config()?.descriptionId"
271
+ [attr.data-state]="visible() ? 'open' : 'closed'"
272
+ tabindex="-1"
273
+ >
274
+ @if (config()?.customTemplate) {
275
+ <ng-container
276
+ [ngTemplateOutlet]="config()!.customTemplate!"
277
+ [ngTemplateOutletContext]="templateContext()"
278
+ />
279
+ } @else {
280
+ <div class="flex flex-col space-y-2">
281
+ @if (config()?.title) {
282
+ <h2 [id]="config()?.titleId" [class]="titleClasses()">
283
+ {{ config()?.title }}
284
+ </h2>
285
+ }
286
+ <p [id]="config()?.descriptionId" [class]="messageClasses()">
287
+ {{ config()?.message }}
288
+ </p>
289
+ </div>
290
+ <div [class]="footerClasses()">
291
+ <button
292
+ #cancelButton
293
+ comButton
294
+ variant="outline"
295
+ (click)="onCancel()"
296
+ type="button"
297
+ >
298
+ {{ config()?.cancelLabel }}
299
+ </button>
300
+ <button
301
+ comButton
302
+ [color]="config()?.confirmColor ?? 'primary'"
303
+ (click)="onConfirm()"
304
+ type="button"
305
+ >
306
+ {{ config()?.confirmLabel }}
307
+ </button>
308
+ </div>
309
+ }
310
+ </div>
311
+ `, imports: [NgTemplateOutlet, ComButton], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:contents}[data-state=open]{--tw-enter-opacity: 0;--tw-enter-scale: .95}[data-state=closed]{--tw-exit-opacity: 0;--tw-exit-scale: .95}@media(prefers-reduced-motion:reduce){[data-state=open],[data-state=closed]{animation:none}}\n"] }]
312
+ }], propDecorators: { panelElement: [{ type: i0.ViewChild, args: ['panelElement', { isSignal: true }] }], cancelButton: [{ type: i0.ViewChild, args: ['cancelButton', { isSignal: true }] }] } });
313
+
314
+ /**
315
+ * Confirmation directive — intercepts clicks and displays a confirmation panel
316
+ * before allowing the action to proceed.
317
+ *
318
+ * The directive acts as an output gate: it captures clicks, shows confirmation UI,
319
+ * and emits `true` (confirmed) or `false` (cancelled) through its output.
320
+ *
321
+ * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`,
322
+ * `--color-foreground`, `--color-muted-foreground`, `--color-background`,
323
+ * `--shadow-lg`, `--radius-popover`
324
+ *
325
+ * @example Basic confirmation
326
+ * ```html
327
+ * <button comButton (comConfirm)="onDelete($event)" confirmMessage="Delete this item?">
328
+ * Delete
329
+ * </button>
330
+ * ```
331
+ *
332
+ * @example Destructive action with warn styling
333
+ * ```html
334
+ * <button comButton color="warn"
335
+ * (comConfirm)="onPermanentDelete($event)"
336
+ * confirmTitle="Permanent Deletion"
337
+ * confirmMessage="This action cannot be undone."
338
+ * confirmLabel="Delete Forever"
339
+ * confirmColor="warn">
340
+ * Delete Permanently
341
+ * </button>
342
+ * ```
343
+ *
344
+ * @example Custom template
345
+ * ```html
346
+ * <button comButton (comConfirm)="onAction($event)" [confirmTpl]="customTpl">
347
+ * Action
348
+ * </button>
349
+ *
350
+ * <ng-template #customTpl let-message let-confirm="confirm" let-cancel="cancel">
351
+ * <div class="flex flex-col gap-4">
352
+ * <p>{{ message }}</p>
353
+ * <div class="flex justify-end gap-2">
354
+ * <button comButton variant="ghost" (click)="cancel()">Cancel</button>
355
+ * <button comButton (click)="confirm()">Confirm</button>
356
+ * </div>
357
+ * </div>
358
+ * </ng-template>
359
+ * ```
360
+ */
361
+ class ComConfirm {
362
+ overlay = inject(Overlay);
363
+ elementRef = inject(ElementRef);
364
+ viewContainerRef = inject(ViewContainerRef);
365
+ injector = inject(Injector);
366
+ destroyRef = inject(DestroyRef);
367
+ platformId = inject(PLATFORM_ID);
368
+ overlayRef = null;
369
+ panelInstance = null;
370
+ titleId = generateConfirmTitleId();
371
+ descriptionId = generateConfirmDescriptionId();
372
+ /** Whether the confirmation panel is currently open. */
373
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
374
+ // ─── Content Inputs ───
375
+ /** The confirmation message to display. */
376
+ confirmMessage = input('Are you sure?', ...(ngDevMode ? [{ debugName: "confirmMessage" }] : []));
377
+ /** Optional title for the confirmation dialog. */
378
+ confirmTitle = input(undefined, ...(ngDevMode ? [{ debugName: "confirmTitle" }] : []));
379
+ /** Label for the confirm button. */
380
+ confirmLabel = input('Confirm', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : []));
381
+ /** Label for the cancel button. */
382
+ cancelLabel = input('Cancel', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : []));
383
+ // ─── Styling Inputs ───
384
+ /** Color variant for the confirm button. */
385
+ confirmColor = input('primary', ...(ngDevMode ? [{ debugName: "confirmColor" }] : []));
386
+ // ─── Behavior Inputs ───
387
+ /** When true, clicks pass through without showing confirmation. */
388
+ confirmDisabled = input(false, { ...(ngDevMode ? { debugName: "confirmDisabled" } : {}), transform: booleanAttribute });
389
+ /** Whether to show a backdrop behind the panel. */
390
+ confirmBackdrop = input(false, { ...(ngDevMode ? { debugName: "confirmBackdrop" } : {}), transform: booleanAttribute });
391
+ /** Custom template for the panel content. */
392
+ confirmTpl = input(undefined, ...(ngDevMode ? [{ debugName: "confirmTpl" }] : []));
393
+ // ─── Output ───
394
+ /**
395
+ * Emits `true` when confirmed, `false` when cancelled or navigated away.
396
+ * This is the main directive output — acts as an output gate for the action.
397
+ */
398
+ comConfirm = output();
399
+ // ─── Computed ───
400
+ panelConfig = computed(() => ({
401
+ message: this.confirmMessage(),
402
+ title: this.confirmTitle(),
403
+ confirmLabel: this.confirmLabel(),
404
+ cancelLabel: this.cancelLabel(),
405
+ confirmColor: this.confirmColor(),
406
+ hasBackdrop: this.confirmBackdrop(),
407
+ customTemplate: this.confirmTpl(),
408
+ titleId: this.titleId,
409
+ descriptionId: this.descriptionId,
410
+ }), ...(ngDevMode ? [{ debugName: "panelConfig" }] : []));
411
+ constructor() {
412
+ // Emit false and cleanup on destroy (navigation away)
413
+ this.destroyRef.onDestroy(() => {
414
+ if (this.isOpen()) {
415
+ this.comConfirm.emit(false);
416
+ }
417
+ this.disposeOverlay();
418
+ });
419
+ }
420
+ // ─── Public API ───
421
+ /** Programmatically open the confirmation dialog. */
422
+ open() {
423
+ if (this.isOpen() || this.confirmDisabled())
424
+ return;
425
+ this.createOverlay();
426
+ this.attachPanel();
427
+ }
428
+ /** Programmatically close the confirmation dialog (emits false). */
429
+ close() {
430
+ if (!this.isOpen())
431
+ return;
432
+ this.handleCancel();
433
+ }
434
+ // ─── Event Handlers ───
435
+ onTriggerClick(event) {
436
+ // If disabled, let the click pass through normally
437
+ if (this.confirmDisabled())
438
+ return;
439
+ // Intercept the click
440
+ event.preventDefault();
441
+ event.stopPropagation();
442
+ this.open();
443
+ }
444
+ // ─── Overlay Management ───
445
+ createOverlay() {
446
+ if (this.overlayRef)
447
+ return;
448
+ if (!isPlatformBrowser(this.platformId))
449
+ return;
450
+ // Use GlobalPositionStrategy for centered modal
451
+ const positionStrategy = this.overlay
452
+ .position()
453
+ .global()
454
+ .centerHorizontally()
455
+ .centerVertically();
456
+ this.overlayRef = this.overlay.create({
457
+ positionStrategy,
458
+ scrollStrategy: this.overlay.scrollStrategies.block(),
459
+ hasBackdrop: false, // We handle backdrop in the panel component
460
+ panelClass: 'com-confirm-overlay',
461
+ disposeOnNavigation: true,
462
+ });
463
+ }
464
+ attachPanel() {
465
+ if (!this.overlayRef || this.overlayRef.hasAttached())
466
+ return;
467
+ const portal = new ComponentPortal(ConfirmPanelComponent, this.viewContainerRef, this.injector);
468
+ const componentRef = this.overlayRef.attach(portal);
469
+ this.panelInstance = componentRef.instance;
470
+ // Configure panel
471
+ this.panelInstance.config.set(this.panelConfig());
472
+ this.panelInstance.confirmFn.set(() => this.handleConfirm());
473
+ this.panelInstance.cancelFn.set(() => this.handleCancel());
474
+ // Subscribe to keyboard events (Escape to cancel)
475
+ this.overlayRef
476
+ .keydownEvents()
477
+ .pipe(filter((event) => event.key === 'Escape'), takeUntilDestroyed(this.destroyRef))
478
+ .subscribe((event) => {
479
+ event.preventDefault();
480
+ event.stopPropagation();
481
+ this.handleCancel();
482
+ });
483
+ // Subscribe to detachments (cleanup)
484
+ this.overlayRef
485
+ .detachments()
486
+ .pipe(takeUntilDestroyed(this.destroyRef))
487
+ .subscribe(() => {
488
+ this.handleDetachment();
489
+ });
490
+ // Show panel after a microtask (allows initial styles to apply)
491
+ requestAnimationFrame(() => {
492
+ if (this.panelInstance) {
493
+ this.panelInstance.visible.set(true);
494
+ }
495
+ });
496
+ this.isOpen.set(true);
497
+ }
498
+ handleConfirm() {
499
+ if (!this.isOpen())
500
+ return;
501
+ this.comConfirm.emit(true);
502
+ this.closePanel();
503
+ }
504
+ handleCancel() {
505
+ if (!this.isOpen())
506
+ return;
507
+ this.comConfirm.emit(false);
508
+ this.closePanel();
509
+ }
510
+ closePanel() {
511
+ if (!this.panelInstance)
512
+ return;
513
+ // Trigger hide animation
514
+ this.panelInstance.visible.set(false);
515
+ // Wait for animation to complete before detaching
516
+ setTimeout(() => {
517
+ this.disposeOverlay();
518
+ this.returnFocusToTrigger();
519
+ }, 150); // Match animation duration
520
+ }
521
+ handleDetachment() {
522
+ this.isOpen.set(false);
523
+ this.panelInstance?.destroyFocusTrap();
524
+ this.panelInstance = null;
525
+ }
526
+ disposeOverlay() {
527
+ if (this.overlayRef) {
528
+ this.panelInstance?.destroyFocusTrap();
529
+ this.overlayRef.dispose();
530
+ this.overlayRef = null;
531
+ }
532
+ this.panelInstance = null;
533
+ this.isOpen.set(false);
534
+ }
535
+ returnFocusToTrigger() {
536
+ this.elementRef.nativeElement.focus();
537
+ }
538
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComConfirm, deps: [], target: i0.ɵɵFactoryTarget.Directive });
539
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: ComConfirm, isStandalone: true, selector: "[comConfirm]", inputs: { confirmMessage: { classPropertyName: "confirmMessage", publicName: "confirmMessage", isSignal: true, isRequired: false, transformFunction: null }, confirmTitle: { classPropertyName: "confirmTitle", publicName: "confirmTitle", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmColor: { classPropertyName: "confirmColor", publicName: "confirmColor", isSignal: true, isRequired: false, transformFunction: null }, confirmDisabled: { classPropertyName: "confirmDisabled", publicName: "confirmDisabled", isSignal: true, isRequired: false, transformFunction: null }, confirmBackdrop: { classPropertyName: "confirmBackdrop", publicName: "confirmBackdrop", isSignal: true, isRequired: false, transformFunction: null }, confirmTpl: { classPropertyName: "confirmTpl", publicName: "confirmTpl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { comConfirm: "comConfirm" }, host: { listeners: { "click": "onTriggerClick($event)" }, properties: { "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "isOpen()" } }, exportAs: ["comConfirm"], ngImport: i0 });
540
+ }
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComConfirm, decorators: [{
542
+ type: Directive,
543
+ args: [{
544
+ selector: '[comConfirm]',
545
+ exportAs: 'comConfirm',
546
+ host: {
547
+ '[attr.aria-haspopup]': '"dialog"',
548
+ '[attr.aria-expanded]': 'isOpen()',
549
+ '(click)': 'onTriggerClick($event)',
550
+ },
551
+ }]
552
+ }], ctorParameters: () => [], propDecorators: { confirmMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmMessage", required: false }] }], confirmTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmTitle", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], confirmColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmColor", required: false }] }], confirmDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmDisabled", required: false }] }], confirmBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmBackdrop", required: false }] }], confirmTpl: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmTpl", required: false }] }], comConfirm: [{ type: i0.Output, args: ["comConfirm"] }] } });
553
+
554
+ // Public API for the confirm directive
555
+ // Main directive
556
+
557
+ /**
558
+ * Generated bundle index. Do not edit.
559
+ */
560
+
561
+ export { ComConfirm, confirmBackdropVariants, confirmFooterVariants, confirmMessageVariants, confirmPanelVariants, confirmTitleVariants };
562
+ //# sourceMappingURL=ngx-com-components-confirm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-com-components-confirm.mjs","sources":["../../../projects/com/components/confirm/confirm.variants.ts","../../../projects/com/components/confirm/confirm.utils.ts","../../../projects/com/components/confirm/confirm-panel.component.ts","../../../projects/com/components/confirm/confirm.directive.ts","../../../projects/com/components/confirm/index.ts","../../../projects/com/components/confirm/ngx-com-components-confirm.ts"],"sourcesContent":["import { cva } from 'class-variance-authority';\n\n/**\n * CVA variants for the confirmation panel backdrop.\n *\n * @tokens `--color-background`\n */\nexport const confirmBackdropVariants: (props?: {\n visible?: boolean;\n}) => string = cva(\n [\n 'fixed',\n 'inset-0',\n 'z-50',\n 'bg-background/80',\n 'backdrop-blur-sm',\n ],\n {\n variants: {\n visible: {\n true: 'animate-in fade-in-0',\n false: 'animate-out fade-out-0',\n },\n },\n defaultVariants: {\n visible: true,\n },\n },\n);\n\n/**\n * CVA variants for the confirmation panel container.\n *\n * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`, `--shadow-lg`, `--radius-popover`\n */\nexport const confirmPanelVariants: (props?: {\n visible?: boolean;\n}) => string = cva(\n [\n 'com-confirm-panel',\n 'fixed',\n 'left-1/2',\n 'top-1/2',\n '-translate-x-1/2',\n '-translate-y-1/2',\n 'z-50',\n 'grid',\n 'w-full',\n 'max-w-lg',\n 'gap-4',\n 'border',\n 'border-border',\n 'bg-popover',\n 'text-popover-foreground',\n 'p-6',\n 'shadow-lg',\n 'rounded-popover',\n 'outline-none',\n ],\n {\n variants: {\n visible: {\n true: 'animate-in fade-in-0 zoom-in-95',\n false: 'animate-out fade-out-0 zoom-out-95',\n },\n },\n defaultVariants: {\n visible: true,\n },\n },\n);\n\n/**\n * CVA variants for the confirmation panel title.\n *\n * @tokens `--color-foreground`\n */\nexport const confirmTitleVariants: () => string = cva([\n 'text-lg',\n 'font-semibold',\n 'text-foreground',\n 'leading-none',\n 'tracking-tight',\n]);\n\n/**\n * CVA variants for the confirmation panel message.\n *\n * @tokens `--color-muted-foreground`\n */\nexport const confirmMessageVariants: () => string = cva([\n 'text-sm',\n 'text-muted-foreground',\n]);\n\n/**\n * CVA variants for the confirmation panel footer.\n */\nexport const confirmFooterVariants: () => string = cva([\n 'flex',\n 'flex-col-reverse',\n 'sm:flex-row',\n 'sm:justify-end',\n 'sm:space-x-2',\n]);\n","export { mergeClasses } from 'ngx-com/utils';\n\nlet confirmIdCounter = 0;\n\n/**\n * Generate a unique ID for a confirmation dialog title.\n */\nexport function generateConfirmTitleId(): string {\n return `confirm-title-${++confirmIdCounter}`;\n}\n\n/**\n * Generate a unique ID for a confirmation dialog description.\n */\nexport function generateConfirmDescriptionId(): string {\n return `confirm-desc-${++confirmIdCounter}`;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n signal,\n viewChild,\n} from '@angular/core';\nimport type { AfterViewInit, Signal, WritableSignal } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { FocusTrapFactory, FocusTrap } from '@angular/cdk/a11y';\nimport { ComButton } from 'ngx-com/components/button';\nimport {\n confirmPanelVariants,\n confirmBackdropVariants,\n confirmTitleVariants,\n confirmMessageVariants,\n confirmFooterVariants,\n} from './confirm.variants';\nimport type { ConfirmTemplateContext, ConfirmPanelConfig } from './confirm.models';\nimport { mergeClasses } from './confirm.utils';\n\n/**\n * Internal confirmation panel component rendered inside the CDK overlay.\n * Receives configuration from the directive and manages the dialog UI.\n *\n * @internal Not exported in public API\n *\n * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`,\n * `--color-foreground`, `--color-muted-foreground`, `--shadow-lg`, `--radius-popover`\n */\n@Component({\n selector: 'com-confirm-panel',\n template: `\n @if (config()?.hasBackdrop) {\n <div\n [class]=\"backdropClasses()\"\n [attr.data-state]=\"visible() ? 'open' : 'closed'\"\n aria-hidden=\"true\"\n ></div>\n }\n <div\n #panelElement\n [class]=\"panelClasses()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"config()?.title ? config()?.titleId : null\"\n [attr.aria-describedby]=\"config()?.descriptionId\"\n [attr.data-state]=\"visible() ? 'open' : 'closed'\"\n tabindex=\"-1\"\n >\n @if (config()?.customTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"config()!.customTemplate!\"\n [ngTemplateOutletContext]=\"templateContext()\"\n />\n } @else {\n <div class=\"flex flex-col space-y-2\">\n @if (config()?.title) {\n <h2 [id]=\"config()?.titleId\" [class]=\"titleClasses()\">\n {{ config()?.title }}\n </h2>\n }\n <p [id]=\"config()?.descriptionId\" [class]=\"messageClasses()\">\n {{ config()?.message }}\n </p>\n </div>\n <div [class]=\"footerClasses()\">\n <button\n #cancelButton\n comButton\n variant=\"outline\"\n (click)=\"onCancel()\"\n type=\"button\"\n >\n {{ config()?.cancelLabel }}\n </button>\n <button\n comButton\n [color]=\"config()?.confirmColor ?? 'primary'\"\n (click)=\"onConfirm()\"\n type=\"button\"\n >\n {{ config()?.confirmLabel }}\n </button>\n </div>\n }\n </div>\n `,\n styles: `\n :host {\n display: contents;\n }\n\n /* Animation styles using Tailwind animate utilities */\n [data-state='open'] {\n --tw-enter-opacity: 0;\n --tw-enter-scale: 0.95;\n }\n\n [data-state='closed'] {\n --tw-exit-opacity: 0;\n --tw-exit-scale: 0.95;\n }\n\n @media (prefers-reduced-motion: reduce) {\n [data-state='open'],\n [data-state='closed'] {\n animation: none;\n }\n }\n `,\n imports: [NgTemplateOutlet, ComButton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ConfirmPanelComponent implements AfterViewInit {\n private readonly focusTrapFactory = inject(FocusTrapFactory);\n private focusTrap: FocusTrap | null = null;\n\n /** Reference to the panel element for focus trap. */\n private readonly panelElement = viewChild<ElementRef<HTMLElement>>('panelElement');\n\n /** Reference to the cancel button for initial focus. */\n private readonly cancelButton = viewChild<ElementRef<HTMLButtonElement>>('cancelButton');\n\n /** Panel configuration passed from the directive. */\n readonly config: WritableSignal<ConfirmPanelConfig | null> = signal(null);\n\n /** Whether the panel is visible (for animation state). */\n readonly visible: WritableSignal<boolean> = signal(false);\n\n /** Internal loading state for async operations. */\n readonly loading: WritableSignal<boolean> = signal(false);\n\n /** Function to confirm the action, set by directive. */\n readonly confirmFn: WritableSignal<() => void> = signal(() => {});\n\n /** Function to cancel the action, set by directive. */\n readonly cancelFn: WritableSignal<() => void> = signal(() => {});\n\n /** Computed template context for custom templates. */\n protected readonly templateContext: Signal<ConfirmTemplateContext> = computed(() => ({\n $implicit: this.config()?.message ?? '',\n title: this.config()?.title,\n confirm: () => this.onConfirm(),\n cancel: () => this.onCancel(),\n loading: this.loading(),\n setLoading: (value: boolean) => this.loading.set(value),\n }));\n\n /** Computed backdrop CSS classes. */\n protected readonly backdropClasses: Signal<string> = computed(() =>\n mergeClasses(confirmBackdropVariants({ visible: this.visible() })),\n );\n\n /** Computed panel CSS classes. */\n protected readonly panelClasses: Signal<string> = computed(() =>\n mergeClasses(confirmPanelVariants({ visible: this.visible() })),\n );\n\n /** Computed title CSS classes. */\n protected readonly titleClasses: Signal<string> = computed(() =>\n mergeClasses(confirmTitleVariants()),\n );\n\n /** Computed message CSS classes. */\n protected readonly messageClasses: Signal<string> = computed(() =>\n mergeClasses(confirmMessageVariants()),\n );\n\n /** Computed footer CSS classes. */\n protected readonly footerClasses: Signal<string> = computed(() =>\n mergeClasses(confirmFooterVariants()),\n );\n\n ngAfterViewInit(): void {\n this.setupFocusTrap();\n this.focusCancelButton();\n }\n\n /** Handle confirm button click. */\n protected onConfirm(): void {\n this.confirmFn()();\n }\n\n /** Handle cancel button click. */\n protected onCancel(): void {\n this.cancelFn()();\n }\n\n /** Clean up focus trap on destroy. */\n destroyFocusTrap(): void {\n this.focusTrap?.destroy();\n this.focusTrap = null;\n }\n\n private setupFocusTrap(): void {\n const panelEl = this.panelElement()?.nativeElement;\n if (panelEl) {\n this.focusTrap = this.focusTrapFactory.create(panelEl);\n this.focusTrap.focusInitialElementWhenReady();\n }\n }\n\n private focusCancelButton(): void {\n // Focus cancel button as safer default (prevents accidental confirmation)\n // Use setTimeout to ensure DOM is ready\n setTimeout(() => {\n const cancelBtn = this.cancelButton()?.nativeElement;\n if (cancelBtn) {\n cancelBtn.focus();\n }\n }, 0);\n }\n}\n","import {\n booleanAttribute,\n computed,\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n Injector,\n input,\n output,\n PLATFORM_ID,\n signal,\n ViewContainerRef,\n} from '@angular/core';\nimport type {\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n TemplateRef,\n WritableSignal,\n} from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { filter } from 'rxjs/operators';\nimport { ConfirmPanelComponent } from './confirm-panel.component';\nimport { generateConfirmTitleId, generateConfirmDescriptionId } from './confirm.utils';\nimport type { ConfirmColor, ConfirmTemplateContext, ConfirmPanelConfig } from './confirm.models';\n\n/**\n * Confirmation directive — intercepts clicks and displays a confirmation panel\n * before allowing the action to proceed.\n *\n * The directive acts as an output gate: it captures clicks, shows confirmation UI,\n * and emits `true` (confirmed) or `false` (cancelled) through its output.\n *\n * @tokens `--color-popover`, `--color-popover-foreground`, `--color-border`,\n * `--color-foreground`, `--color-muted-foreground`, `--color-background`,\n * `--shadow-lg`, `--radius-popover`\n *\n * @example Basic confirmation\n * ```html\n * <button comButton (comConfirm)=\"onDelete($event)\" confirmMessage=\"Delete this item?\">\n * Delete\n * </button>\n * ```\n *\n * @example Destructive action with warn styling\n * ```html\n * <button comButton color=\"warn\"\n * (comConfirm)=\"onPermanentDelete($event)\"\n * confirmTitle=\"Permanent Deletion\"\n * confirmMessage=\"This action cannot be undone.\"\n * confirmLabel=\"Delete Forever\"\n * confirmColor=\"warn\">\n * Delete Permanently\n * </button>\n * ```\n *\n * @example Custom template\n * ```html\n * <button comButton (comConfirm)=\"onAction($event)\" [confirmTpl]=\"customTpl\">\n * Action\n * </button>\n *\n * <ng-template #customTpl let-message let-confirm=\"confirm\" let-cancel=\"cancel\">\n * <div class=\"flex flex-col gap-4\">\n * <p>{{ message }}</p>\n * <div class=\"flex justify-end gap-2\">\n * <button comButton variant=\"ghost\" (click)=\"cancel()\">Cancel</button>\n * <button comButton (click)=\"confirm()\">Confirm</button>\n * </div>\n * </div>\n * </ng-template>\n * ```\n */\n@Directive({\n selector: '[comConfirm]',\n exportAs: 'comConfirm',\n host: {\n '[attr.aria-haspopup]': '\"dialog\"',\n '[attr.aria-expanded]': 'isOpen()',\n '(click)': 'onTriggerClick($event)',\n },\n})\nexport class ComConfirm {\n private readonly overlay = inject(Overlay);\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly viewContainerRef = inject(ViewContainerRef);\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly platformId = inject(PLATFORM_ID);\n\n private overlayRef: OverlayRef | null = null;\n private panelInstance: ConfirmPanelComponent | null = null;\n private readonly titleId = generateConfirmTitleId();\n private readonly descriptionId = generateConfirmDescriptionId();\n\n /** Whether the confirmation panel is currently open. */\n protected readonly isOpen: WritableSignal<boolean> = signal(false);\n\n // ─── Content Inputs ───\n\n /** The confirmation message to display. */\n readonly confirmMessage: InputSignal<string> = input<string>('Are you sure?');\n\n /** Optional title for the confirmation dialog. */\n readonly confirmTitle: InputSignal<string | undefined> = input<string | undefined>(undefined);\n\n /** Label for the confirm button. */\n readonly confirmLabel: InputSignal<string> = input<string>('Confirm');\n\n /** Label for the cancel button. */\n readonly cancelLabel: InputSignal<string> = input<string>('Cancel');\n\n // ─── Styling Inputs ───\n\n /** Color variant for the confirm button. */\n readonly confirmColor: InputSignal<ConfirmColor> = input<ConfirmColor>('primary');\n\n // ─── Behavior Inputs ───\n\n /** When true, clicks pass through without showing confirmation. */\n readonly confirmDisabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Whether to show a backdrop behind the panel. */\n readonly confirmBackdrop: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n /** Custom template for the panel content. */\n readonly confirmTpl: InputSignal<TemplateRef<ConfirmTemplateContext> | undefined> =\n input<TemplateRef<ConfirmTemplateContext> | undefined>(undefined);\n\n // ─── Output ───\n\n /**\n * Emits `true` when confirmed, `false` when cancelled or navigated away.\n * This is the main directive output — acts as an output gate for the action.\n */\n readonly comConfirm: OutputEmitterRef<boolean> = output<boolean>();\n\n // ─── Computed ───\n\n private readonly panelConfig: Signal<ConfirmPanelConfig> = computed(() => ({\n message: this.confirmMessage(),\n title: this.confirmTitle(),\n confirmLabel: this.confirmLabel(),\n cancelLabel: this.cancelLabel(),\n confirmColor: this.confirmColor(),\n hasBackdrop: this.confirmBackdrop(),\n customTemplate: this.confirmTpl(),\n titleId: this.titleId,\n descriptionId: this.descriptionId,\n }));\n\n constructor() {\n // Emit false and cleanup on destroy (navigation away)\n this.destroyRef.onDestroy(() => {\n if (this.isOpen()) {\n this.comConfirm.emit(false);\n }\n this.disposeOverlay();\n });\n }\n\n // ─── Public API ───\n\n /** Programmatically open the confirmation dialog. */\n open(): void {\n if (this.isOpen() || this.confirmDisabled()) return;\n this.createOverlay();\n this.attachPanel();\n }\n\n /** Programmatically close the confirmation dialog (emits false). */\n close(): void {\n if (!this.isOpen()) return;\n this.handleCancel();\n }\n\n // ─── Event Handlers ───\n\n protected onTriggerClick(event: Event): void {\n // If disabled, let the click pass through normally\n if (this.confirmDisabled()) return;\n\n // Intercept the click\n event.preventDefault();\n event.stopPropagation();\n\n this.open();\n }\n\n // ─── Overlay Management ───\n\n private createOverlay(): void {\n if (this.overlayRef) return;\n if (!isPlatformBrowser(this.platformId)) return;\n\n // Use GlobalPositionStrategy for centered modal\n const positionStrategy = this.overlay\n .position()\n .global()\n .centerHorizontally()\n .centerVertically();\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.overlay.scrollStrategies.block(),\n hasBackdrop: false, // We handle backdrop in the panel component\n panelClass: 'com-confirm-overlay',\n disposeOnNavigation: true,\n });\n }\n\n private attachPanel(): void {\n if (!this.overlayRef || this.overlayRef.hasAttached()) return;\n\n const portal = new ComponentPortal(ConfirmPanelComponent, this.viewContainerRef, this.injector);\n const componentRef = this.overlayRef.attach(portal);\n this.panelInstance = componentRef.instance;\n\n // Configure panel\n this.panelInstance.config.set(this.panelConfig());\n this.panelInstance.confirmFn.set(() => this.handleConfirm());\n this.panelInstance.cancelFn.set(() => this.handleCancel());\n\n // Subscribe to keyboard events (Escape to cancel)\n this.overlayRef\n .keydownEvents()\n .pipe(\n filter((event) => event.key === 'Escape'),\n takeUntilDestroyed(this.destroyRef),\n )\n .subscribe((event) => {\n event.preventDefault();\n event.stopPropagation();\n this.handleCancel();\n });\n\n // Subscribe to detachments (cleanup)\n this.overlayRef\n .detachments()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => {\n this.handleDetachment();\n });\n\n // Show panel after a microtask (allows initial styles to apply)\n requestAnimationFrame(() => {\n if (this.panelInstance) {\n this.panelInstance.visible.set(true);\n }\n });\n\n this.isOpen.set(true);\n }\n\n private handleConfirm(): void {\n if (!this.isOpen()) return;\n\n this.comConfirm.emit(true);\n this.closePanel();\n }\n\n private handleCancel(): void {\n if (!this.isOpen()) return;\n\n this.comConfirm.emit(false);\n this.closePanel();\n }\n\n private closePanel(): void {\n if (!this.panelInstance) return;\n\n // Trigger hide animation\n this.panelInstance.visible.set(false);\n\n // Wait for animation to complete before detaching\n setTimeout(() => {\n this.disposeOverlay();\n this.returnFocusToTrigger();\n }, 150); // Match animation duration\n }\n\n private handleDetachment(): void {\n this.isOpen.set(false);\n this.panelInstance?.destroyFocusTrap();\n this.panelInstance = null;\n }\n\n private disposeOverlay(): void {\n if (this.overlayRef) {\n this.panelInstance?.destroyFocusTrap();\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n this.panelInstance = null;\n this.isOpen.set(false);\n }\n\n private returnFocusToTrigger(): void {\n this.elementRef.nativeElement.focus();\n }\n}\n","// Public API for the confirm directive\n\n// Main directive\nexport { ComConfirm } from './confirm.directive';\n\n// Types and interfaces\nexport type { ConfirmTemplateContext, ConfirmColor } from './confirm.models';\n\n// Variants (for advanced customization)\nexport {\n confirmPanelVariants,\n confirmBackdropVariants,\n confirmTitleVariants,\n confirmMessageVariants,\n confirmFooterVariants,\n} from './confirm.variants';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}