@ethlete/core 5.0.0-next.51 → 5.0.0-next.52

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,26 @@
1
1
  # @ethlete/core
2
2
 
3
+ ## 5.0.0-next.52
4
+
5
+ ### Major Changes
6
+
7
+ - [`4044a00`](https://github.com/ethlete-io/ethdk/commit/4044a0007de55d25b5a697c6e4190e21d68d022f) Thanks [@TomTomB](https://github.com/TomTomB)! - - Notifications: a toast keeps one elevation, paints above overlays, and keeps out of every reserved viewport edge.
8
+ - Query devtools: a side dock reserves the edge it covers.
9
+ - `SurfaceContextTracker` drops `topType` / `topElevation`.
10
+
11
+ ### Minor Changes
12
+
13
+ - [`3122607`](https://github.com/ethlete-io/ethdk/commit/3122607d1727844a2d987032f45ad631f678c2ca) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays and floating chrome now keep out of space a surface above the page reserved with `reserveOverlayViewportSpace()` - so a dialog, menu or toast is no longer stacked under the docked query devtools panel.
14
+
15
+ ### Patch Changes
16
+
17
+ - [`0116464`](https://github.com/ethlete-io/ethdk/commit/0116464f3efc92bfa7dc094a2b20ae9d813a8c45) Thanks [@TomTomB](https://github.com/TomTomB)! - - `etAnimatedLifecycle` no longer ends an enter or leave before its animation started, which destroyed a routed overlay page without playing its exit animation.
18
+ - Adds `AnimatableDirective.getRunningAnimations()`.
19
+
20
+ - [`68db91f`](https://github.com/ethlete-io/ethdk/commit/68db91fb975378cccebc4ad99f59365eba90fb43) Thanks [@TomTomB](https://github.com/TomTomB)! - - `etAutoSurface`, `et-grid-item` and `et-form-field` elevate above an app's root surface, instead of staying inherited.
21
+ - An unset `etProvideSurface` reports the surface it inherits, so content below it no longer resolves one elevation too low.
22
+ - Adds `injectParentSurface()`.
23
+
3
24
  ## 5.0.0-next.51
4
25
 
5
26
  ### Minor Changes
@@ -7,7 +7,7 @@ import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
7
7
  import { DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
8
8
  import { Router, NavigationEnd, NavigationSkipped, NavigationStart, NavigationError, RouterLink } from '@angular/router';
9
9
  import { Title, Meta, DomSanitizer } from '@angular/platform-browser';
10
- import { autoUpdate, offset, flip, shift, limitShift, computePosition, hide, arrow, size } from '@floating-ui/dom';
10
+ import { offset, flip, shift, limitShift, computePosition, autoUpdate, hide, arrow, size } from '@floating-ui/dom';
11
11
 
12
12
  const ANIMATION_DEBUG_STORAGE_KEY = 'et-overlay-debug';
13
13
  let cachedEnabled = null;
@@ -42,7 +42,6 @@ class AnimatableDirective {
42
42
  this.animationEndSubject$ = new Subject();
43
43
  this.activeAnimationCount = 0;
44
44
  this.hostActiveAnimationCount$ = new BehaviorSubject(0);
45
- this.pendingTransitionIds = [];
46
45
  this.animationStart$ = this.animationStartSubject$.asObservable().pipe(debounceTime(0));
47
46
  this.animationEnd$ = this.animationEndSubject$.asObservable().pipe(debounceTime(0));
48
47
  this.totalActiveAnimationCount$ = this.parent
@@ -58,9 +57,10 @@ class AnimatableDirective {
58
57
  const startingNewBatch = this.activeAnimationCount === 0;
59
58
  this.updateActiveAnimationCount(1);
60
59
  if (startingNewBatch) {
61
- this.activeBatchTransitionId = this.pendingTransitionIds.shift();
60
+ this.activeBatchTransitionId = this.pendingTransitionId;
61
+ this.pendingTransitionId = undefined;
62
62
  }
63
- animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `start (count ${this.activeAnimationCount}, batch "${this.activeBatchTransitionId}", pending [${this.pendingTransitionIds.join(', ')}])`);
63
+ animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `start (count ${this.activeAnimationCount}, batch "${this.activeBatchTransitionId}", pending "${this.pendingTransitionId ?? 'none'}")`);
64
64
  if (!didEmitStart) {
65
65
  didEmitStart = true;
66
66
  this.animationStartSubject$.next();
@@ -91,8 +91,33 @@ class AnimatableDirective {
91
91
  }), takeUntilDestroyed())
92
92
  .subscribe();
93
93
  }
94
+ /**
95
+ * Labels the next batch of animations that starts on this element. Only the most recent id is
96
+ * kept: a call whose animations never start must not leave an id behind for a later batch.
97
+ */
94
98
  setTransitionId(id) {
95
- this.pendingTransitionIds.push(id);
99
+ this.pendingTransitionId = id;
100
+ }
101
+ /**
102
+ * The animations running on this element right now, without the endless and pseudo-element ones.
103
+ *
104
+ * Reading this flushes pending style changes, so an animation a class change started in the same
105
+ * task is already listed here. `isAnimating$` cannot answer that: it turns true only once the
106
+ * browser dispatches `transitionrun`, a frame after the style change is committed.
107
+ */
108
+ getRunningAnimations() {
109
+ const el = this.elementRef.nativeElement;
110
+ if (typeof el.getAnimations !== 'function')
111
+ return [];
112
+ return el.getAnimations().filter((animation) => {
113
+ if (animation.playState !== 'running')
114
+ return false;
115
+ const effect = animation.effect;
116
+ if (!effect || effect.pseudoElement)
117
+ return false;
118
+ // An endless animation never resolves `finished`, so awaiting one would strand the transition.
119
+ return effect.getComputedTiming().iterations !== Infinity;
120
+ });
96
121
  }
97
122
  updateActiveAnimationCount(delta) {
98
123
  const newVal = this.activeAnimationCount + delta;
@@ -4696,73 +4721,39 @@ class AnimatedLifecycleDirective {
4696
4721
  this.removeClass(fromClass);
4697
4722
  this.addClass(toClass);
4698
4723
  }
4699
- }), switchMap(() => this.animatable.isAnimating$), take(1), switchMap((isAnimating) => {
4700
- if (isAnimating)
4701
- return of(true);
4702
- // Nothing started yet on the first check - give a transition with a delay one more
4703
- // frame before concluding none is coming (mirrors handleInterruptedTransition).
4704
- return fromNextFrame().pipe(switchMap(() => this.animatable.isAnimating$), take(1));
4705
- }), switchMap((isAnimating) => {
4706
- if (!isAnimating) {
4707
- // No transition ever started - e.g. `prefers-reduced-motion` collapsed every
4708
- // transition-duration to 0, which per spec never fires transitionrun/transitionend.
4709
- // Waiting on animationEnd$ here would hang forever, so treat it as settled.
4710
- this.debugLog(`${transitionId}: completes via fallback (no transition started)`);
4711
- return of(true);
4712
- }
4713
- return this.animatable.animationEnd$.pipe(filter(() => this.state$.value === expectedState), switchMap((e) => {
4714
- if (!e.cancelled && e.transitionId === transitionId) {
4715
- return of(true);
4716
- }
4717
- // The batch ended cancelled or under a different id - e.g. the browser cancelled and
4718
- // restarted a running transition mid-flight (an anchored overlay whose ancestor pane got
4719
- // destroyed) or a foreign transition on the same element finished. If nothing is
4720
- // animating anymore the expected end event can never arrive, so treat the transition as
4721
- // settled instead of waiting forever (mirrors the fallback in handleInterruptedTransition).
4722
- return this.animatable.isAnimating$.pipe(take(1), tap((stillAnimating) => {
4723
- if (!stillAnimating) {
4724
- this.debugLog(`${transitionId}: completes via fallback (batch id "${e.transitionId ?? 'none'}", cancelled ${e.cancelled})`);
4725
- }
4726
- }), map((stillAnimating) => !stillAnimating));
4727
- }));
4728
- }), filter((settled) => settled && this.state$.value === expectedState), tap(onComplete), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
4724
+ }), switchMap(() => this.whenAnimationsSettled()), tap(() => this.debugLog(`${transitionId}: settled`)), filter(() => this.state$.value === expectedState), tap(onComplete), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
4729
4725
  .subscribe();
