@tolle_/tolle-ui 18.2.30 → 18.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.
@@ -6310,12 +6310,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6310
6310
  args: [AccordionItemComponent]
6311
6311
  }] } });
6312
6312
 
6313
+ /**
6314
+ * Safety net if the exit animation's `animationend` never fires — reduced
6315
+ * motion, no matching keyframe, or a panel that never rendered — so a modal
6316
+ * can never get stuck open forever.
6317
+ */
6318
+ const CLOSE_FALLBACK_MS$1 = 300;
6313
6319
  class ModalRef {
6314
6320
  overlay;
6315
6321
  modal;
6316
6322
  stack;
6317
6323
  _afterClosed$ = new Subject();
6318
6324
  afterClosed$ = this._afterClosed$.asObservable();
6325
+ _closingSubject = new BehaviorSubject(false);
6326
+ /** True once `close()` has been called — drives the panel's exit animation. */
6327
+ closing$ = this._closingSubject.asObservable();
6319
6328
  constructor(overlay, modal, stack) {
6320
6329
  this.overlay = overlay;
6321
6330
  this.modal = modal;
@@ -6329,22 +6338,46 @@ class ModalRef {
6329
6338
  });
6330
6339
  }
6331
6340
  /**
6332
- * Closes the modal instantly.
6341
+ * Closes the modal. Signals the panel and backdrop to play their exit
6342
+ * animation, then tears down the overlay once it finishes (or after
6343
+ * `CLOSE_FALLBACK_MS`, whichever comes first).
6333
6344
  * @param result Data to pass back to the caller
6334
6345
  */
6335
6346
  close(result) {
6336
- this._afterClosed$.next(result);
6337
- this._afterClosed$.complete();
6338
- this.overlay.dispose(); // Instant disposal (No animation timer)
6339
- this.stack.unregister(this);
6347
+ if (this._closingSubject.value)
6348
+ return;
6349
+ this._closingSubject.next(true);
6350
+ this.overlay.backdropElement?.setAttribute('data-state', 'closed');
6351
+ let finished = false;
6352
+ const finish = () => {
6353
+ if (finished)
6354
+ return;
6355
+ finished = true;
6356
+ this._afterClosed$.next(result);
6357
+ this._afterClosed$.complete();
6358
+ this.overlay.dispose();
6359
+ this.stack.unregister(this);
6360
+ };
6361
+ const panel = this.overlay.overlayElement.querySelector('[data-state]');
6362
+ if (panel) {
6363
+ panel.addEventListener('animationend', finish, { once: true });
6364
+ setTimeout(finish, CLOSE_FALLBACK_MS$1);
6365
+ }
6366
+ else {
6367
+ finish();
6368
+ }
6340
6369
  }
6341
6370
  }
6342
6371
 
