@ethlete/core 5.0.0-next.15 → 5.0.0-next.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ethlete/core
2
2
 
3
+ ## 5.0.0-next.16
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2999](https://github.com/ethlete-io/ethdk/pull/2999) [`0232803`](https://github.com/ethlete-io/ethdk/commit/0232803afcee04ddc5d8c6ab57a8e920a908e1ac) Thanks [@github-actions](https://github.com/apps/github-actions)! - Update overlay runtime to support stategies
8
+
3
9
  ## 5.0.0-next.15
4
10
 
5
11
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, NgZone, signal, isSignal, untracked, DOCUMENT, linkedSignal, isDevMode, computed, afterNextRender, effect, Injector, booleanAttribute, numberAttribute, runInInjectionContext, RendererStyleFlags2, PLATFORM_ID, ApplicationRef, RendererFactory2, EnvironmentInjector, createComponent, model, ViewContainerRef, input, output, inputBinding, Pipe, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, NgZone, signal, isSignal, untracked, DOCUMENT, linkedSignal, isDevMode, computed, afterNextRender, effect, EnvironmentInjector, runInInjectionContext, Injector, booleanAttribute, numberAttribute, RendererStyleFlags2, PLATFORM_ID, ApplicationRef, RendererFactory2, createComponent, model, ViewContainerRef, input, output, inputBinding, outputBinding, Pipe, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { takeUntilDestroyed, toSignal, toObservable, outputFromObservable } from '@angular/core/rxjs-interop';
4
4
  import { Subject, BehaviorSubject, debounceTime, combineLatest, map, merge, fromEvent, filter, tap, switchMap, startWith, of, timer, takeUntil, pairwise, distinctUntilChanged, take, Observable, concatMap, EMPTY, concat, defer, exhaustMap, share } from 'rxjs';
5
5
  import { FormGroup, FormArray, FormControl } from '@angular/forms';
@@ -13,6 +13,30 @@ import { ComponentPortal } from '@angular/cdk/portal';
13
13
  import { autoUpdate, computePosition, offset, flip, size, shift, limitShift, arrow, hide } from '@floating-ui/dom';
14
14
  import { Title, Meta, DomSanitizer } from '@angular/platform-browser';
15
15
 
16
+ const ANIMATION_DEBUG_STORAGE_KEY = 'et-overlay-debug';
17
+ let cachedEnabled = null;
18
+ /**
19
+ * Debug logging for overlay and animation lifecycle internals.
20
+ * Enable via `localStorage.setItem('et-overlay-debug', 'true')` and reload.
21
+ */
22
+ const isAnimationDebugEnabled = () => {
23
+ if (cachedEnabled === null) {
24
+ try {
25
+ cachedEnabled = globalThis.localStorage?.getItem(ANIMATION_DEBUG_STORAGE_KEY) === 'true';
26
+ }
27
+ catch {
28
+ cachedEnabled = false;
29
+ }
30
+ }
31
+ return cachedEnabled;
32
+ };
33
+ const animationDebugLog = (scope, ...args) => {
34
+ if (!isAnimationDebugEnabled())
35
+ return;
36
+ const timestamp = (globalThis.performance?.now() ?? 0).toFixed(1);
37
+ console.log(`\x1B[36m[et-overlay-debug ${timestamp}ms | ${scope}]\x1B[m`, ...args);
38
+ };
39
+
16
40
  const ANIMATABLE_TOKEN = new InjectionToken('ANIMATABLE_DIRECTIVE_TOKEN');
17
41
  class AnimatableDirective {
18
42
  constructor() {
@@ -31,7 +55,7 @@ class AnimatableDirective {
31
55
  this.isAnimating$ = this.totalActiveAnimationCount$.pipe(map((count) => count > 0));
32
56
  let didEmitStart = false;
33
57
  const el = this.elementRef.nativeElement;
34
- merge(merge(fromEvent(el, 'animationstart'), fromEvent(el, 'transitionstart')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'start')), merge(fromEvent(el, 'animationend'), fromEvent(el, 'transitionend')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'end')), merge(fromEvent(el, 'animationcancel'), fromEvent(el, 'transitioncancel')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'cancel')))
58
+ merge(merge(fromEvent(el, 'animationstart'), fromEvent(el, 'transitionrun')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'start')), merge(fromEvent(el, 'animationend'), fromEvent(el, 'transitionend')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'end')), merge(fromEvent(el, 'animationcancel'), fromEvent(el, 'transitioncancel')).pipe(filter((e) => e.target === el && !e.pseudoElement), map(() => 'cancel')))
35
59
  .pipe(tap((eventType) => {
36
60
  switch (eventType) {
37
61
  case 'start': {
@@ -40,6 +64,7 @@ class AnimatableDirective {
40
64
  if (startingNewBatch) {
41
65
  this.activeBatchTransitionId = this.pendingTransitionIds.shift();
42
66
  }
67
+ animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `start (count ${this.activeAnimationCount}, batch "${this.activeBatchTransitionId}", pending [${this.pendingTransitionIds.join(', ')}])`);
43
68
  if (!didEmitStart) {
44
69
  didEmitStart = true;
45
70
  this.animationStartSubject$.next();
@@ -50,6 +75,7 @@ class AnimatableDirective {
50
75
  case 'cancel': {
51
76
  if (this.activeAnimationCount > 0) {
52
77
  this.updateActiveAnimationCount(-1);
78
+ animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `${eventType} (count ${this.activeAnimationCount}, batch "${this.activeBatchTransitionId}")`);
53
79
  if (this.activeAnimationCount === 0 && didEmitStart) {
54
80
  didEmitStart = false;
55
81
  this.animationEndSubject$.next({
@@ -60,6 +86,7 @@ class AnimatableDirective {
60
86
  }
61
87
  }
62
88
  else {
89
+ animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `${eventType} ignored — count already 0 (start ${didEmitStart ? '' : 'not '}emitted)`);
63
90
  console.warn(`${el.tagName} received animation end/cancel event but activeAnimationCount is already 0. Start was ${didEmitStart ? '' : 'not '}emitted.`);
64
91
  }
65
92
  break;
@@ -1101,10 +1128,14 @@ const deferredSignal = (valueFn) => {
1101
1128
  return valueSignal;
1102
1129
  };
1103
1130
  const memoizeSignal = (factory) => {
1104
- let cached = null;
1131
+ const cache = new WeakMap();
1105
1132
  return () => {
1106
- if (!cached)
1107
- cached = factory();
1133
+ const envInjector = inject(EnvironmentInjector);
1134
+ let cached = cache.get(envInjector);
1135
+ if (!cached) {
1136
+ cached = runInInjectionContext(envInjector, factory);
1137
+ cache.set(envInjector, cached);
1138
+ }
1108
1139
  return cached;
1109
1140
  };
1110
1141
  };
@@ -2916,6 +2947,72 @@ const createSessionMemory = ({ key, parse, serialize }) => {
2916
2947
  };
2917
2948
  };
2918
2949
 
2950
+ const getClientXY = (event) => {
2951
+ if (event.type[0] === 't') {
2952
+ const touch = event.targetTouches[0] ?? event.changedTouches[0];
2953
+ return touch ? { clientX: touch.clientX, clientY: touch.clientY } : { clientX: 0, clientY: 0 };
2954
+ }
2955
+ return { clientX: event.clientX, clientY: event.clientY };
2956
+ };
2957
+ const createSwipeTracker = (startEvent) => {
2958
+ const { clientX: originClientX, clientY: originClientY } = getClientXY(startEvent);
2959
+ const startTime = Date.now();
2960
+ let movementX = 0;
2961
+ let movementY = 0;
2962
+ let isSwiping = false;
2963
+ let isScrolling = false;
2964
+ const update = (event) => {
2965
+ const { clientX, clientY } = getClientXY(event);
2966
+ movementX = clientX - originClientX;
2967
+ movementY = clientY - originClientY;
2968
+ const positiveMovementX = Math.abs(movementX);
2969
+ const positiveMovementY = Math.abs(movementY);
2970
+ if (!isSwiping && !isScrolling) {
2971
+ if (positiveMovementY > positiveMovementX) {
2972
+ isScrolling = true;
2973
+ }
2974
+ else {
2975
+ isSwiping = true;
2976
+ }
2977
+ }
2978
+ return {
2979
+ originClientX,
2980
+ originClientY,
2981
+ timestamp: startTime,
2982
+ movementX,
2983
+ movementY,
2984
+ positiveMovementX,
2985
+ positiveMovementY,
2986
+ isScrolling,
2987
+ isSwiping,
2988
+ };
2989
+ };
2990
+ const end = () => {
2991
+ const swipeTime = Math.max(1, Date.now() - startTime);
2992
+ const positiveMovementX = Math.abs(movementX);
2993
+ const positiveMovementY = Math.abs(movementY);
2994
+ const pixelPerSecondX = (movementX / swipeTime) * 1000;
2995
+ const pixelPerSecondY = (movementY / swipeTime) * 1000;
2996
+ return {
2997
+ movementX,
2998
+ movementY,
2999
+ positiveMovementX,
3000
+ positiveMovementY,
3001
+ pixelPerSecondX,
3002
+ pixelPerSecondY,
3003
+ positivePixelPerSecondX: Math.abs(pixelPerSecondX),
3004
+ positivePixelPerSecondY: Math.abs(pixelPerSecondY),
3005
+ originClientX,
3006
+ originClientY,
3007
+ };
3008
+ };
3009
+ const cancel = () => {
3010
+ movementX = 0;
3011
+ movementY = 0;
3012
+ };
3013
+ return { update, end, cancel };
3014
+ };
3015
+
2919
3016
  const [, injectAngularRootElement] = createRootProvider(() => {
2920
3017
  const appRef = inject(ApplicationRef);
2921
3018
  const rootElement = signal(null, ...(ngDevMode ? [{ debugName: "rootElement" }] : /* istanbul ignore next */ []));
@@ -3322,6 +3419,7 @@ class AnimatedLifecycleDirective {
3322
3419
  if (currentState === 'entering')
3323
3420
  return;
3324
3421
  if ((currentState === 'init' && !this.isConstructed) || this.skipNextEnter()) {
3422
+ this.debugLog('enter: instant (not constructed or skipNextEnter)', { currentState });
3325
3423
  this.updateState('entered');
3326
3424
  this.skipNextEnter.set(false);
3327
3425
  this.addClass(ANIMATION_CLASSES.enterDone);
@@ -3337,6 +3435,10 @@ class AnimatedLifecycleDirective {
3337
3435
  this.animatable.setTransitionId(transitionId);
3338
3436
  const skipAnimation = this.forcedAtFrameId !== null && this.forcedAtFrameId === this.currentFrameId;
3339
3437
  this.forcedAtFrameId = null;
3438
+ this.debugLog(`enter: ${skipAnimation ? 'skip (forced this frame)' : isInterrupting ? 'interrupting leave' : 'normal'}`, {
3439
+ currentState,
3440
+ transitionId,
3441
+ });
3340
3442
  if (skipAnimation) {
3341
3443
  this.removeClasses(ANIMATION_CLASSES.leaveFrom, ANIMATION_CLASSES.leaveActive, ANIMATION_CLASSES.leaveTo, ANIMATION_CLASSES.leaveInterrupt);
3342
3444
  this.updateState('entered');
@@ -3387,6 +3489,7 @@ class AnimatedLifecycleDirective {
3387
3489
  if (currentState === 'leaving')
3388
3490
  return;
3389
3491
  if (currentState === 'init') {
3492
+ this.debugLog('leave: instant (state is init, enter never ran)');
3390
3493
  this.updateState('left');
3391
3494
  this.addClass(ANIMATION_CLASSES.leaveDone);
3392
3495
  this.forcedAtFrameId = null;
@@ -3401,6 +3504,10 @@ class AnimatedLifecycleDirective {
3401
3504
  this.animatable.setTransitionId(transitionId);
3402
3505
  const skipAnimation = this.forcedAtFrameId !== null && this.forcedAtFrameId === this.currentFrameId;
3403
3506
  this.forcedAtFrameId = null;
3507
+ this.debugLog(`leave: ${skipAnimation ? 'skip (forced this frame)' : isInterrupting ? 'interrupting enter' : 'normal'}`, {
3508
+ currentState,
3509
+ transitionId,
3510
+ });
3404
3511
  if (skipAnimation) {
3405
3512
  this.removeClasses(ANIMATION_CLASSES.enterFrom, ANIMATION_CLASSES.enterActive, ANIMATION_CLASSES.enterTo, ANIMATION_CLASSES.enterInterrupt);
3406
3513
  this.updateState('left');
@@ -3481,21 +3588,33 @@ class AnimatedLifecycleDirective {
3481
3588
  addClasses.forEach((cls) => this.addClass(cls));
3482
3589
  fromNextFrame()
3483
3590
  .pipe(switchMap(() => this.animatable.isAnimating$), take(1), switchMap((isAnimating) => {
3591
+ if (isAnimating) {
3592
+ return of(true);
3593
+ }
3594
+ this.debugLog(`${transitionId}: interrupt found no running transition, re-checking next frame`);
3595
+ return fromNextFrame().pipe(switchMap(() => this.animatable.isAnimating$), take(1));
3596
+ }), take(1), switchMap((isAnimating) => {
3484
3597
  if (!isAnimating && this.state$.value === expectedState) {
3598
+ this.debugLog(`${transitionId}: interrupt completes INSTANTLY (no transition running after class swap)`);
3485
3599
  return of({ cancelled: false, transitionId });
3486
3600
  }
3601
+ this.debugLog(`${transitionId}: interrupt waiting for animation end`, { isAnimating });
3487
3602
  return this.animatable.animationEnd$.pipe(switchMap((e) => {
3488
3603
  if (e.transitionId === transitionId) {
3489
3604
  return of(e);
3490
3605
  }
3491
3606
  return this.animatable.isAnimating$.pipe(take(1), switchMap((stillAnimating) => {
3492
3607
  if (!stillAnimating && this.state$.value === expectedState) {
3608
+ this.debugLog(`${transitionId}: interrupt completes via foreign animation end (batch id was "${e.transitionId}")`, { stillAnimating });
3493
3609
  return of({ cancelled: false, transitionId });
3494
3610
  }
3495
3611
  return of(null);
3496
3612
  }));
3497
3613
  }), filter((e) => e !== null && e.transitionId === transitionId));
3498
- }), filter((e) => this.state$.value === expectedState && !e.cancelled), tap(() => onComplete()), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
3614
+ }), filter((e) => this.state$.value === expectedState && !e.cancelled), tap(() => {
3615
+ this.debugLog(`${transitionId}: interrupt complete`);
3616
+ onComplete();
3617
+ }), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
3499
3618
  .subscribe();
3500
3619
  }
3501
3620
  addClass(className) {
@@ -3508,8 +3627,19 @@ class AnimatedLifecycleDirective {
3508
3627
  this.renderer.removeClass(this.element, ...classNames);
3509
3628
  }
3510
3629
  updateState(newState) {
3630
+ this.debugLog(`state: ${this.state$.value} → ${newState}`);
3511
3631
  this.state$.next(newState);
3512
3632
  }
3633
+ debugLog(message, data) {
3634
+ const el = this.element;
3635
+ const scope = `lifecycle ${el.tagName.toLowerCase()}${el.classList.contains('et-overlay') ? '.et-overlay' : ''}`;
3636
+ if (data) {
3637
+ animationDebugLog(scope, message, data);
3638
+ }
3639
+ else {
3640
+ animationDebugLog(scope, message);
3641
+ }
3642
+ }
3513
3643
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedLifecycleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3514
3644
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: AnimatedLifecycleDirective, isStandalone: true, selector: "[etAnimatedLifecycle]", inputs: { skipNextEnter: { classPropertyName: "skipNextEnter", publicName: "skipNextEnter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stateChange: "stateChange", skipNextEnter: "skipNextEnterChange" }, host: { classAttribute: "et-force-invisible" }, providers: [
3515
3645
  {
@@ -4053,15 +4183,21 @@ class ScrollObserverDirective {
4053
4183
  constructor() {
4054
4184
  this.elementRef = inject(ElementRef);
4055
4185
  this.enabled = model(true, ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
4186
+ this.enabledValue = computed(() => {
4187
+ const enabled = this.enabled();
4188
+ if (isSignal(enabled))
4189
+ return enabled();
4190
+ return enabled;
4191
+ }, ...(ngDevMode ? [{ debugName: "enabledValue" }] : /* istanbul ignore next */ []));
4056
4192
  this._startEl = signal(null, ...(ngDevMode ? [{ debugName: "_startEl" }] : /* istanbul ignore next */ []));
4057
4193
  this._endEl = signal(null, ...(ngDevMode ? [{ debugName: "_endEl" }] : /* istanbul ignore next */ []));
4058
4194
  this._startIntersection = signalElementIntersection(this._startEl, {
4059
4195
  root: this.elementRef,
4060
- enabled: this.enabled,
4196
+ enabled: this.enabledValue,
4061
4197
  });
4062
4198
  this._endIntersection = signalElementIntersection(this._endEl, {
4063
4199
  root: this.elementRef,
4064
- enabled: this.enabled,
4200
+ enabled: this.enabledValue,
4065
4201
  });
4066
4202
  this.isAtStart = computed(() => this._startIntersection()[0]?.isIntersecting ?? false, ...(ngDevMode ? [{ debugName: "isAtStart" }] : /* istanbul ignore next */ []));
4067
4203
  this.isAtEnd = computed(() => this._endIntersection()[0]?.isIntersecting ?? false, ...(ngDevMode ? [{ debugName: "isAtEnd" }] : /* istanbul ignore next */ []));
@@ -4288,8 +4424,50 @@ const applyCenteredPosition = (hostElement, paneElement, renderer, _config) => {
4288
4424
  position: 'relative',
4289
4425
  });
4290
4426
  };
4427
+ const applyGlobalPosition = (hostElement, paneElement, renderer, config) => {
4428
+ renderer.setStyle(hostElement, {
4429
+ display: 'grid',
4430
+ // an explicit full-size cell keeps the grid area definite so percentage
4431
+ // based pane sizes (e.g. max-height: calc(100% - 72px)) can resolve
4432
+ gridTemplateRows: '100%',
4433
+ gridTemplateColumns: '100%',
4434
+ placeItems: `${config.vertical ?? 'center'} ${config.horizontal ?? 'center'}`,
4435
+ padding: config.padding ?? '0',
4436
+ });
4437
+ renderer.setStyle(paneElement, {
4438
+ position: 'relative',
4439
+ });
4440
+ };
4441
+ /**
4442
+ * Clears every inline style any position strategy kind may have set and
4443
+ * restores the base element styles, so a different strategy can be applied afterwards.
4444
+ */
4445
+ const resetPositioningStyles = (config, hostElement, paneElement, renderer) => {
4446
+ renderer.setStyle(hostElement, {
4447
+ gridTemplateRows: null,
4448
+ gridTemplateColumns: null,
4449
+ placeItems: null,
4450
+ padding: null,
4451
+ overflow: null,
4452
+ });
4453
+ renderer.setStyle(paneElement, {
4454
+ position: null,
4455
+ top: null,
4456
+ left: null,
4457
+ width: null,
4458
+ transform: null,
4459
+ visibility: null,
4460
+ });
4461
+ renderer.setCssProperties(paneElement, {
4462
+ '--et-overlay-max-width': null,
4463
+ '--et-overlay-max-height': null,
4464
+ '--et-overlay-anchored-x': null,
4465
+ '--et-overlay-anchored-y': null,
4466
+ });
4467
+ renderer.removeAttribute(paneElement, 'data-overlay-placement');
4468
+ setBaseElementStyles(config, hostElement, paneElement, renderer);
4469
+ };
4291
4470
  const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, renderer) => {
4292
- const arrowElement = paneElement.querySelector('[et-floating-arrow]');
4293
4471
  renderer.setStyle(paneElement, {
4294
4472
  position: 'absolute',
4295
4473
  top: '0',
@@ -4297,6 +4475,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
4297
4475
  width: strategy.mirrorWidth ? `${strategy.referenceElement.offsetWidth}px` : 'max-content',
4298
4476
  });
4299
4477
  const cleanup = autoUpdate(strategy.referenceElement, paneElement, () => {
4478
+ const arrowElement = paneElement.querySelector('[et-floating-arrow]');
4300
4479
  const middleware = [];
4301
4480
  middleware.push(offset(strategy.offset ?? 8));
4302
4481
  middleware.push(flip({
@@ -4340,6 +4519,11 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
4340
4519
  transform: `translate3d(${x}px, ${y}px, 0)`,
4341
4520
  width: strategy.mirrorWidth ? `${strategy.referenceElement.offsetWidth}px` : null,
4342
4521
  });
4522
+ // exposed so animations can compose their transforms with the anchored position
4523
+ renderer.setCssProperties(paneElement, {
4524
+ '--et-overlay-anchored-x': `${x}px`,
4525
+ '--et-overlay-anchored-y': `${y}px`,
4526
+ });
4343
4527
  renderer.setAttribute(paneElement, 'data-overlay-placement', placement);
4344
4528
  if (arrowElement && middlewareData.arrow) {
4345
4529
  renderer.setCssProperty(arrowElement, '--et-floating-arrow-translate', `translate3d(${middlewareData.arrow.x ?? 0}px, ${middlewareData.arrow.y ?? 0}px, 0)`);
@@ -4371,6 +4555,10 @@ const setupPositioning = (config, hostElement, paneElement, overlayRef, renderer
4371
4555
  });
4372
4556
  return createAnchoredPositionCleanup(strategy, paneElement, overlayRef, renderer);
4373
4557
  }
4558
+ if (strategy.kind === 'global') {
4559
+ applyGlobalPosition(hostElement, paneElement, renderer, strategy);
4560
+ return () => undefined;
4561
+ }
4374
4562
  applyCenteredPosition(hostElement, paneElement, renderer, strategy);
4375
4563
  return () => undefined;
4376
4564
  };
@@ -4378,6 +4566,7 @@ const setupPositioning = (config, hostElement, paneElement, overlayRef, renderer
4378
4566
  const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
4379
4567
  const _state = signal('mounting', ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
4380
4568
  const _componentInstance = signal(null, ...(ngDevMode ? [{ debugName: "_componentInstance" }] : /* istanbul ignore next */ []));
4569
+ let positionUpdater = null;
4381
4570
  const beforeOpenedSubject = new Subject();
4382
4571
  const afterOpenedSubject = new Subject();
4383
4572
  const beforeClosedSubject = new Subject();
@@ -4411,6 +4600,16 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
4411
4600
  attachComponentRef(componentRef) {
4412
4601
  _componentInstance.set(componentRef.instance);
4413
4602
  },
4603
+ /** @internal */
4604
+ attachPositionUpdater(updater) {
4605
+ positionUpdater = updater;
4606
+ },
4607
+ updatePositionStrategy(strategy) {
4608
+ if (_state() === 'closing' || _state() === 'closed') {
4609
+ return;
4610
+ }
4611
+ positionUpdater?.(strategy);
4612
+ },
4414
4613
  markOpened() {
4415
4614
  if (_state() !== 'mounting') {
4416
4615
  return;
@@ -4449,10 +4648,18 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4449
4648
  const openEntriesState = signal([], ...(ngDevMode ? [{ debugName: "openEntriesState" }] : /* istanbul ignore next */ []));
4450
4649
  const openEntries = computed(() => openEntriesState(), ...(ngDevMode ? [{ debugName: "openEntries" }] : /* istanbul ignore next */ []));
4451
4650
  let rootElement = null;
4651
+ // Synchronous teardown for each currently-mounted overlay, run when the runtime's injector is
4652
+ // destroyed (app teardown). Registered on mount, removed once the overlay is destroyed normally.
4653
+ const mountedTeardowns = new Set();
4452
4654
  const getRootElement = () => {
4453
4655
  if (rootElement) {
4454
4656
  return rootElement;
4455
4657
  }
4658
+ // A previous Angular app (e.g. the one that existed before a Storybook HMR update or story
4659
+ // switch) may have left its runtime root orphaned in <body> if it was torn down mid-animation.
4660
+ // Such a node keeps a backdrop/pane on screen and blocks pointer events, so clear any stragglers
4661
+ // before creating ours.
4662
+ document.querySelectorAll('.et-overlay-runtime-root').forEach((el) => el.remove());
4456
4663
  rootElement = renderer.createElement('div');
4457
4664
  renderer.addClass(rootElement, 'et-overlay-runtime-root');
4458
4665
  renderer.setStyle(rootElement, {
@@ -4495,7 +4702,6 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4495
4702
  const previousFocusedElement = isHTMLElement(document.activeElement) ? document.activeElement : null;
4496
4703
  const autoFocus = config.autoFocus ?? 'first-tabbable';
4497
4704
  renderer.addClass(hostElement, 'et-overlay-runtime-entry');
4498
- renderer.addClass(paneElement, 'et-overlay-runtime-pane');
4499
4705
  setBaseElementStyles(config, hostElement, paneElement, renderer);
4500
4706
  renderer.setAttributes(hostElement, {
4501
4707
  'data-overlay-id': config.id,
@@ -4507,7 +4713,6 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4507
4713
  'aria-label': config.ariaLabel ?? null,
4508
4714
  });
4509
4715
  renderer.addClass(hostElement, ...(config.hostClass ?? []));
4510
- renderer.addClass(paneElement, ...(config.paneClass ?? []));
4511
4716
  if (backdropElement) {
4512
4717
  renderer.addClass(backdropElement, 'et-overlay-runtime-backdrop');
4513
4718
  setBackdropStyles(backdropElement, renderer);
@@ -4523,6 +4728,10 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4523
4728
  backdropElement,
4524
4729
  paneElement,
4525
4730
  }, (result, source) => beginClose({ result, source }));
4731
+ animationDebugLog(`runtime ${config.id}`, 'mount');
4732
+ // matches the previous overlay behavior: escape/outside-pointer closes are
4733
+ // ignored until the enter transition has started plus one frame
4734
+ let interactiveCloseReady = false;
4526
4735
  const cleanupFns = [];
4527
4736
  const parentInjector = config.injector ?? config.viewContainerRef?.injector ?? environmentInjector;
4528
4737
  const elementInjector = Injector.create({
@@ -4533,15 +4742,31 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4533
4742
  environmentInjector,
4534
4743
  elementInjector,
4535
4744
  hostElement: paneElement,
4536
- bindings: Object.entries(config.inputBindings ?? {}).map(([key, value]) => inputBinding(key, () => value)),
4745
+ bindings: [
4746
+ ...Object.entries(config.inputBindings ?? {}).map(([key, value]) => inputBinding(key, () => value)),
4747
+ ...Object.entries(config.outputBindings ?? {}).map(([key, listener]) => outputBinding(key, listener)),
4748
+ ],
4537
4749
  });
4750
+ // pane classes are applied after component creation — Angular replaces the host
4751
+ // element's class attribute with the component's static host class on creation
4752
+ renderer.addClass(paneElement, 'et-overlay-runtime-pane', ...(config.paneClass ?? []));
4538
4753
  appRef.attachView(componentRef.hostView);
4539
4754
  overlayRef.attachComponentRef(componentRef);
4540
4755
  overlayRef.beforeOpenedSubject.next();
4541
4756
  overlayRef.beforeOpenedSubject.complete();
4542
4757
  openEntriesState.update((entries) => [...entries, overlayRef]);
4543
- cleanupFns.push(setupPositioning(config, hostElement, paneElement, overlayRef, renderer));
4758
+ let positionCleanup = setupPositioning(config, hostElement, paneElement, overlayRef, renderer);
4759
+ cleanupFns.push(() => positionCleanup());
4760
+ let currentPositionStrategy = config.positionStrategy;
4761
+ const getOriginElement = () => currentPositionStrategy?.kind === 'anchored' ? currentPositionStrategy.referenceElement : null;
4762
+ overlayRef.attachPositionUpdater((strategy) => {
4763
+ currentPositionStrategy = strategy;
4764
+ positionCleanup();
4765
+ resetPositioningStyles(config, hostElement, paneElement, renderer);
4766
+ positionCleanup = setupPositioning({ ...config, positionStrategy: strategy }, hostElement, paneElement, overlayRef, renderer);
4767
+ });
4544
4768
  const destroyMountedOverlay = (closeEvent) => {
4769
+ animationDebugLog(`runtime ${config.id}`, `destroy (source "${closeEvent.source}")`);
4545
4770
  cleanupFns.forEach((cleanup) => cleanup());
4546
4771
  appRef.detachView(componentRef.hostView);
4547
4772
  componentRef.destroy();
@@ -4556,16 +4781,27 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4556
4781
  }
4557
4782
  overlayRef.finishClose(closeEvent);
4558
4783
  };
4784
+ // Allows the runtime to synchronously destroy this overlay on app teardown, bypassing the
4785
+ // async leave animation (whose completion callback would never fire once the app is gone).
4786
+ const forceTeardown = () => destroyMountedOverlay({ result: undefined, source: 'api' });
4787
+ mountedTeardowns.add(forceTeardown);
4788
+ cleanupFns.push(() => mountedTeardowns.delete(forceTeardown));
4559
4789
  const beginClose = (closeEvent) => {
4560
4790
  if (!overlayRef.beginClose(closeEvent)) {
4561
4791
  return;
4562
4792
  }
4563
4793
  const lifecycle = getAnimatedLifecycle(componentRef);
4794
+ animationDebugLog(`runtime ${config.id}`, `close requested (source "${closeEvent.source}", lifecycle state "${lifecycle?.state$.value ?? 'none'}", delegate ${config.animationDelegate?.leave ? 'yes' : 'no'})`);
4564
4795
  if (!lifecycle) {
4565
4796
  destroyMountedOverlay(closeEvent);
4566
4797
  return;
4567
4798
  }
4568
- lifecycle.leave();
4799
+ if (config.animationDelegate?.leave) {
4800
+ config.animationDelegate.leave({ lifecycle, elements: overlayRef.elements, closeEvent });
4801
+ }
4802
+ else {
4803
+ lifecycle.leave();
4804
+ }
4569
4805
  lifecycle.state$
4570
4806
  .pipe(filter((state) => state === 'left'), take(1))
4571
4807
  .subscribe(() => {
@@ -4578,6 +4814,10 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4578
4814
  if (event.key !== 'Escape' || !isTopMost(overlayRef)) {
4579
4815
  return;
4580
4816
  }
4817
+ if (!interactiveCloseReady) {
4818
+ animationDebugLog(`runtime ${config.id}`, 'escape ignored (enter transition has not started yet)');
4819
+ return;
4820
+ }
4581
4821
  event.preventDefault();
4582
4822
  overlayRef.close(undefined, 'escape');
4583
4823
  };
@@ -4594,7 +4834,21 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4594
4834
  if (!isHTMLElement(target) || paneElement.contains(target)) {
4595
4835
  return;
4596
4836
  }
4837
+ if (!interactiveCloseReady) {
4838
+ animationDebugLog(`runtime ${config.id}`, 'outside pointer ignored (enter transition has not started yet)');
4839
+ return;
4840
+ }
4597
4841
  overlayRef.close(undefined, 'outside-pointer');
4842
+ const originElement = getOriginElement();
4843
+ if (originElement && originElement.contains(target)) {
4844
+ const swallowReopenClick = (clickEvent) => {
4845
+ if (isHTMLElement(clickEvent.target) && originElement.contains(clickEvent.target)) {
4846
+ clickEvent.stopImmediatePropagation();
4847
+ clickEvent.preventDefault();
4848
+ }
4849
+ };
4850
+ document.addEventListener('click', swallowReopenClick, { capture: true, once: true });
4851
+ }
4598
4852
  };
4599
4853
  document.addEventListener('pointerdown', onPointerDown, true);
4600
4854
  cleanupFns.push(() => document.removeEventListener('pointerdown', onPointerDown, true));
@@ -4602,15 +4856,31 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4602
4856
  cleanupFns.push(setupFocusTrap(paneElement, overlayRef, config.modal !== false, isTopMost, document));
4603
4857
  nextFrame(() => {
4604
4858
  if (overlayRef.state() !== 'mounting') {
4859
+ animationDebugLog(`runtime ${config.id}`, `enter skipped (state "${overlayRef.state()}" before enter frame)`);
4605
4860
  return;
4606
4861
  }
4607
4862
  const lifecycle = getAnimatedLifecycle(componentRef);
4608
4863
  if (!lifecycle) {
4864
+ interactiveCloseReady = true;
4609
4865
  applyInitialFocus(paneElement, autoFocus, document);
4610
4866
  overlayRef.markOpened();
4611
4867
  return;
4612
4868
  }
4613
- lifecycle.enter();
4869
+ animationDebugLog(`runtime ${config.id}`, `enter (delegate ${config.animationDelegate?.enter ? 'yes' : 'no'}, lifecycle state "${lifecycle.state$.value}")`);
4870
+ const readySubscription = lifecycle.state$
4871
+ .pipe(filter((state) => state === 'entering' || state === 'entered'), take(1))
4872
+ .subscribe(() => {
4873
+ nextFrame(() => {
4874
+ interactiveCloseReady = true;
4875
+ });
4876
+ });
4877
+ cleanupFns.push(() => readySubscription.unsubscribe());
4878
+ if (config.animationDelegate?.enter) {
4879
+ config.animationDelegate.enter({ lifecycle, elements: overlayRef.elements });
4880
+ }
4881
+ else {
4882
+ lifecycle.enter();
4883
+ }
4614
4884
  lifecycle.state$
4615
4885
  .pipe(filter((state) => state === 'entered'), take(1))
4616
4886
  .subscribe(() => {
@@ -4621,7 +4891,7 @@ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4621
4891
  return overlayRef;
4622
4892
  };
4623
4893
  destroyRef.onDestroy(() => {
4624
- openEntriesState().forEach((entry) => entry.close(undefined, 'api'));
4894
+ [...mountedTeardowns].forEach((teardown) => teardown());
4625
4895
  maybeDestroyRootElement();
4626
4896
  });
4627
4897
  return {
@@ -7021,5 +7291,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
7021
7291
  * Generated bundle index. Do not edit.
7022
7292
  */
7023
7293
 
7024
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PROVIDER, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RuntimeError, SEO_DIRECTIVE_TOKEN, SURFACE_PROVIDER, SURFACE_TYPE, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SeoDirective, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRxHostListener, createSessionMemory, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUserConsentProvider, deferredSignal, deleteCookie, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, htmlToMarkdown, inferMimeType, injectAngularRootElement, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, markdownToHtml, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideViewportConfig, resolveSurfaceByElevation, round, routerDisableScrollTop, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
7294
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PROVIDER, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RuntimeError, SEO_DIRECTIVE_TOKEN, SURFACE_PROVIDER, SURFACE_TYPE, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SeoDirective, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRxHostListener, createSessionMemory, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUserConsentProvider, deferredSignal, deleteCookie, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, htmlToMarkdown, inferMimeType, injectAngularRootElement, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, markdownToHtml, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideViewportConfig, resetPositioningStyles, resolveSurfaceByElevation, round, routerDisableScrollTop, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
7025
7295
  //# sourceMappingURL=ethlete-core.mjs.map