4730
4726
  }
4731
4727
  handleInterruptedTransition(config) {
4732
4728
  const { removeClasses, addClasses, expectedState, transitionId, onComplete, cancelSignal } = config;
4733
4729
  this.removeClasses(...removeClasses);
4734
4730
  addClasses.forEach((cls) => this.addClass(cls));
4735
- fromNextFrame()
4736
- .pipe(switchMap(() => this.animatable.isAnimating$), take(1), switchMap((isAnimating) => {
4737
- if (isAnimating) {
4738
- return of(true);
4739
- }
4740
- this.debugLog(`${transitionId}: interrupt found no running transition, re-checking next frame`);
4741
- return fromNextFrame().pipe(switchMap(() => this.animatable.isAnimating$), take(1));
4742
- }), take(1), switchMap((isAnimating) => {
4743
- if (!isAnimating && this.state$.value === expectedState) {
4744
- this.debugLog(`${transitionId}: interrupt completes INSTANTLY (no transition running after class swap)`);
4745
- return of({ cancelled: false, transitionId });
4746
- }
4747
- this.debugLog(`${transitionId}: interrupt waiting for animation end`, { isAnimating });
4748
- return this.animatable.animationEnd$.pipe(switchMap((e) => {
4749
- if (e.transitionId === transitionId) {
4750
- return of(e);
4751
- }
4752
- return this.animatable.isAnimating$.pipe(take(1), switchMap((stillAnimating) => {
4753
- if (!stillAnimating && this.state$.value === expectedState) {
4754
- this.debugLog(`${transitionId}: interrupt completes via foreign animation end (batch id was "${e.transitionId}")`, { stillAnimating });
4755
- return of({ cancelled: false, transitionId });
4756
- }
4757
- return of(null);
4758
- }));
4759
- }), filter((e) => e !== null && e.transitionId === transitionId));
4760
- }), filter((e) => this.state$.value === expectedState && !e.cancelled), tap(() => {
4761
- this.debugLog(`${transitionId}: interrupt complete`);
4762
- onComplete();
4763
- }), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
4731
+ this.whenAnimationsSettled()
4732
+ .pipe(tap(() => this.debugLog(`${transitionId}: interrupt settled`)), filter(() => this.state$.value === expectedState), tap(onComplete), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
4764
4733
  .subscribe();
4765
4734
  }
4735
+ /**
4736
+ * Emits once every animation the class change started on this element has finished, or right away
4737
+ * when the change starts none - a `transition-duration` of 0 (`prefers-reduced-motion`) or a
4738
+ * property whose value did not change.
4739
+ *
4740
+ * `isAnimating$` cannot replace the reading here: it turns true a frame after the browser commits
4741
+ * the style change, so a slow commit reads as "nothing will animate" and ends the transition
4742
+ * before its animation starts.
4743
+ */
4744
+ whenAnimationsSettled(isFirstRead = true) {
4745
+ return defer(() => {
4746
+ const running = this.animatable.getRunningAnimations();
4747
+ if (!running.length) {
4748
+ // Settling on the first read means nothing was ever awaited, so emitting here would reenter
4749
+ // the enter()/leave() call still on the stack. Every later read already runs off a promise.
4750
+ return isFirstRead ? fromNextFrame() : of(undefined);
4751
+ }
4752
+ // A running animation may be replaced rather than finished - the browser retargets a transition
4753
+ // whose end value changes - so re-read instead of settling on the first batch.
4754
+ return from(Promise.allSettled(running.map((animation) => animation.finished))).pipe(switchMap(() => this.whenAnimationsSettled(false)));
4755
+ });
4756
+ }
4766
4757
  addClass(className) {
4767
4758
  this.renderer.addClass(this.element, className);
4768
4759
  }
@@ -7242,6 +7233,112 @@ const setupFocusTrap = (paneElement, overlayRef, enabled, isTopMost, document) =
7242
7233
  };
7243
7234
  };