6343
6372
  class ModalComponent {
6344
6373
  ref;
6374
+ cdr = inject(ChangeDetectorRef);
6375
+ subscription = new Subscription();
6345
6376
  contentType = 'string';
6346
6377
  content;
6347
6378
  modalClasses = '';
6379
+ /** True while the exit animation plays, just before the overlay is torn down. */
6380
+ closing = false;
6348
6381
  /** Stable, per-instance ids used to wire dialog ARIA relationships. */
6349
6382
  _uid = Math.random().toString(36).substr(2, 9);
6350
6383
  titleId = `tolle-modal-title-${this._uid}`;
@@ -6356,16 +6389,21 @@ class ModalComponent {
6356
6389
  this.content = this.ref.modal.content;
6357
6390
  this.modalClasses = this.getModalSizeCss();
6358
6391
  this.determineContentType();
6392
+ this.subscription.add(this.ref.closing$.subscribe((closing) => {
6393
+ this.closing = closing;
6394
+ this.cdr.markForCheck();
6395
+ }));
6359
6396
  }
6360
- /** Whether the auto-rendered header (title and/or close button) is shown. */
6361
- get hasHeader() {
6362
- return !!(this.ref.modal.showCloseButton || this.ref.modal.title);
6397
+ ngOnDestroy() {
6398
+ this.subscription.unsubscribe();
6363
6399
  }
6364
6400
  getModalSizeCss() {
6365
6401
  const { size } = this.ref.modal;
6366
6402
  return cn(
6367
6403
  // Surface: overlay card that never exceeds the viewport (header stays, body scrolls).
6368
- 'bg-background text-foreground border border-border shadow-lg relative flex flex-col w-full mx-auto', size === 'fullscreen' ? 'h-screen w-screen rounded-none' : 'rounded-lg max-h-[85vh]',
6404
+ 'relative flex w-full mx-auto flex-col gap-4 rounded-lg border border-border bg-background p-6 text-foreground shadow-lg duration-200',
6405
+ // Enter/exit animation, driven by `data-state` (see `closing` above).
6406
+ 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', size === 'fullscreen' ? 'h-screen w-screen rounded-none' : 'max-h-[85vh]',
6369
6407
  // Sizing scale with explicit max-widths
6370
6408
  size === 'xs' && 'max-w-[320px]', size === 'sm' && 'max-w-[425px]', size === 'default' && 'max-w-[512px]', size === 'lg' && 'max-w-[1024px]', size === 'xl' && 'max-w-[1280px]');
6371
6409
  }
@@ -6383,6 +6421,7 @@ class ModalComponent {
6383
6421
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ModalComponent, deps: [{ token: ModalRef }], target: i0.ɵɵFactoryTarget.Component });
6384
6422
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ModalComponent, isStandalone: true, selector: "tolle-modal", ngImport: i0, template: `
6385
6423
  <div [class]="modalClasses" class="pointer-events-auto"
6424
+ [attr.data-state]="closing ? 'closed' : 'open'"
6386
6425
  role="dialog"
6387
6426
  aria-modal="true"
6388
6427
  [attr.aria-labelledby]="ref.modal.title ? titleId : null"
@@ -6390,25 +6429,26 @@ class ModalComponent {
6390
6429
  cdkTrapFocus cdkTrapFocusAutoCapture
6391
6430
  (mousedown)="$event.stopPropagation()">
6392
6431
 
6432
+ <button
6433
+ *ngIf="ref.modal.showCloseButton"
6434
+ type="button"
6435
+ (click)="ref.close()"
6436
+ aria-label="Close"
6437
+ class="absolute right-4 top-4 grid h-6 w-6 place-items-center rounded-sm text-muted-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">
6438
+ <i class="ri-close-line text-base" aria-hidden="true"></i>
6439
+ </button>
6440
+
6393
6441
  <!-- Header -->
6394
- <div *ngIf="hasHeader" class="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
6395
- <h2 *ngIf="ref.modal.title" [id]="titleId" class="text-lg font-semibold leading-none tracking-tight text-foreground">
6442
+ <div *ngIf="ref.modal.title" class="flex shrink-0 flex-col gap-1.5 pr-8 text-center sm:text-left">
6443
+ <h2 [id]="titleId" class="text-lg font-semibold leading-none tracking-tight text-foreground">
6396
6444
  {{ ref.modal.title }}
6397
6445
  </h2>
6398
- <button
6399
- *ngIf="ref.modal.showCloseButton"
6400
- type="button"
6401
- (click)="ref.close()"
6402
- aria-label="Close"
6403
- class="-mr-2 -mt-2 ml-auto grid h-8 w-8 shrink-0 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
6404
- <i class="ri-close-line text-xl"></i>
6405
- </button>
6406
6446
  </div>
6407
6447
 
6408
6448
  <!-- Body -->
6409
6449
  <div class="min-h-0 flex-1 overflow-y-auto">
6410
6450
  <ng-container [ngSwitch]="contentType">
6411
- <p *ngSwitchCase="'string'" [id]="descId" [class]="hasHeader ? 'px-6 pb-6 text-sm leading-relaxed text-muted-foreground' : 'p-6 text-sm leading-relaxed text-muted-foreground'">{{ content }}</p>
6451
+ <p *ngSwitchCase="'string'" [id]="descId" class="text-sm leading-relaxed text-muted-foreground">{{ content }}</p>
6412
6452
 
6413
6453
  <ng-container *ngSwitchCase="'template'">
6414
6454
  <ng-container *ngTemplateOutlet="asTemplate; context: ref.modal.context"></ng-container>
@@ -6426,6 +6466,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6426
6466
  type: Component,
6427
6467
  args: [{ selector: 'tolle-modal', standalone: true, imports: [CommonModule, A11yModule], template: `
6428
6468
  <div [class]="modalClasses" class="pointer-events-auto"
6469
+ [attr.data-state]="closing ? 'closed' : 'open'"
6429
6470
  role="dialog"
6430
6471
  aria-modal="true"
6431
6472
  [attr.aria-labelledby]="ref.modal.title ? titleId : null"
@@ -6433,25 +6474,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6433
6474
  cdkTrapFocus cdkTrapFocusAutoCapture
6434
6475
  (mousedown)="$event.stopPropagation()">
6435
6476
 
6477
+ <button
6478
+ *ngIf="ref.modal.showCloseButton"
6479
+ type="button"
6480
+ (click)="ref.close()"
6481
+ aria-label="Close"
6482
+ class="absolute right-4 top-4 grid h-6 w-6 place-items-center rounded-sm text-muted-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">
6483
+ <i class="ri-close-line text-base" aria-hidden="true"></i>
6484
+ </button>
6485
+
6436
6486
  <!-- Header -->
6437
- <div *ngIf="hasHeader" class="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
6438
- <h2 *ngIf="ref.modal.title" [id]="titleId" class="text-lg font-semibold leading-none tracking-tight text-foreground">
6487
+ <div *ngIf="ref.modal.title" class="flex shrink-0 flex-col gap-1.5 pr-8 text-center sm:text-left">
6488
+ <h2 [id]="titleId" class="text-lg font-semibold leading-none tracking-tight text-foreground">
6439
6489
  {{ ref.modal.title }}
6440
6490
  </h2>
6441
- <button
6442
- *ngIf="ref.modal.showCloseButton"
6443
- type="button"
6444
- (click)="ref.close()"
6445
- aria-label="Close"
6446
- class="-mr-2 -mt-2 ml-auto grid h-8 w-8 shrink-0 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
6447
- <i class="ri-close-line text-xl"></i>
6448
- </button>
6449
6491
  </div>
6450
6492
 
6451
6493
  <!-- Body -->
6452
6494
  <div class="min-h-0 flex-1 overflow-y-auto">
6453
6495
  <ng-container [ngSwitch]="contentType">
6454
- <p *ngSwitchCase="'string'" [id]="descId" [class]="hasHeader ? 'px-6 pb-6 text-sm leading-relaxed text-muted-foreground' : 'p-6 text-sm leading-relaxed text-muted-foreground'">{{ content }}</p>
6496
+ <p *ngSwitchCase="'string'" [id]="descId" class="text-sm leading-relaxed text-muted-foreground">{{ content }}</p>
6455
6497
 
6456
6498
  <ng-container *ngSwitchCase="'template'">
6457
6499
  <ng-container *ngTemplateOutlet="asTemplate; context: ref.modal.context"></ng-container>
@@ -6490,6 +6532,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6490
6532
  args: [{ providedIn: 'root' }]
6491
6533
  }] });