7244
7235
 
7236
+ const NO_INSET = { top: 0, right: 0, bottom: 0, left: 0 };
7237
+ const reservations = /* @__PURE__ */ new Set();
7238
+ const listeners = /* @__PURE__ */ new Set();
7239
+ /**
7240
+ * The custom property each edge is published as on the document root, so page chrome that overlays
7241
+ * cannot move for you - a sticky action bar, a floating button - can keep out of the same space:
7242
+ * `inset-block-end: calc(1.6rem + var(--et-viewport-inset-bottom, 0px))`.
7243
+ */
7244
+ const INSET_PROPERTIES = {
7245
+ top: '--et-viewport-inset-top',
7246
+ right: '--et-viewport-inset-right',
7247
+ bottom: '--et-viewport-inset-bottom',
7248
+ left: '--et-viewport-inset-left',
7249
+ };
7250
+ /**
7251
+ * Page content paints below every reserving surface, so - unlike an overlay - it keeps out of every
7252
+ * reservation, whichever level it was made on.
7253
+ */
7254
+ const publishInsetProperties = () => {
7255
+ const root = globalThis.document?.documentElement;
7256
+ if (!root)
7257
+ return;
7258
+ const insets = overlayViewportInsets(Number.NEGATIVE_INFINITY);
7259
+ Object.entries(INSET_PROPERTIES).forEach(([edge, property]) => {
7260
+ if (!reservations.size) {
7261
+ root.style.removeProperty(property);
7262
+ return;
7263
+ }
7264
+ root.style.setProperty(property, `${insets[edge]}px`);
7265
+ });
7266
+ };
7267
+ const notify = () => {
7268
+ publishInsetProperties();
7269
+ listeners.forEach((listener) => listener());
7270
+ };
7271
+ /**
7272
+ * Reserves an edge of the viewport, so overlays keep out of it. Returns the release callback.
7273
+ *
7274
+ * Meant for a surface an application paints over its own content and above the overlay layer - a
7275
+ * docked devtools panel, an always-on-top widget. A centered or globally positioned overlay is laid
7276
+ * out inside what is left of the viewport, and an anchored one avoids the reserved edge the same way
7277
+ * it avoids the viewport edge. Page chrome that nothing can move for you - a sticky action bar, a
7278
+ * floating button - reads the published `--et-viewport-inset-*` custom properties instead.
7279
+ */
7280
+ const reserveOverlayViewportSpace = (reservation) => {
7281
+ const entry = {
7282
+ top: reservation.top ?? 0,
7283
+ right: reservation.right ?? 0,
7284
+ bottom: reservation.bottom ?? 0,
7285
+ left: reservation.left ?? 0,
7286
+ layer: reservation.layer ?? DEFAULT_OVERLAY_LAYER + 1,
7287
+ };
7288
+ reservations.add(entry);
7289
+ notify();
7290
+ return () => {
7291
+ if (!reservations.delete(entry))
7292
+ return;
7293
+ notify();
7294
+ };
7295
+ };
7296
+ /**
7297
+ * What an overlay on this stacking level must keep out of: the largest reservation per edge made by a
7298
+ * surface that paints above it. Reservations on or below the level are ignored - they cannot cover it.
7299
+ */
7300
+ const overlayViewportInsets = (layer = DEFAULT_OVERLAY_LAYER) => {
7301
+ let insets = NO_INSET;
7302
+ reservations.forEach((reservation) => {
7303
+ if (reservation.layer <= layer)
7304
+ return;
7305
+ insets = {
7306
+ top: Math.max(insets.top, reservation.top),
7307
+ right: Math.max(insets.right, reservation.right),
7308
+ bottom: Math.max(insets.bottom, reservation.bottom),
7309
+ left: Math.max(insets.left, reservation.left),
7310
+ };
7311
+ });
7312
+ return insets;
7313
+ };
7314
+ /** {@link overlayViewportInsets} for the stacking level `element` is rendered on. */
7315
+ const overlayViewportInsetsFor = (element) => overlayViewportInsets(resolveOverlayLayer(element));
7316
+ /**
7317
+ * Runs `listener` whenever a reservation is made or released, so an already positioned overlay can be
7318
+ * laid out again. Returns the unsubscribe callback.
7319
+ *
7320
+ * @internal
7321
+ */
7322
+ const onOverlayViewportInsetsChange = (listener) => {
7323
+ listeners.add(listener);
7324
+ return () => {
7325
+ listeners.delete(listener);
7326
+ };
7327
+ };
7328
+
7329
+ /**
7330
+ * Shrinks the host box to the part of the viewport nothing above this overlay has reserved, so a
7331
+ * centered or globally placed pane is laid out inside it instead of under a docked panel.
7332
+ */
7333
+ const applyViewportInsets = (hostElement, renderer) => {
7334
+ const insets = overlayViewportInsetsFor(hostElement);
7335
+ renderer.setStyle(hostElement, {
7336
+ top: `${insets.top}px`,
7337
+ right: `${insets.right}px`,
7338
+ bottom: `${insets.bottom}px`,
7339
+ left: `${insets.left}px`,
7340
+ });
7341
+ };
7245
7342
  const setBaseElementStyles = (config, hostElement, paneElement, renderer) => {
7246
7343
  renderer.setStyle(hostElement, {
7247
7344
  position: 'fixed',
@@ -7273,6 +7370,7 @@ const applyCenteredPosition = (hostElement, paneElement, renderer, _config) => {
7273
7370
  padding: '16px',
7274
7371
  overflow: 'auto',
7275
7372
  });
7373
+ applyViewportInsets(hostElement, renderer);
7276
7374
  renderer.setStyle(paneElement, {
7277
7375
  position: 'relative',
7278
7376
  });
@@ -7287,6 +7385,7 @@ const applyGlobalPosition = (hostElement, paneElement, renderer, config) => {
7287
7385
  placeItems: `${config.vertical ?? 'center'} ${config.horizontal ?? 'center'}`,
7288
7386
  padding: config.padding ?? '0',
7289
7387
  });
7388
+ applyViewportInsets(hostElement, renderer);
7290
7389
  renderer.setStyle(paneElement, {
7291
7390
  position: 'relative',
7292
7391
  });
@@ -7348,10 +7447,10 @@ const setupPositioning = (config, hostElement, paneElement, overlayRef, renderer
7348
7447
  }
7349
7448
  if (strategy.kind === 'global') {
7350
7449
  applyGlobalPosition(hostElement, paneElement, renderer, strategy);
7351
- return () => undefined;
7450
+ return onOverlayViewportInsetsChange(() => applyViewportInsets(hostElement, renderer));
7352
7451
  }
7353
7452
  applyCenteredPosition(hostElement, paneElement, renderer, strategy);
7354
- return () => undefined;
7453
+ return onOverlayViewportInsetsChange(() => applyViewportInsets(hostElement, renderer));
7355
7454
  };