6492
6534
 
6535
+ /**
6536
+ * `open()` always receives a plain object literal, never a `new Modal()`
6537
+ * instance, so a class field initializer would never actually apply — these
6538
+ * are the real defaults, merged in explicitly below.
6539
+ */
6540
+ const MODAL_DEFAULTS = {
6541
+ size: 'default',
6542
+ backdropClose: true,
6543
+ showCloseButton: true,
6544
+ };
6493
6545
  class ModalService {
6494
6546
  overlay;
6495
6547
  injector;
@@ -6500,12 +6552,13 @@ class ModalService {
6500
6552
  this.stack = stack;
6501
6553
  }
6502
6554
  open(config) {
6555
+ const resolved = { ...MODAL_DEFAULTS, ...config };
6503
6556
  // 0. Remember what was focused so we can restore it after the modal closes.
6504
6557
  const previouslyFocused = document.activeElement;
6505
6558
  // 1. Create the Overlay (DOM placeholder)
6506
6559
  const overlayRef = this.createOverlay();
6507
6560
  // 2. Create the Controller (Ref)
6508
- const modalRef = new ModalRef(overlayRef, config, this.stack);
6561
+ const modalRef = new ModalRef(overlayRef, resolved, this.stack);
6509
6562
  // 3. Create Injector to allow the Component to access the Ref
6510
6563
  const injector = Injector.create({
6511
6564
  parent: this.injector,
@@ -6514,7 +6567,7 @@ class ModalService {
6514
6567
  // Escape-to-close: mirror the backdrop close path, but only for
6515
6568
  // non-blocking modals (backdropClose !== false).
6516
6569
  overlayRef.keydownEvents().subscribe((event) => {
6517
- if (event.key === 'Escape' && config.backdropClose !== false) {
6570
+ if (event.key === 'Escape' && resolved.backdropClose) {
6518
6571
  event.preventDefault();
6519
6572
  modalRef.close();
6520
6573
  }
@@ -6524,6 +6577,9 @@ class ModalService {
6524
6577
  // 4. Attach the UI Component to the Overlay
6525
6578
  const portal = new ComponentPortal(ModalComponent, null, injector);
6526
6579
  overlayRef.attach(portal);
6580
+ // The backdrop element only exists once attached — setting this any
6581
+ // earlier (e.g. in ModalRef's constructor) would silently no-op.
6582
+ overlayRef.backdropElement?.setAttribute('data-state', 'open');
6527
6583
  return modalRef;
6528
6584
  }
6529
6585
  /** Global helper to close everything */
@@ -6534,7 +6590,15 @@ class ModalService {
6534
6590
  createOverlay() {
6535
6591
  const config = new OverlayConfig({
6536
6592
  hasBackdrop: true,
6537
- backdropClass: ['cdk-overlay-backdrop', 'bg-black/80', 'backdrop-blur-sm'],
6593
+ backdropClass: [
6594
+ 'cdk-overlay-backdrop',
6595
+ 'bg-black/80',
6596
+ 'backdrop-blur-sm',
6597
+ 'data-[state=open]:animate-in',
6598
+ 'data-[state=open]:fade-in-0',
6599
+ 'data-[state=closed]:animate-out',
6600
+ 'data-[state=closed]:fade-out-0',
6601
+ ],
6538
6602
  panelClass: [
6539
6603
  'w-full',
6540
6604
  'h-full',
@@ -6559,35 +6623,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6559
6623
  args: [{ providedIn: 'root' }]
6560
6624
  }], ctorParameters: () => [{ type: i1$2.Overlay }, { type: i0.Injector }, { type: ModalStackService }] });
6561
6625
 
6562
- class Modal {
6563
- /** The content to display (String, Component, or Template) */
6564
- content;
6565
- /** Optional title for the standard header */
6566
- title;
6567
- /** * Predefined size scale.
6568
- * - xs: 320px (Mobile alerts)
6569
- * - sm: 425px (Standard dialogs)
6570
- * - default: 544px (Forms)
6571
- * - lg: 90% / 1024px (Data tables)
6572
- * - xl: 1280px (Large forms, dashboards)
6573
- * - fullscreen: 100vw/100vh (Complex workflows)
6574
- */
6575
- size = 'default';
6576
- /** * If true (default), clicking the backdrop closes the modal.
6577
- * Set to false for "blocking" modals (e.g., Terms of Service).
6578
- */
6579
- backdropClose = true;
6580
- /** * Data to pass to a Component content.
6581
- * Accessed via @Input() in the child component.
6582
- */
6583
- data;
6584
- /** * Context to pass to a TemplateRef content.
6585
- * Accessed via `let-val` in the HTML.
6586
- */
6587
- context;
6588
- showCloseButton = true;
6589
- }
6590
-
6591
6626
  class ButtonGroupComponent {
6592
6627
  class = '';
6593
6628
  cn = cn;
@@ -9071,7 +9106,7 @@ class SegmentComponent {
9071
9106
  (keydown)="onKeydown($event)"
9072
9107
  >
9073
9108
  <div
9074
- class="absolute top-1 bottom-1 bg-primary shadow-sm rounded-md transition-all duration-300 ease-[cubic-bezier(0.2,0.0,0.2,1)]"
9109
+ class="absolute top-1 bottom-1 bg-primary shadow-sm rounded-md transition-all duration-300 ease-tolle"
9075
9110
  [style.left.px]="gliderLeft"
9076
9111
  [style.width.px]="gliderWidth"
9077
9112
  [class.opacity-0]="!hasValue"
@@ -9128,7 +9163,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9128
9163
  (keydown)="onKeydown($event)"
9129
9164
  >
9130
9165
  <div
9131
- class="absolute top-1 bottom-1 bg-primary shadow-sm rounded-md transition-all duration-300 ease-[cubic-bezier(0.2,0.0,0.2,1)]"
9166
+ class="absolute top-1 bottom-1 bg-primary shadow-sm rounded-md transition-all duration-300 ease-tolle"
9132
9167
  [style.left.px]="gliderLeft"
9133
9168
  [style.width.px]="gliderWidth"
9134
9169
  [class.opacity-0]="!hasValue"
@@ -11177,6 +11212,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11177
11212
  type: Input
11178
11213
  }] } });
11179
11214
 
11215
+ /**
11216
+ * Safety net if the exit animation's `animationend` never fires — reduced
11217
+ * motion, no matching keyframe, or a panel that never rendered — so an
11218
+ * alert dialog can never get stuck open forever. Also used by
11219
+ * `alert-dialog.service.ts` and `alert-dialog-dynamic.component.ts`, which
11220
+ * animate the same content component through a different overlay wiring.
11221
+ */
11222
+ const CLOSE_FALLBACK_MS = 300;
11180
11223
  class AlertDialogInternalService {
11181
11224
  openSubject = new BehaviorSubject(false);
11182
11225
  open$ = this.openSubject.asObservable();
@@ -11271,14 +11314,39 @@ class AlertDialogPortalComponent {
11271
11314
  });
11272
11315
  const portal = new TemplatePortal(this.portalContent, this.viewContainerRef);
11273
11316
  this.overlayRef.attach(portal);
11317
+ // The backdrop element only exists once attached — setting this any
11318
+ // earlier would silently no-op.
11319
+ this.overlayRef.backdropElement?.setAttribute('data-state', 'open');
11274
11320
  }
11321
+ /**
11322
+ * Tears the overlay down once its exit animation finishes (or after
11323
+ * `CLOSE_FALLBACK_MS`, whichever comes first) instead of instantly, so
11324
+ * `data-[state=closed]:animate-out` actually gets a chance to play.
11325
+ */
11275
11326
  hide() {
11276
- if (this.overlayRef) {
11277
- this.overlayRef.detach();
11278
- this.overlayRef.dispose();
11279
- this.overlayRef = undefined;
11327
+ const ref = this.overlayRef;
11328
+ if (!ref)
11329
+ return;
11330
+ ref.backdropElement?.setAttribute('data-state', 'closed');
11331
+ let finished = false;
11332
+ const finish = () => {
11333
+ if (finished)
11334
+ return;
11335
+ finished = true;
11336
+ ref.detach();
11337
+ ref.dispose();
11338
+ if (this.overlayRef === ref)
11339
+ this.overlayRef = undefined;
11280
11340
  // Restore focus to the trigger.
11281
11341
  this.previouslyFocused?.focus?.();
11342
+ };
11343
+ const panel = ref.overlayElement.querySelector('[data-state]');
11344
+ if (panel) {
11345
+ panel.addEventListener('animationend', finish, { once: true });
11346
+ setTimeout(finish, CLOSE_FALLBACK_MS);
11347
+ }
11348
+ else {
11349
+ finish();
11282
11350
  }
11283
11351
  }
11284
11352
  ngOnDestroy() {
@@ -11316,7 +11384,7 @@ class AlertDialogContentComponent {
11316
11384
  });
11317
11385
  }
11318
11386
  get computedClass() {
11319
- return cn("fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-50 grid w-full gap-4 border border-input bg-background p-6 shadow-lg data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] rounded-lg", {
11387
+ return cn("fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-50 grid w-full gap-4 border border-input bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] rounded-lg", {
11320
11388
  'max-w-xs': this.size === 'xs',
11321
11389
  'max-w-sm': this.size === 'sm',
11322
11390
  'max-w-md': this.size === 'md',
@@ -11479,6 +11547,11 @@ class AlertDialogRef {
11479
11547
  class AlertDialogDynamicComponent {
11480
11548
  config;
11481
11549
  dialogRef;
11550
+ /**
11551
+ * Set by `AlertDialogService` once the dialog's result is ready, so the
11552
+ * content panel plays its exit animation before the overlay is torn down.
11553
+ */
11554
+ closing = false;
11482
11555
  onOpenChange(open) {
11483
11556
  if (!open) {
11484
11557
  this.close(false);
@@ -11489,7 +11562,7 @@ class AlertDialogDynamicComponent {
11489
11562
  }
11490
11563
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AlertDialogDynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11491
11564
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: AlertDialogDynamicComponent, isStandalone: true, selector: "tolle-alert-dialog-dynamic", ngImport: i0, template: `
11492
- <tolle-alert-dialog [open]="true" (openChange)="onOpenChange($event)">
11565
+ <tolle-alert-dialog [open]="!closing" (openChange)="onOpenChange($event)">
11493
11566
  <tolle-alert-dialog-content [size]="config.size || 'lg'">
11494
11567
  <tolle-alert-dialog-header>
11495
11568
  <tolle-alert-dialog-title>{{ config.title }}</tolle-alert-dialog-title>
@@ -11525,7 +11598,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
11525
11598
  AlertDialogActionComponent,
11526
11599
  ButtonComponent
11527
11600
  ], template: `
11528
- <tolle-alert-dialog [open]="true" (openChange)="onOpenChange($event)">
11601
+ <tolle-alert-dialog [open]="!closing" (openChange)="onOpenChange($event)">
11529
11602
  <tolle-alert-dialog-content [size]="config.size || 'lg'">
11530
11603
  <tolle-alert-dialog-header>
11531
11604
  <tolle-alert-dialog-title>{{ config.title }}</tolle-alert-dialog-title>
@@ -11556,7 +11629,15 @@ class AlertDialogService {
11556
11629
  const previouslyFocused = document.activeElement;
11557
11630
  const overlayConfig = new OverlayConfig({
11558
11631
  hasBackdrop: true,
11559
- backdropClass: ['cdk-overlay-backdrop', 'bg-black/80', 'backdrop-blur-sm'],
11632
+ backdropClass: [
11633
+ 'cdk-overlay-backdrop',
11634
+ 'bg-black/80',
11635
+ 'backdrop-blur-sm',
11636
+ 'data-[state=open]:animate-in',
11637
+ 'data-[state=open]:fade-in-0',
11638
+ 'data-[state=closed]:animate-out',
11639
+ 'data-[state=closed]:fade-out-0',
11640
+ ],
11560
11641
  positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),
11561
11642
  scrollStrategy: this.overlay.scrollStrategies.block()
11562
11643
  });
@@ -11564,13 +11645,36 @@ class AlertDialogService {
11564
11645
  const dialogRef = new AlertDialogRef();
11565
11646
  const portal = new ComponentPortal(AlertDialogDynamicComponent, null, this.injector);
11566
11647
  const componentRef = overlayRef.attach(portal);
11648
+ // The backdrop element only exists once attached — setting this any
11649
+ // earlier would silently no-op.
11650
+ overlayRef.backdropElement?.setAttribute('data-state', 'open');
11567
11651
  componentRef.instance.config = config;
11568
11652
  componentRef.instance.dialogRef = dialogRef;
11653
+ // The result (`afterClosed$`) is ready immediately, but disposing the
11654
+ // overlay waits for the content panel's exit animation to finish (or
11655
+ // a fallback timeout), so `data-[state=closed]:animate-out` gets a
11656
+ // chance to play instead of being torn down mid-frame.
11569
11657
  dialogRef.afterClosed$.subscribe(() => {
11570
- overlayRef.detach();
11571
- overlayRef.dispose();
11572
- // Restore focus to the trigger.
11573
- previouslyFocused?.focus?.();
11658
+ overlayRef.backdropElement?.setAttribute('data-state', 'closed');
11659
+ componentRef.instance.closing = true;
11660
+ let finished = false;
11661
+ const finish = () => {
11662
+ if (finished)
11663
+ return;
11664
+ finished = true;
11665
+ overlayRef.detach();
11666
+ overlayRef.dispose();
11667
+ // Restore focus to the trigger.
11668
+ previouslyFocused?.focus?.();
11669
+ };
11670
+ const panel = overlayRef.overlayElement.querySelector('[data-state]');
11671
+ if (panel) {
11672
+ panel.addEventListener('animationend', finish, { once: true });
11673
+ setTimeout(finish, CLOSE_FALLBACK_MS);
11674
+ }
11675
+ else {
11676
+ finish();
11677
+ }
11574
11678
  });
11575
11679
  // Alert-dialog semantics: backdrop clicks must NOT dismiss.
11576
11680
  // Escape still closes the dialog.
@@ -16497,21 +16601,21 @@ class ResizablePanelComponent {
16497
16601
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ResizablePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16498
16602
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ResizablePanelComponent, isStandalone: true, selector: "tolle-resizable-panel", inputs: { direction: "direction", class: "class" }, queries: [{ propertyName: "panels", predicate: i0.forwardRef(() => ResizablePanelItemComponent) }], ngImport: i0, template: `
16499
16603
  <div [class]="computedContainerClass">
16500
- <div class="flex" [class.flex-col]="direction === 'vertical'" [class.flex-row]="direction === 'horizontal'">
16604
+ <div class="flex h-full w-full" [class.flex-col]="direction === 'vertical'" [class.flex-row]="direction === 'horizontal'">
16501
16605
  <ng-content></ng-content>
16502
16606
  </div>
16503
16607
  </div>
16504
- `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
16608
+ `, isInline: true, styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
16505
16609
  }
16506
16610
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ResizablePanelComponent, decorators: [{
16507
16611
  type: Component,
16508
16612
  args: [{ selector: 'tolle-resizable-panel', standalone: true, imports: [CommonModule], template: `
16509
16613
  <div [class]="computedContainerClass">
16510
- <div class="flex" [class.flex-col]="direction === 'vertical'" [class.flex-row]="direction === 'horizontal'">
16614
+ <div class="flex h-full w-full" [class.flex-col]="direction === 'vertical'" [class.flex-row]="direction === 'horizontal'">
16511
16615
  <ng-content></ng-content>
16512
16616
  </div>
16513
16617
  </div>
16514
- `, styles: [":host{display:block}\n"] }]
16618
+ `, styles: [":host{display:block;width:100%;height:100%}\n"] }]
16515
16619
  }], propDecorators: { direction: [{
16516
16620
  type: Input
16517
16621
  }], class: [{
@@ -16915,11 +17019,16 @@ class ContextMenuService {
16915
17019
  })
16916
17020
  ]
16917
17021
  });
17022
+ // Position via left/top, not transform: the menu's own
17023
+ // data-[state=open]:zoom-in-95/slide-in-from-top-2 enter animation also
17024
+ // drives `transform`, and a CSS animation overrides whatever an inline
17025
+ // transform says for as long as it's running — so a translate() here
17026
+ // would get clobbered by the animation and only "snap" into place once
17027
+ // it finishes, which is exactly the top-left-then-jump flash this avoids.
16918
17028
  Object.assign(menuElement.style, {
16919
17029
  position: 'fixed',
16920
- left: '0',
16921
- top: '0',
16922
- transform: `translate(${Math.round(x)}px, ${Math.round(y)}px)`
17030
+ left: `${Math.round(x)}px`,
17031
+ top: `${Math.round(y)}px`,
16923
17032
  });
16924
17033
  }
16925
17034
  async positionSubmenu(triggerElement, submenuElement) {
@@ -16948,9 +17057,8 @@ class ContextMenuService {
16948
17057
  });
16949
17058
  Object.assign(submenuElement.style, {
16950
17059
  position: 'fixed',
16951
- left: '0',
16952
- top: '0',
16953
- transform: `translate(${Math.round(x)}px, ${Math.round(y)}px)`
17060
+ left: `${Math.round(x)}px`,
17061
+ top: `${Math.round(y)}px`,
16954
17062
  });
16955
17063
  }
16956
17064
  performAction(actionId) {
@@ -31665,5 +31773,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
31665
31773
  * Generated bundle index. Do not edit.
31666
31774
  */
31667
31775
 
31668
- export { AccordionComponent, AccordionItemComponent, AlertComponent, AlertDialogActionComponent, AlertDialogCancelComponent, AlertDialogComponent, AlertDialogContentComponent, AlertDialogDescriptionComponent, AlertDialogDynamicComponent, AlertDialogFooterComponent, AlertDialogHeaderComponent, AlertDialogPortalComponent, AlertDialogRef, AlertDialogService, AlertDialogTitleComponent, AlertDialogTriggerComponent, AspectRatioComponent, AttachmentActionsComponent, AttachmentComponent, AttachmentGroupComponent, AvatarComponent, AvatarFallbackComponent, BASE_PALETTES, BadgeComponent, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbLinkComponent, BreadcrumbSeparatorComponent, BubbleActionsComponent, BubbleComponent, BubbleReactionsComponent, ButtonComponent, ButtonGroupComponent, CHART_COLOR_LIMIT, CHART_OVERFLOW_COLOR, CalendarComponent, CardComponent, CardContentComponent, CardDescriptionComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CarouselComponent, CarouselContainerDirective, CarouselContentDirective, CarouselContext, CarouselItemDirective, CarouselNextDirective, CarouselPreviousDirective, ChainOfThoughtComponent, ChainOfThoughtContentComponent, ChainOfThoughtHeaderComponent, ChainOfThoughtSearchResultComponent, ChainOfThoughtSearchResultsComponent, ChainOfThoughtService, ChainOfThoughtStepComponent, ChartAreaComponent, ChartBarComponent, ChartChild, ChartColorScale, ChartComponent, ChartGridComponent, ChartLegendComponent, ChartLineComponent, ChartPieComponent, ChartService, ChartTableComponent, ChartTooltipComponent, ChartXAxisComponent, ChartYAxisComponent, CheckboxComponent, CheckpointComponent, CollapsibleComponent, CollapsibleContentComponent, CollapsibleTriggerComponent, ComboboxComponent, CommandComponent, CommandDialogComponent, CommandEmptyComponent, CommandGroupComponent, CommandInputComponent, CommandItemComponent, CommandListComponent, CommandSeparatorComponent, CommandService, CommandShortcutComponent, ConfirmationComponent, ContextComponent, ContextContentComponent, ContextMenuComponent, ContextMenuService, ContextMenuTriggerDirective, ContextService, ContextTriggerComponent, ConversationComponent, ConversationContentComponent, ConversationEmptyStateComponent, ConversationScrollButtonComponent, ConversationService, CountryCodesService, CountrySelectorComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DateTimePickerComponent, DirectionDirective, DirectionService, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, EmptyStateComponent, FieldComponent, FieldContentComponent, FieldDescriptionComponent, FieldErrorComponent, FieldGroupComponent, FieldLabelComponent, FieldLegendComponent, FieldSeparatorComponent, FieldSetComponent, FieldTitleComponent, HoverCardComponent, HoverCardContentComponent, HoverCardTriggerComponent, InlineCitationCardComponent, InlineCitationComponent, InlineCitationQuoteComponent, InputComponent, InputGroupAddonComponent, InputGroupButtonComponent, InputGroupComponent, InputGroupInputComponent, InputGroupTextComponent, InputGroupTextareaComponent, ItemActionsComponent, ItemComponent, ItemContentComponent, ItemDescriptionComponent, ItemFooterComponent, ItemGroupComponent, ItemHeaderComponent, ItemMediaComponent, ItemTitleComponent, KbdComponent, KbdGroupComponent, LabelComponent, MarkerComponent, MarkerGroupComponent, MaskedInputComponent, MenubarComponent, MenubarContentComponent, MenubarItemComponent, MenubarLabelComponent, MenubarMenuComponent, MenubarSeparatorComponent, MenubarService, MenubarTriggerComponent, MessageAlignService, MessageAvatarComponent, MessageComponent, MessageContentComponent, MessageFooterComponent, MessageGroupComponent, MessageHeaderComponent, MessageScrollerButtonComponent, MessageScrollerComponent, MessageScrollerContentComponent, MessageScrollerItemDirective, MessageScrollerService, MessageScrollerViewportComponent, Modal, ModalComponent, ModalRef, ModalService, ModalStackService, ModelSelectorComponent, MultiSelectComponent, NativeSelectComponent, NavigationMenuComponent, NavigationMenuContentComponent, NavigationMenuItemComponent, NavigationMenuLinkComponent, NavigationMenuListComponent, NavigationMenuService, NavigationMenuTriggerComponent, OtpComponent, OtpGroupComponent, OtpSlotComponent, PaginationComponent, PhoneNumberInputComponent, PhoneNumberService, PlanComponent, PlanService, PlanStepComponent, PopoverComponent, PopoverContentComponent, ProgressComponent, PromptInputComponent, PromptInputService, PromptInputSubmitComponent, PromptInputToolbarComponent, PromptInputToolsComponent, QueueComponent, QueueItemComponent, QueueService, RadioGroupComponent, RadioItemComponent, RadioService, RangeCalendarComponent, ReasoningComponent, ReasoningContentComponent, ReasoningService, ReasoningTriggerComponent, ResizableComponent, ResizablePanelComponent, ResizablePanelItemComponent, ScrollAreaComponent, SegmentComponent, SegmentComponent as SegmentedComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SelectService, SeparatorComponent, SheetComponent, SheetContentComponent, SheetDescriptionComponent, SheetFooterComponent, SheetHeaderComponent, SheetRef, SheetService, SheetTitleComponent, SheetTriggerComponent, SheetWrapperComponent, ShimmerComponent, SidebarComponent, SkeletonComponent, SliderComponent, SourceComponent, SourcesComponent, SourcesContentComponent, SourcesService, SourcesTriggerComponent, SpinnerComponent, SuggestionComponent, SuggestionsComponent, SuggestionsService, SwitchComponent, TOLLE_CONFIG, TableBodyDirective, TableCaptionDirective, TableCellDirective, TableComponent, TableFooterDirective, TableHeadDirective, TableHeaderDirective, TableRowDirective, TabsComponent, TabsContentComponent, TabsListComponent, TabsTriggerComponent, TagInputComponent, TaskComponent, TaskContentComponent, TaskItemComponent, TaskItemFileComponent, TaskService, TaskTriggerComponent, TextareaComponent, ThemeService, TimeColumnsComponent, TimePickerComponent, ToastContainerComponent, ToastService, ToggleComponent, ToggleGroupComponent, ToggleGroupItemComponent, TolleCellDirective, ToolComponent, ToolHeaderComponent, ToolInputComponent, ToolOutputComponent, ToolPayloadBase, ToolService, TooltipDirective, TypographyComponent, arcPath, barPath, buildPath, cn, contrastTriplet, darkenColor, decimalsFor, formatTimeString, formatTokens, from12Hour, generateBaseCss, generateChartCss, generateChartRamp, generateThemeCss, getContrastColor, hexToHsl, hexToRgb, hslToHex, lightenColor, monotoneTangents, niceScale, niceStep, parseTimeString, polarPoint, provideTolleConfig, radiusScale, rgbTriplet, timePartsToSeconds, to12Hour };
31776
+ export { AccordionComponent, AccordionItemComponent, AlertComponent, AlertDialogActionComponent, AlertDialogCancelComponent, AlertDialogComponent, AlertDialogContentComponent, AlertDialogDescriptionComponent, AlertDialogDynamicComponent, AlertDialogFooterComponent, AlertDialogHeaderComponent, AlertDialogPortalComponent, AlertDialogRef, AlertDialogService, AlertDialogTitleComponent, AlertDialogTriggerComponent, AspectRatioComponent, AttachmentActionsComponent, AttachmentComponent, AttachmentGroupComponent, AvatarComponent, AvatarFallbackComponent, BASE_PALETTES, BadgeComponent, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbLinkComponent, BreadcrumbSeparatorComponent, BubbleActionsComponent, BubbleComponent, BubbleReactionsComponent, ButtonComponent, ButtonGroupComponent, CHART_COLOR_LIMIT, CHART_OVERFLOW_COLOR, CLOSE_FALLBACK_MS, CalendarComponent, CardComponent, CardContentComponent, CardDescriptionComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CarouselComponent, CarouselContainerDirective, CarouselContentDirective, CarouselContext, CarouselItemDirective, CarouselNextDirective, CarouselPreviousDirective, ChainOfThoughtComponent, ChainOfThoughtContentComponent, ChainOfThoughtHeaderComponent, ChainOfThoughtSearchResultComponent, ChainOfThoughtSearchResultsComponent, ChainOfThoughtService, ChainOfThoughtStepComponent, ChartAreaComponent, ChartBarComponent, ChartChild, ChartColorScale, ChartComponent, ChartGridComponent, ChartLegendComponent, ChartLineComponent, ChartPieComponent, ChartService, ChartTableComponent, ChartTooltipComponent, ChartXAxisComponent, ChartYAxisComponent, CheckboxComponent, CheckpointComponent, CollapsibleComponent, CollapsibleContentComponent, CollapsibleTriggerComponent, ComboboxComponent, CommandComponent, CommandDialogComponent, CommandEmptyComponent, CommandGroupComponent, CommandInputComponent, CommandItemComponent, CommandListComponent, CommandSeparatorComponent, CommandService, CommandShortcutComponent, ConfirmationComponent, ContextComponent, ContextContentComponent, ContextMenuComponent, ContextMenuService, ContextMenuTriggerDirective, ContextService, ContextTriggerComponent, ConversationComponent, ConversationContentComponent, ConversationEmptyStateComponent, ConversationScrollButtonComponent, ConversationService, CountryCodesService, CountrySelectorComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DateTimePickerComponent, DirectionDirective, DirectionService, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, EmptyStateComponent, FieldComponent, FieldContentComponent, FieldDescriptionComponent, FieldErrorComponent, FieldGroupComponent, FieldLabelComponent, FieldLegendComponent, FieldSeparatorComponent, FieldSetComponent, FieldTitleComponent, HoverCardComponent, HoverCardContentComponent, HoverCardTriggerComponent, InlineCitationCardComponent, InlineCitationComponent, InlineCitationQuoteComponent, InputComponent, InputGroupAddonComponent, InputGroupButtonComponent, InputGroupComponent, InputGroupInputComponent, InputGroupTextComponent, InputGroupTextareaComponent, ItemActionsComponent, ItemComponent, ItemContentComponent, ItemDescriptionComponent, ItemFooterComponent, ItemGroupComponent, ItemHeaderComponent, ItemMediaComponent, ItemTitleComponent, KbdComponent, KbdGroupComponent, LabelComponent, MarkerComponent, MarkerGroupComponent, MaskedInputComponent, MenubarComponent, MenubarContentComponent, MenubarItemComponent, MenubarLabelComponent, MenubarMenuComponent, MenubarSeparatorComponent, MenubarService, MenubarTriggerComponent, MessageAlignService, MessageAvatarComponent, MessageComponent, MessageContentComponent, MessageFooterComponent, MessageGroupComponent, MessageHeaderComponent, MessageScrollerButtonComponent, MessageScrollerComponent, MessageScrollerContentComponent, MessageScrollerItemDirective, MessageScrollerService, MessageScrollerViewportComponent, ModalComponent, ModalRef, ModalService, ModalStackService, ModelSelectorComponent, MultiSelectComponent, NativeSelectComponent, NavigationMenuComponent, NavigationMenuContentComponent, NavigationMenuItemComponent, NavigationMenuLinkComponent, NavigationMenuListComponent, NavigationMenuService, NavigationMenuTriggerComponent, OtpComponent, OtpGroupComponent, OtpSlotComponent, PaginationComponent, PhoneNumberInputComponent, PhoneNumberService, PlanComponent, PlanService, PlanStepComponent, PopoverComponent, PopoverContentComponent, ProgressComponent, PromptInputComponent, PromptInputService, PromptInputSubmitComponent, PromptInputToolbarComponent, PromptInputToolsComponent, QueueComponent, QueueItemComponent, QueueService, RadioGroupComponent, RadioItemComponent, RadioService, RangeCalendarComponent, ReasoningComponent, ReasoningContentComponent, ReasoningService, ReasoningTriggerComponent, ResizableComponent, ResizablePanelComponent, ResizablePanelItemComponent, ScrollAreaComponent, SegmentComponent, SegmentComponent as SegmentedComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SelectService, SeparatorComponent, SheetComponent, SheetContentComponent, SheetDescriptionComponent, SheetFooterComponent, SheetHeaderComponent, SheetRef, SheetService, SheetTitleComponent, SheetTriggerComponent, SheetWrapperComponent, ShimmerComponent, SidebarComponent, SkeletonComponent, SliderComponent, SourceComponent, SourcesComponent, SourcesContentComponent, SourcesService, SourcesTriggerComponent, SpinnerComponent, SuggestionComponent, SuggestionsComponent, SuggestionsService, SwitchComponent, TOLLE_CONFIG, TableBodyDirective, TableCaptionDirective, TableCellDirective, TableComponent, TableFooterDirective, TableHeadDirective, TableHeaderDirective, TableRowDirective, TabsComponent, TabsContentComponent, TabsListComponent, TabsTriggerComponent, TagInputComponent, TaskComponent, TaskContentComponent, TaskItemComponent, TaskItemFileComponent, TaskService, TaskTriggerComponent, TextareaComponent, ThemeService, TimeColumnsComponent, TimePickerComponent, ToastContainerComponent, ToastService, ToggleComponent, ToggleGroupComponent, ToggleGroupItemComponent, TolleCellDirective, ToolComponent, ToolHeaderComponent, ToolInputComponent, ToolOutputComponent, ToolPayloadBase, ToolService, TooltipDirective, TypographyComponent, arcPath, barPath, buildPath, cn, contrastTriplet, darkenColor, decimalsFor, formatTimeString, formatTokens, from12Hour, generateBaseCss, generateChartCss, generateChartRamp, generateThemeCss, getContrastColor, hexToHsl, hexToRgb, hslToHex, lightenColor, monotoneTangents, niceScale, niceStep, parseTimeString, polarPoint, provideTolleConfig, radiusScale, rgbTriplet, timePartsToSeconds, to12Hour };
31669
31777
  //# sourceMappingURL=tolle-ui.mjs.map