7356
7455
 
7357
7456
  let middlewareExtras = null;
@@ -7423,6 +7522,27 @@ const preferredSide = (options) => ({
7423
7522
  : { data: { availableSpace }, reset: { placement: toOppositeSidePlacement(placement) } };
7424
7523
  },
7425
7524
  });
7525
+ const toSideObject = (padding) => typeof padding === 'number'
7526
+ ? { top: padding, right: padding, bottom: padding, left: padding }
7527
+ : {
7528
+ top: padding.top ?? 0,
7529
+ right: padding.right ?? 0,
7530
+ bottom: padding.bottom ?? 0,
7531
+ left: padding.left ?? 0,
7532
+ };
7533
+ /**
7534
+ * The strategy's own viewport padding plus the space reserved on each edge. Every middleware that
7535
+ * measures overflow gets it, so an edge a docked panel covers is as unavailable as the viewport edge.
7536
+ */
7537
+ const paddingWithInsets = (padding, insets) => {
7538
+ const own = toSideObject(padding);
7539
+ return {
7540
+ top: own.top + insets.top,
7541
+ right: own.right + insets.right,
7542
+ bottom: own.bottom + insets.bottom,
7543
+ left: own.left + insets.left,
7544
+ };
7545
+ };
7426
7546
  const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, renderer) => {
7427
7547
  // mirrorWidth needs a real element to measure; virtual references fall back to max-content
7428
7548
  const mirrorWidthElement = strategy.mirrorWidth && isHTMLElement(strategy.referenceElement) ? strategy.referenceElement : null;
@@ -7450,7 +7570,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7450
7570
  renderer.setStyle(paneElement, { visibility: 'hidden' });
7451
7571
  }
7452
7572
  };
7453
- const cleanup = autoUpdate(strategy.referenceElement, paneElement, () => {
7573
+ const update = () => {
7454
7574
  // Checked here rather than left to the `hide` middleware, which is only in the list when `autoHide`
7455
7575
  // or `autoCloseIfReferenceHidden` asked for it: a trigger destroyed while its overlay is open (a
7456
7576
  // menu item that removes the button it was opened from) would otherwise fly to the corner for the
@@ -7460,19 +7580,22 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7460
7580
  return;
7461
7581
  }
7462
7582
  const arrowElement = paneElement.querySelector('[et-floating-arrow]');
7583
+ const insets = overlayViewportInsetsFor(paneElement);
7584
+ const viewportPadding = paddingWithInsets(strategy.viewportPadding ?? 8, insets);
7463
7585
  const middleware = [];
7464
7586
  middleware.push(offset(strategy.offset ?? 8));
7465
7587
  middleware.push(strategy.minAvailableSpace === undefined
7466
7588
  ? flip({
7467
7589
  fallbackPlacements: strategy.fallbackPlacements ?? undefined,
7468
7590
  fallbackAxisSideDirection: 'start',
7591
+ padding: insets,
7469
7592
  boundary: strategy.boundary,
7470
7593
  })
7471
7594
  : preferredSide({
7472
7595
  minAvailableSpace: strategy.minAvailableSpace,
7473
7596
  // must stay the padding `size` measures with: the threshold is then compared against the
7474
7597
  // very height the pane ends up capped to
7475
- padding: strategy.viewportPadding ?? 8,
7598
+ padding: viewportPadding,
7476
7599
  boundary: strategy.boundary,
7477
7600
  }));
7478
7601
  if (strategy.shift !== false) {
@@ -7483,7 +7606,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7483
7606
  crossAxis: strategy.minAvailableSpace === undefined &&
7484
7607
  (typeof strategy.shift === 'object' ? (strategy.shift.crossAxis ?? false) : false),
7485
7608
  limiter: limitShift(),
7486
- padding: strategy.viewportPadding ?? 8,
7609
+ padding: viewportPadding,
7487
7610
  boundary: strategy.boundary,
7488
7611
  }));
7489
7612
  }
@@ -7493,7 +7616,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7493
7616
  const extras = requireMiddlewareExtras('autoResize');
7494
7617
  if (extras) {
7495
7618
  middleware.push(extras.size({
7496
- padding: strategy.viewportPadding ?? 8,
7619
+ padding: viewportPadding,
7497
7620
  apply({ availableHeight, availableWidth }) {
7498
7621
  renderer.setCssProperties(paneElement, {
7499
7622
  '--et-overlay-max-width': `${availableWidth}px`,
@@ -7547,9 +7670,14 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7547
7670
  renderer.setCssProperty(arrowElement, '--et-floating-arrow-translate', `translate3d(${middlewareData.arrow.x ?? 0}px, ${middlewareData.arrow.y ?? 0}px, 0)`);
7548
7671
  }
7549
7672
  });
7550
- });
7673
+ };
7674
+ const cleanup = autoUpdate(strategy.referenceElement, paneElement, update);
7675
+ // A panel docked over the page changes how much room the pane has without moving, resizing or
7676
+ // scrolling anything `autoUpdate` watches.
7677
+ const stopInsetUpdates = onOverlayViewportInsetsChange(update);
7551
7678
  return () => {
7552
7679
  cleanup();
7680
+ stopInsetUpdates();
7553
7681
  };
7554
7682
  };
7555
7683
  /**
@@ -9184,9 +9312,16 @@ class ProvideSurfaceDirective {
9184
9312
  return theme;
9185
9313
  }, /* @ts-ignore */
9186
9314
  ...(ngDevMode ? [{ debugName: "resolvedTheme" }] : /* istanbul ignore next */ []));
9187
- this.elevation = computed(() => this.resolvedTheme()?.elevation ?? 0, /* @ts-ignore */
9315
+ /**
9316
+ * The surface theme in effect on this element - the theme this provider resolves itself, or,
9317
+ * where it is left unset, the one it inherits from the closest ancestor provider. The outermost
9318
+ * provider resolves the app default, so the chain ends there.
9319
+ */
9320
+ this.activeTheme = computed(() => this.resolvedTheme() ?? this.parentProvider?.activeTheme() ?? null, /* @ts-ignore */
9321
+ ...(ngDevMode ? [{ debugName: "activeTheme" }] : /* istanbul ignore next */ []));
9322
+ this.elevation = computed(() => this.activeTheme()?.elevation ?? 0, /* @ts-ignore */
9188
9323
  ...(ngDevMode ? [{ debugName: "elevation" }] : /* istanbul ignore next */ []));
9189
- this.surfaceType = computed(() => this.resolvedTheme()?.type ?? null, /* @ts-ignore */
9324
+ this.surfaceType = computed(() => this.activeTheme()?.type ?? null, /* @ts-ignore */
9190
9325
  ...(ngDevMode ? [{ debugName: "surfaceType" }] : /* istanbul ignore next */ []));
9191
9326
  this.surfaceName = computed(() => {
9192
9327
  const value = this.effectiveSurface();
@@ -9261,20 +9396,25 @@ const injectSurfaceType = () => {
9261
9396
  const defaultType = injectDefaultSurfaceTheme()?.type ?? SURFACE_TYPE.DARK;
9262
9397
  return computed(() => provider?.surfaceType() ?? defaultType);
9263
9398
  };
9399
+ /**
9400
+ * Inject a signal containing the surface theme the current subtree renders on - the theme in
9401
+ * effect on the surrounding surface provider, or the app's default surface where nothing provides
9402
+ * one. Use it to derive an elevation relative to the surrounding surface.
9403
+ *
9404
+ * `null` where the app registers no surface themes, or registers a default per surface type -
9405
+ * which of those two `:root` paints is a `prefers-color-scheme` decision, so it cannot be
9406
+ * resolved at runtime.
9407
+ */
9408
+ const injectParentSurface = () => {
9409
+ const provider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
9410
+ const defaultTheme = injectDefaultSurfaceTheme();
9411
+ return computed(() => provider?.activeTheme() ?? defaultTheme);
9412
+ };
9264
9413
 
9265
9414
  let uniqueId = 0;
9266
9415
  const SURFACE_CONTEXT_TRACKER_DEF = /* @__PURE__ */ defineRootProvider(() => {
9267
9416
  const entries = signal([], /* @ts-ignore */
9268
9417
  ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
9269
- const topEntry = computed(() => {
9270
- const stack = entries();
9271
- return stack.length > 0 ? (stack[stack.length - 1] ?? null) : null;
9272
- }, /* @ts-ignore */
9273
- ...(ngDevMode ? [{ debugName: "topEntry" }] : /* istanbul ignore next */ []));
9274
- const topType = computed(() => topEntry()?.type ?? null, /* @ts-ignore */
9275
- ...(ngDevMode ? [{ debugName: "topType" }] : /* istanbul ignore next */ []));
9276
- const topElevation = computed(() => topEntry()?.elevation ?? 0, /* @ts-ignore */
9277
- ...(ngDevMode ? [{ debugName: "topElevation" }] : /* istanbul ignore next */ []));
9278
9418
  const register = (type, elevation, element) => {
9279
9419
  const id = `surface-ctx-${uniqueId++}`;
9280
9420
  const entry = { id, type, elevation, element };
@@ -9294,7 +9434,7 @@ const SURFACE_CONTEXT_TRACKER_DEF = /* @__PURE__ */ defineRootProvider(() => {
9294
9434
  }
9295
9435
  return null;
9296
9436
  };
9297
- return { topType, topElevation, register, surfaceForElement };
9437
+ return { register, surfaceForElement };
9298
9438
  }, { name: 'SurfaceContextTracker' });
9299
9439
  const provideSurfaceContextTracker = /* @__PURE__ */ toProvideFn(SURFACE_CONTEXT_TRACKER_DEF);
9300
9440
  const injectSurfaceContextTracker = /* @__PURE__ */ toInjectFn(SURFACE_CONTEXT_TRACKER_DEF);
@@ -9314,9 +9454,9 @@ class AutoSurfaceDirective {
9314
9454
  }
9315
9455
  constructor() {
9316
9456
  this.ownSurfaceProvider = inject(ProvideSurfaceDirective);
9317
- this.contextSurfaceProvider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
9318
9457
  this.surfaceThemes = injectSurfaceThemes({ optional: true });
9319
9458
  this.surfaceContextTracker = injectSurfaceContextTracker();
9459
+ this.parentSurface = injectParentSurface();
9320
9460
  this.elementRef = inject(ElementRef);
9321
9461
  /**
9322
9462
  * Explicit surface provider to resolve the surface relative to. Falls back to the
@@ -9343,9 +9483,10 @@ class AutoSurfaceDirective {
9343
9483
  // Establish a dependency on the DOM-settle tick so the non-reactive containment read below
9344
9484
  // is re-evaluated after the element is grafted into its final overlay pane.
9345
9485
  this.domSettleTick();
9346
- const contextProvider = this.surfaceProvider() ?? this.contextSurfaceProvider ?? null;
9347
- const contextElevation = contextProvider?.elevation() ?? null;
9348
- const contextType = contextProvider?.surfaceType() ?? null;
9486
+ const explicitProvider = this.surfaceProvider();
9487
+ const contextTheme = explicitProvider ? explicitProvider.activeTheme() : this.parentSurface();
9488
+ const contextElevation = contextTheme?.elevation ?? null;
9489
+ const contextType = contextTheme?.type ?? null;
9349
9490
  // An overlay's projected/portaled content keeps the injector of where it was
9350
9491
  // *declared* (the trigger location), not the pane it renders into - so the
9351
9492
  // injector-derived parent surface is one elevation too low. The surface-context
@@ -9867,11 +10008,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
9867
10008
 
9868
10009
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
9869
10010
  /** The version of `@ethlete/core` this build was cut from. */
9870
- const CORE_VERSION = '5.0.0-next.51';
10011
+ const CORE_VERSION = '5.0.0-next.52';
9871
10012
 
9872
10013
  /**
9873
10014
  * Generated bundle index. Do not edit.
9874
10015
  */
9875
10016
 
9876
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PALETTE, COLOR_PROVIDER, CORE_VERSION, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_OVERLAY_LAYER, 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, ET_RESTORE_SCROLL, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RestoreScrollDirective, RuntimeError, SURFACE_COLOR, SURFACE_PROVIDER, SURFACE_TYPE, SWIPE_VELOCITY_WINDOW_MS, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, Validators, anchoredOverlayPosition, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyFaviconOverlay, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHeadTitleMarker, 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, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createObjectUrlHandle, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTabLock, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, defineLabels, defineProvider, defineRootProvider, defineStaticProvider, defineStaticRootProvider, deleteCookie, dragGestureFrom, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, enableAnchoredOverlayPositionExtras, equal, fetchDeployedBuildFingerprint, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectAppUpdates, injectAppUpdatesConfig, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorPalette, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDefaultColorTheme, injectDefaultSurfaceTheme, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFaviconStore, injectFileDownload, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsDocumentVisible, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectNotifications, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideAppUpdates, provideAppUpdatesConfig, provideAppUpdatesInstance, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorPalette, provideColorThemes, provideColorThemesWithTailwind4, provideFaviconStore, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideNotifications, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, registerAnchoredPositionMiddlewareExtras, registerAnchoredPositionSetup, resetPositioningStyles, resolveAppRootColorProvider, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
10017
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PALETTE, COLOR_PROVIDER, CORE_VERSION, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_OVERLAY_LAYER, 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, ET_RESTORE_SCROLL, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RestoreScrollDirective, RuntimeError, SURFACE_COLOR, SURFACE_PROVIDER, SURFACE_TYPE, SWIPE_VELOCITY_WINDOW_MS, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, Validators, anchoredOverlayPosition, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyFaviconOverlay, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHeadTitleMarker, 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, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createObjectUrlHandle, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTabLock, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, defineLabels, defineProvider, defineRootProvider, defineStaticProvider, defineStaticRootProvider, deleteCookie, dragGestureFrom, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, enableAnchoredOverlayPositionExtras, equal, fetchDeployedBuildFingerprint, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectAppUpdates, injectAppUpdatesConfig, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorPalette, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDefaultColorTheme, injectDefaultSurfaceTheme, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFaviconStore, injectFileDownload, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsDocumentVisible, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectNotifications, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectParentSurface, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointAttribute, numberBreakpointTransform, onOverlayViewportInsetsChange, overlayViewportInsets, overlayViewportInsetsFor, previousSignalValue, provideAppUpdates, provideAppUpdatesConfig, provideAppUpdatesInstance, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorPalette, provideColorThemes, provideColorThemesWithTailwind4, provideFaviconStore, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideNotifications, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, registerAnchoredPositionMiddlewareExtras, registerAnchoredPositionSetup, reserveOverlayViewportSpace, resetPositioningStyles, resolveAppRootColorProvider, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
9877
10018
  //# sourceMappingURL=ethlete-core.mjs.map