@ethlete/core 5.0.0-next.63 → 5.0.0-next.65

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.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { assertInInjectionContext, inject, DestroyRef, ElementRef, TemplateRef, InjectionToken, booleanAttribute, QueryList, RendererFactory2, RendererStyleFlags2, isSignal, DOCUMENT, signal, linkedSignal, isDevMode, computed, afterNextRender, effect, untracked, ApplicationRef, runInInjectionContext, NgZone, Injector, numberAttribute, PLATFORM_ID, afterRenderEffect, EnvironmentInjector, createComponent, ViewEncapsulation, Component, Directive, model, ViewContainerRef, input, CSP_NONCE, provideEnvironmentInitializer, output, createEnvironmentInjector, Pipe, afterEveryRender } from '@angular/core';
2
+ import { assertInInjectionContext, inject, DestroyRef, ElementRef, TemplateRef, InjectionToken, booleanAttribute, QueryList, RendererFactory2, RendererStyleFlags2, isSignal, DOCUMENT, signal, linkedSignal, isDevMode, computed, afterNextRender, effect, untracked, ApplicationRef, runInInjectionContext, NgZone, Injector, numberAttribute, PLATFORM_ID, afterRenderEffect, EnvironmentInjector, createComponent, ViewEncapsulation, Component, Directive, model, ViewContainerRef, input, CSP_NONCE, provideEnvironmentInitializer, output, createEnvironmentInjector, Pipe, makeEnvironmentProviders, afterEveryRender } from '@angular/core';
3
3
  import { takeUntilDestroyed, toSignal, toObservable, outputFromObservable } from '@angular/core/rxjs-interop';
4
4
  import { Subject, fromEvent, switchMap, startWith, of, defer, from, map, catchError, timer, takeUntil, tap, pairwise, debounceTime, merge, distinctUntilChanged, EMPTY, expand, skip, take, filter, BehaviorSubject, combineLatest, Observable, isObservable, firstValueFrom, defaultIfEmpty, concatMap, concat, finalize, exhaustMap, share, shareReplay, ReplaySubject } from 'rxjs';
5
5
  import { FormGroup, FormArray, FormControl } from '@angular/forms';
6
6
  import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
7
- import { isPlatformBrowser, Location, DOCUMENT as DOCUMENT$1 } from '@angular/common';
7
+ import { isPlatformBrowser, Location, DOCUMENT as DOCUMENT$1, isPlatformServer } 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
10
  import { platform, offset, flip, shift, limitShift, computePosition, autoUpdate, hide, arrow, size } from '@floating-ui/dom';
@@ -4549,17 +4549,15 @@ const provideFocusVisibleTracker = /* @__PURE__ */ toProvideFn(FOCUS_VISIBLE_TRA
4549
4549
  const injectFocusVisibleTracker = /* @__PURE__ */ toInjectFn(FOCUS_VISIBLE_TRACKER_DEF);
4550
4550
  const FOCUS_VISIBLE_TRACKER_TOKEN = /* @__PURE__ */ toToken(FOCUS_VISIBLE_TRACKER_DEF);
4551
4551
 
4552
- const LOCALE_DEF = /* @__PURE__ */ defineRootProvider(() => {
4553
- const currentLocale = signal('en', /* @ts-ignore */
4554
- ...(ngDevMode ? [{ debugName: "currentLocale" }] : /* istanbul ignore next */ []));
4555
- return {
4556
- currentLocale,
4557
- };
4558
- }, {
4559
- name: 'Locale',
4552
+ const LOCALE = /* @__PURE__ */ new InjectionToken('Locale', {
4553
+ providedIn: 'root',
4554
+ factory: () => ({ currentLocale: signal('en') }),
4560
4555
  });
4561
- const provideLocale = /* @__PURE__ */ toProvideFn(LOCALE_DEF);
4562
- const injectLocale = /* @__PURE__ */ toInjectFn(LOCALE_DEF);
4556
+ /** Provides the app locale, starting at `locale` (default `'en'`). Change it later with `injectLocale().currentLocale.set(...)`. */
4557
+ const provideLocale = (locale) => [
4558
+ { provide: LOCALE, useFactory: () => ({ currentLocale: signal(locale ?? 'en') }) },
4559
+ ];
4560
+ const injectLocale = () => inject(LOCALE);
4563
4561
 
4564
4562
  const resolveSource = (source, locale) => typeof source === 'function' ? source(locale) : source;
4565
4563
  /**
@@ -4634,7 +4632,8 @@ const STYLE_MANAGER_DEF = /* @__PURE__ */ defineRootProvider(() => {
4634
4632
  const nextContainer = renderer.createElement('div');
4635
4633
  renderer.addClass(nextContainer, 'et-style-manager');
4636
4634
  renderer.setAttribute(nextContainer, 'aria-hidden', 'true');
4637
- renderer.setStyle(nextContainer, { display: 'none' });
4635
+ // A style attribute needs 'unsafe-inline' in a CSP's style-src-attr; a nonce does not cover it.
4636
+ renderer.setAttribute(nextContainer, 'hidden', '');
4638
4637
  renderer.appendChild(getContainerParent(), nextContainer);
4639
4638
  container = nextContainer;
4640
4639
  return nextContainer;
@@ -8016,6 +8015,8 @@ let middlewareExtras = null;
8016
8015
  const registerAnchoredPositionMiddlewareExtras = (extras) => {
8017
8016
  middlewareExtras = extras;
8018
8017
  };
8018
+ /** Whether `enableAnchoredOverlayPositionExtras()` has run, so `arrow`, `autoResize` and `autoHide` take effect. */
8019
+ const hasAnchoredOverlayPositionExtras = () => middlewareExtras !== null;
8019
8020
  const requireMiddlewareExtras = (feature) => {
8020
8021
  if (!middlewareExtras && isDevMode()) {
8021
8022
  console.error(`An anchored overlay uses "${feature}", but the matching floating-ui middleware is not installed. Call \`enableAnchoredOverlayPositionExtras()\` from @ethlete/core once during app setup.`);
@@ -8135,11 +8136,14 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
8135
8136
  if (strategy.minAvailableSpace !== undefined && !strategy.autoResize && isDevMode()) {
8136
8137
  console.error('An anchored overlay sets `minAvailableSpace` without `autoResize`, so it is kept on a side it does not fit on with nothing capping it to the space there. Enable `autoResize` or drop `minAvailableSpace`.');
8137
8138
  }
8139
+ // A width the pane declares through `--et-overlay-width` must survive positioning, and the pane
8140
+ // has to be measured at it - the variable may be set only after this runs.
8141
+ const declaredWidth = () => paneElement.style.getPropertyValue('--et-overlay-width') || null;
8138
8142
  renderer.setStyle(paneElement, {
8139
8143
  position: 'absolute',
8140
8144
  top: '0',
8141
8145
  left: '0',
8142
- width: mirrorWidthElement ? `${mirrorWidthElement.offsetWidth}px` : 'max-content',
8146
+ width: mirrorWidthElement ? `${mirrorWidthElement.offsetWidth}px` : 'var(--et-overlay-width, max-content)',
8143
8147
  });
8144
8148
  /**
8145
8149
  * What to do when the reference is not somewhere the pane can be positioned against: either removed
@@ -8253,7 +8257,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
8253
8257
  }
8254
8258
  renderer.setStyle(paneElement, {
8255
8259
  transform: `translate3d(${x}px, ${y}px, 0)`,
8256
- width: mirrorWidthElement ? `${mirrorWidthElement.offsetWidth}px` : null,
8260
+ width: mirrorWidthElement ? `${mirrorWidthElement.offsetWidth}px` : declaredWidth(),
8257
8261
  visibility: null,
8258
8262
  });
8259
8263
  // exposed so animations can compose their transforms with the anchored position
@@ -9693,195 +9697,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
9693
9697
  }]
9694
9698
  }], ctorParameters: () => [] });
9695
9699
 
9696
- const TOLERANCE_PX = 0.5;
9697
- const readFontSizePx = (view, element) => {
9698
- const match = /^(\d+(?:\.\d+)?)px$/.exec(view.getComputedStyle(element).fontSize ?? '');
9699
- return match ? Number(match[1]) : null;
9700
- };
9701
- const measureProbe = (document, view, fontSize) => {
9702
- const probe = document.createElement('div');
9703
- probe.style.setProperty('display', 'none', 'important');
9704
- probe.style.setProperty('font-size', fontSize, 'important');
9705
- document.documentElement.appendChild(probe);
9706
- try {
9707
- return readFontSizePx(view, probe);
9708
- }
9709
- finally {
9710
- probe.remove();
9711
- }
9712
- };
9713
- const measureUnsetRootFontSize = (document) => {
9714
- const view = document.defaultView;
9715
- if (!view)
9716
- return null;
9717
- const root = readFontSizePx(view, document.documentElement);
9718
- const browserDefault = measureProbe(document, view, 'medium');
9719
- const smallest = measureProbe(document, view, '1px');
9720
- if (root === null || browserDefault === null || smallest === null)
9721
- return null;
9722
- // A browser minimum font size at or above the default clamps any root to the default.
9723
- if (smallest >= browserDefault - TOLERANCE_PX)
9724
- return null;
9725
- return Math.abs(root - browserDefault) <= TOLERANCE_PX ? root : null;
9726
- };
9727
- const warnIfRootFontSizeUnset = (document) => {
9728
- const root = measureUnsetRootFontSize(document);
9729
- if (root === null)
9730
- return;
9731
- console.warn(`[provideSurfaceThemesWithTailwind4] The root font size is ${root}px, the browser default, so every SDK control renders 1.6x too large. The SDK sizes everything in rem against a 10px root (${root * 0.625}px here). Add \`html { font-size: 62.5%; }\` to your global styles. See https://ethlete-sdk-docs-next.web.app/components/setup`);
9732
- };
9733
- const provideRootFontSizeCheck = () => provideEnvironmentInitializer(() => {
9734
- if (!isDevMode() || !isPlatformBrowser(inject(PLATFORM_ID)))
9735
- return;
9736
- const document = inject(DOCUMENT$1);
9737
- const destroyRef = inject(DestroyRef);
9738
- const injector = inject(EnvironmentInjector);
9739
- afterNextRender(() => {
9740
- const view = document.defaultView;
9741
- if (!view)
9742
- return;
9743
- if (document.readyState === 'complete') {
9744
- warnIfRootFontSizeUnset(document);
9745
- return;
9746
- }
9747
- const removeListener = () => view.removeEventListener('load', onLoad);
9748
- const unregisterOnDestroy = destroyRef.onDestroy(removeListener);
9749
- const onLoad = () => {
9750
- removeListener();
9751
- unregisterOnDestroy();
9752
- warnIfRootFontSizeUnset(document);
9753
- };
9754
- view.addEventListener('load', onLoad);
9755
- }, { injector });
9756
- });
9757
-
9758
- const SURFACE_TYPE = {
9759
- LIGHT: 'light',
9760
- DARK: 'dark',
9761
- };
9762
- const createCssSurfaceName = (name) => name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
9763
- const resolveSurfaceByElevation = (themes, type, elevation) => themes.find((t) => t.type === type && t.elevation === elevation) ?? null;
9764
- const SURFACE_THEMES_DEF = /* @__PURE__ */ defineStaticProvider(undefined, {
9765
- name: 'Surface Themes',
9766
- });
9767
- const ɵProvideSurfaceThemes = /* @__PURE__ */ toProvideFn(SURFACE_THEMES_DEF);
9768
- const injectSurfaceThemes = /* @__PURE__ */ toInjectFn(SURFACE_THEMES_DEF);
9769
- const SURFACE_THEMES_PREFIX_DEF = /* @__PURE__ */ defineStaticProvider('et', {
9770
- name: 'Surface Themes Prefix',
9771
- });
9772
- const ɵProvideSurfaceThemesPrefix = /* @__PURE__ */ toProvideFn(SURFACE_THEMES_PREFIX_DEF);
9773
- const injectSurfaceThemesPrefix = /* @__PURE__ */ toInjectFn(SURFACE_THEMES_PREFIX_DEF);
9774
- /**
9775
- * Registers the app's surface themes. In dev mode it also warns once the page has loaded if the root
9776
- * font size is still the browser default, i.e. the app is missing `html { font-size: 62.5%; }`.
9777
- */
9778
- const provideSurfaceThemesWithTailwind4 = (themes, prefix = 'et') => [
9779
- ɵProvideSurfaceThemes(themes),
9780
- ɵProvideSurfaceThemesPrefix(prefix),
9781
- ngDevMode ? provideRootFontSizeCheck() : [],
9782
- ];
9783
- /**
9784
- * Inject the registered `isDefault` surface theme of a `type` - the surface an app renders on
9785
- * where nothing scopes one. Without a `type`, resolves the default of the only surface type the
9786
- * app registers; an app registering both must name the one it means, since which of the two
9787
- * `:root` paints is a `prefers-color-scheme` decision. `null` when neither applies.
9788
- */
9789
- const injectDefaultSurfaceTheme = (type) => {
9790
- const defaults = injectSurfaceThemes({ optional: true })?.filter((theme) => theme.isDefault) ?? [];
9791
- if (type)
9792
- return defaults.find((theme) => theme.type === type) ?? null;
9793
- return defaults.length === 1 ? (defaults[0] ?? null) : null;
9794
- };
9795
-
9796
- /**
9797
- * Reserved color name. Resolves the color tokens from the ambient surface's neutral swatch
9798
- * (`SurfaceTheme['interactionColor']`) instead of a registered accent, so a secondary action can
9799
- * read as chrome without the app registering a neutral color theme. Apps must not register a color
9800
- * theme under this name.
9801
- */
9802
- const SURFACE_COLOR = 'surface';
9803
- const createCssColorThemeName = (name) => name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
9804
- const COLOR_THEMES_DEF = /* @__PURE__ */ defineStaticProvider(undefined, {
9805
- name: 'Color Themes',
9806
- });
9807
- const ɵProvideColorThemes = /* @__PURE__ */ toProvideFn(COLOR_THEMES_DEF);
9808
- const injectColorThemes = /* @__PURE__ */ toInjectFn(COLOR_THEMES_DEF);
9809
- const COLOR_THEMES_PREFIX_DEF = /* @__PURE__ */ defineStaticProvider('et', {
9810
- name: 'Themes Prefix',
9811
- });
9812
- const ɵProvideColorThemesPrefix = /* @__PURE__ */ toProvideFn(COLOR_THEMES_PREFIX_DEF);
9813
- const injectColorThemesPrefix = /* @__PURE__ */ toInjectFn(COLOR_THEMES_PREFIX_DEF);
9814
- const provideColorThemesWithTailwind4 = (themes, prefix = 'et') => {
9815
- if (isDevMode() && themes.some((theme) => theme.name === SURFACE_COLOR)) {
9816
- console.error(`[provideColorThemesWithTailwind4] "${SURFACE_COLOR}" is a reserved color name that resolves to the ambient surface's neutral swatch. Rename your theme.`);
9817
- }
9818
- return [ɵProvideColorThemes(themes), ɵProvideColorThemesPrefix(prefix)];
9819
- };
9820
- const findColorThemeByType = (themes, type, caller) => {
9821
- if (!themes) {
9822
- throw new Error(`[${caller}] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
9823
- }
9824
- const theme = themes.find((t) => t.type === type);
9825
- if (!theme) {
9826
- throw new Error(`[${caller}] No color theme with type "${type}" found. Add a theme with type: "${type}" to provideColorThemesWithTailwind4().`);
9827
- }
9828
- if (isDevMode()) {
9829
- const duplicates = themes.filter((t) => t.type === type);
9830
- if (duplicates.length > 1) {
9831
- console.error(`[${caller}] Multiple themes with type "${type}" found: ${duplicates.map((t) => t.name).join(', ')}. Only the first one will be used.`);
9832
- }
9833
- }
9834
- return theme;
9835
- };
9836
- const injectColorThemeByType = (type) => findColorThemeByType(injectColorThemes({ optional: true }), type, 'injectColorThemeByType');
9837
- /**
9838
- * A signal of the color theme for `type` on the surface this element renders on: the theme the nearest
9839
- * surface names in `semanticColorThemes`, else the first registered theme of that `type`. Reading it throws
9840
- * when the app registered no theme of that `type`, so read it only for a state that renders.
9841
- *
9842
- * @example
9843
- * protected successTheme = injectSemanticColorTheme('success');
9844
- * // <span [etProvideColor]="successTheme()">+12%</span>
9845
- */
9846
- const injectSemanticColorTheme = (type) => {
9847
- const themes = injectColorThemes({ optional: true });
9848
- const surfaceProvider = inject(SURFACE_PROVIDER, { optional: true });
9849
- const defaultSurface = injectDefaultSurfaceTheme();
9850
- return computed(() => {
9851
- const surface = surfaceProvider?.activeTheme() ?? defaultSurface;
9852
- const mappedName = surface?.semanticColorThemes?.[type];
9853
- const mapped = mappedName ? themes?.find((t) => t.name === mappedName) : undefined;
9854
- if (mapped)
9855
- return mapped;
9856
- if (mappedName && isDevMode()) {
9857
- console.error(`[injectSemanticColorTheme] Surface theme "${surface?.name}" maps "${type}" to the color theme "${mappedName}", which is not registered. Add it to provideColorThemesWithTailwind4().`);
9858
- }
9859
- return findColorThemeByType(themes, type, 'injectSemanticColorTheme');
9860
- });
9861
- };
9862
- /** @deprecated Use `injectSemanticColorTheme('error')`, which follows the surface the element renders on. */
9863
- const injectErrorTheme = () => injectColorThemeByType('error');
9864
- /** @deprecated Use `injectSemanticColorTheme('warning')`, which follows the surface the element renders on. */
9865
- const injectWarningTheme = () => injectColorThemeByType('warning');
9866
- /** @deprecated Use `injectSemanticColorTheme('success')`, which follows the surface the element renders on. */
9867
- const injectSuccessTheme = () => injectColorThemeByType('success');
9868
- const injectDefaultColorTheme = () => {
9869
- const themes = injectColorThemes({ optional: true });
9870
- if (!themes) {
9871
- throw new Error(`[injectDefaultColorTheme] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
9872
- }
9873
- const theme = themes.find((t) => t.isDefault);
9874
- if (!theme) {
9875
- throw new Error(`[injectDefaultColorTheme] No color theme with isDefault: true found. Mark one theme as the default in provideColorThemesWithTailwind4().`);
9876
- }
9877
- if (isDevMode()) {
9878
- const duplicates = themes.filter((t) => t.isDefault);
9879
- if (duplicates.length > 1) {
9880
- console.error(`[injectDefaultColorTheme] Multiple themes with isDefault: true found: ${duplicates.map((t) => t.name).join(', ')}. Only the first one will be used.`);
9881
- }
9882
- }
9883
- return theme;
9884
- };
9700
+ const COLOR_SCHEME_TYPE = new InjectionToken('ColorSchemeType');
9701
+ /** True while the scheme is only known to CSS: a server render in `system` mode with a default per surface type. */
9702
+ const COLOR_SCHEME_UNRESOLVED = new InjectionToken('ColorSchemeUnresolved');
9885
9703
 
9886
9704
  const COLOR_PROVIDER = new InjectionToken('ColorProvider');
9887
9705
  /**
@@ -9907,6 +9725,7 @@ class ProvideColorDirective {
9907
9725
  this.themes = injectColorThemes({ optional: true });
9908
9726
  this.prefix = injectColorThemesPrefix({ optional: true });
9909
9727
  this.injector = inject(Injector);
9728
+ this.rootSurfaceTheme = injectRootSurfaceTheme();
9910
9729
  this.parentProvider = inject(COLOR_PROVIDER, { optional: true, skipSelf: true });
9911
9730
  this.appRef = inject(ApplicationRef);
9912
9731
  this.currentProviderSync = null;
@@ -9957,12 +9776,25 @@ class ProvideColorDirective {
9957
9776
  return createCssColorThemeName(value);
9958
9777
  }, /* @ts-ignore */
9959
9778
  ...(ngDevMode ? [{ debugName: "colorName" }] : /* istanbul ignore next */ []));
9779
+ this.paintedColorName = computed(() => {
9780
+ const raw = this.effectiveColor();
9781
+ const value = typeof raw === 'object' && raw !== null ? raw.name : raw;
9782
+ if (!this.colorName() || !value)
9783
+ return;
9784
+ const surface = this.injector.get(SURFACE_PROVIDER, null)?.activeTheme() ?? this.rootSurfaceTheme();
9785
+ const variant = resolveColorThemeVariant(surface, value, this.themes);
9786
+ if (variant === value)
9787
+ return this.colorName();
9788
+ if (isDevMode() && !this.themes?.some((theme) => theme.name === variant)) {
9789
+ console.error(`Surface theme ${surface?.name} names the color theme ${variant}, which does not exist. Please make sure to add it to provideColorThemesWithTailwind4()`);
9790
+ }
9791
+ return createCssColorThemeName(variant);
9792
+ }, /* @ts-ignore */
9793
+ ...(ngDevMode ? [{ debugName: "paintedColorName" }] : /* istanbul ignore next */ []));
9960
9794
  this.themeClass = computed(() => {
9961
9795
  const prefix = this.prefix || 'et';
9962
- if (this.colorName()) {
9963
- return `${prefix}-color--${this.colorName()}`;
9964
- }
9965
- return `${prefix}-color--inherited`;
9796
+ const name = this.paintedColorName();
9797
+ return name ? `${prefix}-color--${name}` : `${prefix}-color--inherited`;
9966
9798
  }, /* @ts-ignore */
9967
9799
  ...(ngDevMode ? [{ debugName: "themeClass" }] : /* istanbul ignore next */ []));
9968
9800
  }
@@ -10013,6 +9845,106 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
10013
9845
  }]
10014
9846
  }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "etProvideColor", required: false }] }] } });
10015
9847
 
9848
+ const TOLERANCE_PX = 0.5;
9849
+ const readFontSizePx = (view, element) => {
9850
+ const match = /^(\d+(?:\.\d+)?)px$/.exec(view.getComputedStyle(element).fontSize ?? '');
9851
+ return match ? Number(match[1]) : null;
9852
+ };
9853
+ const measureProbe = (document, view, fontSize) => {
9854
+ const probe = document.createElement('div');
9855
+ probe.style.setProperty('display', 'none', 'important');
9856
+ probe.style.setProperty('font-size', fontSize, 'important');
9857
+ document.documentElement.appendChild(probe);
9858
+ try {
9859
+ return readFontSizePx(view, probe);
9860
+ }
9861
+ finally {
9862
+ probe.remove();
9863
+ }
9864
+ };
9865
+ const measureUnsetRootFontSize = (document) => {
9866
+ const view = document.defaultView;
9867
+ if (!view)
9868
+ return null;
9869
+ const root = readFontSizePx(view, document.documentElement);
9870
+ const browserDefault = measureProbe(document, view, 'medium');
9871
+ const smallest = measureProbe(document, view, '1px');
9872
+ if (root === null || browserDefault === null || smallest === null)
9873
+ return null;
9874
+ // A browser minimum font size at or above the default clamps any root to the default.
9875
+ if (smallest >= browserDefault - TOLERANCE_PX)
9876
+ return null;
9877
+ return Math.abs(root - browserDefault) <= TOLERANCE_PX ? root : null;
9878
+ };
9879
+ const warnIfRootFontSizeUnset = (document) => {
9880
+ const root = measureUnsetRootFontSize(document);
9881
+ if (root === null)
9882
+ return;
9883
+ console.warn(`[provideSurfaceThemesWithTailwind4] The root font size is ${root}px, the browser default, so every SDK control renders 1.6x too large. The SDK sizes everything in rem against a 10px root (${root * 0.625}px here). Add \`html { font-size: 62.5%; }\` to your global styles. See https://ethlete-sdk-docs-next.web.app/components/setup`);
9884
+ };
9885
+ const provideRootFontSizeCheck = () => provideEnvironmentInitializer(() => {
9886
+ if (!isDevMode() || !isPlatformBrowser(inject(PLATFORM_ID)))
9887
+ return;
9888
+ const document = inject(DOCUMENT$1);
9889
+ const destroyRef = inject(DestroyRef);
9890
+ const injector = inject(EnvironmentInjector);
9891
+ afterNextRender(() => {
9892
+ const view = document.defaultView;
9893
+ if (!view)
9894
+ return;
9895
+ if (document.readyState === 'complete') {
9896
+ warnIfRootFontSizeUnset(document);
9897
+ return;
9898
+ }
9899
+ const removeListener = () => view.removeEventListener('load', onLoad);
9900
+ const unregisterOnDestroy = destroyRef.onDestroy(removeListener);
9901
+ const onLoad = () => {
9902
+ removeListener();
9903
+ unregisterOnDestroy();
9904
+ warnIfRootFontSizeUnset(document);
9905
+ };
9906
+ view.addEventListener('load', onLoad);
9907
+ }, { injector });
9908
+ });
9909
+
9910
+ const SURFACE_TYPE = {
9911
+ LIGHT: 'light',
9912
+ DARK: 'dark',
9913
+ };
9914
+ const createCssSurfaceName = (name) => name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
9915
+ const resolveSurfaceByElevation = (themes, type, elevation) => themes.find((t) => t.type === type && t.elevation === elevation) ?? null;
9916
+ const SURFACE_THEMES_DEF = /* @__PURE__ */ defineStaticProvider(undefined, {
9917
+ name: 'Surface Themes',
9918
+ });
9919
+ const ɵProvideSurfaceThemes = /* @__PURE__ */ toProvideFn(SURFACE_THEMES_DEF);
9920
+ const injectSurfaceThemes = /* @__PURE__ */ toInjectFn(SURFACE_THEMES_DEF);
9921
+ const SURFACE_THEMES_PREFIX_DEF = /* @__PURE__ */ defineStaticProvider('et', {
9922
+ name: 'Surface Themes Prefix',
9923
+ });
9924
+ const ɵProvideSurfaceThemesPrefix = /* @__PURE__ */ toProvideFn(SURFACE_THEMES_PREFIX_DEF);
9925
+ const injectSurfaceThemesPrefix = /* @__PURE__ */ toInjectFn(SURFACE_THEMES_PREFIX_DEF);
9926
+ /**
9927
+ * Registers the app's surface themes. In dev mode it also warns once the page has loaded if the root
9928
+ * font size is still the browser default, i.e. the app is missing `html { font-size: 62.5%; }`.
9929
+ */
9930
+ const provideSurfaceThemesWithTailwind4 = (themes, prefix = 'et') => [
9931
+ ɵProvideSurfaceThemes(themes),
9932
+ ɵProvideSurfaceThemesPrefix(prefix),
9933
+ ngDevMode ? provideRootFontSizeCheck() : [],
9934
+ ];
9935
+ /**
9936
+ * Inject the registered `isDefault` surface theme of a `type` - the surface an app renders on
9937
+ * where nothing scopes one. Without a `type`, resolves the default of the only surface type the
9938
+ * app registers; an app registering both must name the one it means. `null` when neither applies.
9939
+ * For the theme the root paints right now, use `injectRootSurfaceTheme()`.
9940
+ */
9941
+ const injectDefaultSurfaceTheme = (type) => {
9942
+ const defaults = injectSurfaceThemes({ optional: true })?.filter((theme) => theme.isDefault) ?? [];
9943
+ if (type)
9944
+ return defaults.find((theme) => theme.type === type) ?? null;
9945
+ return defaults.length === 1 ? (defaults[0] ?? null) : null;
9946
+ };
9947
+
10016
9948
  const SURFACE_PROVIDER = new InjectionToken('SurfaceProvider');
10017
9949
  const FORCED_SURFACE_UNSET = /* @__PURE__ */ Symbol('FORCED_SURFACE_UNSET');
10018
9950
  class ProvideSurfaceDirective {
@@ -10021,10 +9953,13 @@ class ProvideSurfaceDirective {
10021
9953
  this.prefix = injectSurfaceThemesPrefix({ optional: true });
10022
9954
  this.injector = inject(Injector);
10023
9955
  this.parentProvider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
10024
- this.defaultTheme = injectDefaultSurfaceTheme();
9956
+ this.hostElement = injectHostElement();
9957
+ this.rootTheme = injectRootSurfaceTheme();
9958
+ this.hasColorScheme = !!inject(COLOR_SCHEME_TYPE, { optional: true });
10025
9959
  this.colorThemes = injectColorThemes({ optional: true });
10026
9960
  this.colorPrefix = injectColorThemesPrefix({ optional: true });
10027
9961
  this.colorProvider = inject(COLOR_PROVIDER, { optional: true });
9962
+ this.ownColorProvider = inject(COLOR_PROVIDER, { optional: true, self: true });
10028
9963
  this.currentProviderSync = null;
10029
9964
  this.forcedSurface = signal(FORCED_SURFACE_UNSET, /* @ts-ignore */
10030
9965
  ...(ngDevMode ? [{ debugName: "forcedSurface" }] : /* istanbul ignore next */ []));
@@ -10044,7 +9979,7 @@ class ProvideSurfaceDirective {
10044
9979
  // Only the outermost provider adopts the app default. A nested one left unset must keep
10045
9980
  // resolving to `null` so it reports the surface it inherits instead of resetting elevation.
10046
9981
  if (!value)
10047
- return this.parentProvider ? null : this.defaultTheme;
9982
+ return this.parentProvider ? null : this.rootTheme();
10048
9983
  const theme = this.themes.find((t) => t.name === value) ?? null;
10049
9984
  if (isDevMode() && !theme) {
10050
9985
  console.error(`Surface theme ${value} does not exist. Please make sure to add it to provideSurfaceThemesWithTailwind4()`);
@@ -10071,13 +10006,25 @@ class ProvideSurfaceDirective {
10071
10006
  }, /* @ts-ignore */
10072
10007
  ...(ngDevMode ? [{ debugName: "surfaceName" }] : /* istanbul ignore next */ []));
10073
10008
  this.colorThemeClass = computed(() => {
10074
- const colorTheme = this.resolvedTheme()?.colorTheme;
10075
- if (!colorTheme || this.colorProvider?.resolvedColor())
10009
+ const own = this.ownColorProvider?.effectiveColor();
10010
+ if (typeof own === 'object' && own !== null ? own.name : own)
10011
+ return null;
10012
+ const resolved = this.colorProvider?.resolvedColor();
10013
+ const chosen = (typeof resolved === 'object' && resolved !== null ? resolved.name : resolved) ||
10014
+ this.colorThemes?.find((theme) => theme.isDefault)?.name;
10015
+ if (!chosen)
10016
+ return null;
10017
+ const variant = resolveColorThemeVariant(this.activeTheme(), chosen, this.colorThemes);
10018
+ // An overlay pane's DI parent surface is not its DOM ancestor, so the pane cannot inherit the parent's class.
10019
+ const inheritsFromParent = !this.parentProvider || this.parentProvider.hostElement.contains(this.hostElement);
10020
+ if (inheritsFromParent &&
10021
+ variant === resolveColorThemeVariant(this.inheritedSurfaceTheme(), chosen, this.colorThemes)) {
10076
10022
  return null;
10077
- if (isDevMode() && !this.colorThemes?.some((theme) => theme.name === colorTheme)) {
10078
- console.error(`Surface theme ${this.resolvedTheme()?.name} names the color theme ${colorTheme}, which does not exist. Please make sure to add it to provideColorThemesWithTailwind4()`);
10079
10023
  }
10080
- return `${this.colorPrefix || 'et'}-color--${createCssColorThemeName(colorTheme)}`;
10024
+ if (isDevMode() && !this.colorThemes?.some((theme) => theme.name === variant)) {
10025
+ console.error(`Surface theme ${this.activeTheme()?.name} names the color theme ${variant}, which does not exist. Please make sure to add it to provideColorThemesWithTailwind4()`);
10026
+ }
10027
+ return `${this.colorPrefix || 'et'}-color--${createCssColorThemeName(variant)}`;
10081
10028
  }, /* @ts-ignore */
10082
10029
  ...(ngDevMode ? [{ debugName: "colorThemeClass" }] : /* istanbul ignore next */ []));
10083
10030
  this.surfaceClass = computed(() => {
@@ -10090,6 +10037,11 @@ class ProvideSurfaceDirective {
10090
10037
  }, /* @ts-ignore */
10091
10038
  ...(ngDevMode ? [{ debugName: "surfaceClass" }] : /* istanbul ignore next */ []));
10092
10039
  }
10040
+ inheritedSurfaceTheme() {
10041
+ if (this.parentProvider)
10042
+ return this.parentProvider.activeTheme();
10043
+ return this.hasColorScheme ? this.rootTheme() : null;
10044
+ }
10093
10045
  syncWithProvider(provider) {
10094
10046
  this.currentProviderSync?.destroy();
10095
10047
  runInInjectionContext(this.injector, () => {
@@ -10142,22 +10094,234 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
10142
10094
  */
10143
10095
  const injectSurfaceType = () => {
10144
10096
  const provider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
10145
- const defaultType = injectDefaultSurfaceTheme()?.type ?? null;
10146
- return computed(() => provider?.surfaceType() ?? defaultType);
10097
+ const rootTheme = injectRootSurfaceTheme();
10098
+ return computed(() => provider?.surfaceType() ?? rootTheme()?.type ?? null);
10147
10099
  };
10148
10100
  /**
10149
10101
  * Inject a signal containing the surface theme the current subtree renders on - the theme in
10150
10102
  * effect on the surrounding surface provider, or the app's default surface where nothing provides
10151
10103
  * one. Use it to derive an elevation relative to the surrounding surface.
10152
10104
  *
10153
- * `null` where the app registers no surface themes, or registers a default per surface type -
10154
- * which of those two `:root` paints is a `prefers-color-scheme` decision, so it cannot be
10155
- * resolved at runtime.
10105
+ * `null` where the app registers no surface themes, or registers a default per surface type
10106
+ * without `provideColorScheme()`.
10156
10107
  */
10157
10108
  const injectParentSurface = () => {
10158
10109
  const provider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
10159
- const defaultTheme = injectDefaultSurfaceTheme();
10160
- return computed(() => provider?.activeTheme() ?? defaultTheme);
10110
+ const rootTheme = injectRootSurfaceTheme();
10111
+ return computed(() => provider?.activeTheme() ?? rootTheme());
10112
+ };
10113
+
10114
+ /**
10115
+ * Reserved color name. Resolves the color tokens from the ambient surface's neutral swatch
10116
+ * (`SurfaceTheme['interactionColor']`) instead of a registered accent, so a secondary action can
10117
+ * read as chrome without the app registering a neutral color theme. Apps must not register a color
10118
+ * theme under this name.
10119
+ */
10120
+ const SURFACE_COLOR = 'surface';
10121
+ const createCssColorThemeName = (name) => name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
10122
+ const COLOR_THEMES_DEF = /* @__PURE__ */ defineStaticProvider(undefined, {
10123
+ name: 'Color Themes',
10124
+ });
10125
+ const ɵProvideColorThemes = /* @__PURE__ */ toProvideFn(COLOR_THEMES_DEF);
10126
+ const injectColorThemes = /* @__PURE__ */ toInjectFn(COLOR_THEMES_DEF);
10127
+ const COLOR_THEMES_PREFIX_DEF = /* @__PURE__ */ defineStaticProvider('et', {
10128
+ name: 'Themes Prefix',
10129
+ });
10130
+ const ɵProvideColorThemesPrefix = /* @__PURE__ */ toProvideFn(COLOR_THEMES_PREFIX_DEF);
10131
+ const injectColorThemesPrefix = /* @__PURE__ */ toInjectFn(COLOR_THEMES_PREFIX_DEF);
10132
+ const provideColorThemesWithTailwind4 = (themes, prefix = 'et') => {
10133
+ if (isDevMode() && themes.some((theme) => theme.name === SURFACE_COLOR)) {
10134
+ console.error(`[provideColorThemesWithTailwind4] "${SURFACE_COLOR}" is a reserved color name that resolves to the ambient surface's neutral swatch. Rename your theme.`);
10135
+ }
10136
+ return [ɵProvideColorThemes(themes), ɵProvideColorThemesPrefix(prefix)];
10137
+ };
10138
+ const findColorThemeByType = (themes, type, caller) => {
10139
+ if (!themes) {
10140
+ throw new Error(`[${caller}] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
10141
+ }
10142
+ const theme = themes.find((t) => t.type === type);
10143
+ if (!theme) {
10144
+ throw new Error(`[${caller}] No color theme with type "${type}" found. Add a theme with type: "${type}" to provideColorThemesWithTailwind4().`);
10145
+ }
10146
+ if (isDevMode()) {
10147
+ const duplicates = themes.filter((t) => t.type === type);
10148
+ if (duplicates.length > 1) {
10149
+ console.error(`[${caller}] Multiple themes with type "${type}" found: ${duplicates.map((t) => t.name).join(', ')}. Only the first one will be used.`);
10150
+ }
10151
+ }
10152
+ return theme;
10153
+ };
10154
+ const injectColorThemeByType = (type) => findColorThemeByType(injectColorThemes({ optional: true }), type, 'injectColorThemeByType');
10155
+ /**
10156
+ * The color theme name that draws `chosenName` on `surface`: the surface's `colorThemeVariants` entry for it,
10157
+ * else `chosenName` itself. Always pass the chosen accent, never an already swapped one.
10158
+ */
10159
+ const resolveColorThemeVariant = (surface, chosenName, themes) => {
10160
+ if (!surface || chosenName === SURFACE_COLOR)
10161
+ return chosenName;
10162
+ const variants = surface.colorThemeVariants;
10163
+ const variant = variants?.[chosenName];
10164
+ if (variant)
10165
+ return variant;
10166
+ const chosen = themes?.find((t) => t.name === chosenName);
10167
+ const semantic = chosen?.type ? surface.semanticColorThemes?.[chosen.type] : undefined;
10168
+ if (semantic)
10169
+ return semantic;
10170
+ if (surface.colorTheme && chosen?.isDefault)
10171
+ return surface.colorTheme;
10172
+ return chosenName;
10173
+ };
10174
+ /**
10175
+ * A signal of the color theme for `type` on the surface this element renders on: the first registered theme
10176
+ * of that `type`, swapped for the nearest surface's `colorThemeVariants` entry. Reading it throws when the app
10177
+ * registered no theme of that `type`, so read it only for a state that renders.
10178
+ *
10179
+ * @example
10180
+ * protected successTheme = injectSemanticColorTheme('success');
10181
+ * // <span [etProvideColor]="successTheme()">+12%</span>
10182
+ */
10183
+ const injectSemanticColorTheme = (type) => {
10184
+ const themes = injectColorThemes({ optional: true });
10185
+ const surfaceProvider = inject(SURFACE_PROVIDER, { optional: true });
10186
+ const rootSurface = injectRootSurfaceTheme();
10187
+ return computed(() => {
10188
+ const chosen = findColorThemeByType(themes, type, 'injectSemanticColorTheme');
10189
+ const surface = surfaceProvider?.activeTheme() ?? rootSurface();
10190
+ const variantName = resolveColorThemeVariant(surface, chosen.name, themes);
10191
+ if (variantName === chosen.name)
10192
+ return chosen;
10193
+ const variant = themes?.find((t) => t.name === variantName);
10194
+ if (variant)
10195
+ return variant;
10196
+ if (isDevMode()) {
10197
+ console.error(`[injectSemanticColorTheme] Surface theme "${surface?.name}" maps "${type}" to the color theme "${variantName}", which is not registered. Add it to provideColorThemesWithTailwind4().`);
10198
+ }
10199
+ return chosen;
10200
+ });
10201
+ };
10202
+ /** @deprecated Use `injectSemanticColorTheme('error')`, which follows the surface the element renders on. */
10203
+ const injectErrorTheme = () => injectColorThemeByType('error');
10204
+ /** @deprecated Use `injectSemanticColorTheme('warning')`, which follows the surface the element renders on. */
10205
+ const injectWarningTheme = () => injectColorThemeByType('warning');
10206
+ /** @deprecated Use `injectSemanticColorTheme('success')`, which follows the surface the element renders on. */
10207
+ const injectSuccessTheme = () => injectColorThemeByType('success');
10208
+ const injectDefaultColorTheme = () => {
10209
+ const themes = injectColorThemes({ optional: true });
10210
+ if (!themes) {
10211
+ throw new Error(`[injectDefaultColorTheme] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
10212
+ }
10213
+ const theme = themes.find((t) => t.isDefault);
10214
+ if (!theme) {
10215
+ throw new Error(`[injectDefaultColorTheme] No color theme with isDefault: true found. Mark one theme as the default in provideColorThemesWithTailwind4().`);
10216
+ }
10217
+ if (isDevMode()) {
10218
+ const duplicates = themes.filter((t) => t.isDefault);
10219
+ if (duplicates.length > 1) {
10220
+ console.error(`[injectDefaultColorTheme] Multiple themes with isDefault: true found: ${duplicates.map((t) => t.name).join(', ')}. Only the first one will be used.`);
10221
+ }
10222
+ }
10223
+ return theme;
10224
+ };
10225
+
10226
+ const findRootSurfaceTheme = (defaults, type) => {
10227
+ if (defaults.length <= 1)
10228
+ return defaults[0] ?? null;
10229
+ return defaults.find((theme) => theme.type === type) ?? null;
10230
+ };
10231
+ const COLOR_SCHEME_DEF = /* @__PURE__ */ defineProvider(() => {
10232
+ const root = inject(DOCUMENT).documentElement;
10233
+ const prefix = injectSurfaceThemesPrefix({ optional: true }) || 'et';
10234
+ const prefersDark = injectBreakpointObserver().observeMediaQuery('(prefers-color-scheme: dark)');
10235
+ const mode = signal('system', /* @ts-ignore */
10236
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
10237
+ const surfaceDefaults = injectSurfaceThemes({ optional: true })?.filter((theme) => theme.isDefault) ?? [];
10238
+ const colorThemes = injectColorThemes({ optional: true });
10239
+ const colorPrefix = injectColorThemesPrefix({ optional: true }) || 'et';
10240
+ const type = computed(() => {
10241
+ const current = mode();
10242
+ if (current !== 'system')
10243
+ return current;
10244
+ return prefersDark() ? 'dark' : 'light';
10245
+ }, /* @ts-ignore */
10246
+ ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
10247
+ const rootSurface = computed(() => findRootSurfaceTheme(surfaceDefaults, type()), /* @ts-ignore */
10248
+ ...(ngDevMode ? [{ debugName: "rootSurface" }] : /* istanbul ignore next */ []));
10249
+ const rootColorClass = computed(() => {
10250
+ const chosen = colorThemes?.find((theme) => theme.isDefault)?.name;
10251
+ if (!chosen)
10252
+ return null;
10253
+ const variant = resolveColorThemeVariant(rootSurface(), chosen, colorThemes);
10254
+ return variant === chosen ? null : `${colorPrefix}-color--${createCssColorThemeName(variant)}`;
10255
+ }, /* @ts-ignore */
10256
+ ...(ngDevMode ? [{ debugName: "rootColorClass" }] : /* istanbul ignore next */ []));
10257
+ const defaultColor = colorThemes?.find((theme) => theme.isDefault)?.name;
10258
+ if (defaultColor) {
10259
+ for (const surface of surfaceDefaults) {
10260
+ const variant = resolveColorThemeVariant(surface, defaultColor, colorThemes);
10261
+ if (variant !== defaultColor)
10262
+ root.classList.remove(`${colorPrefix}-color--${createCssColorThemeName(variant)}`);
10263
+ }
10264
+ }
10265
+ let paintedColorClass = null;
10266
+ const clearColorClass = () => {
10267
+ if (paintedColorClass)
10268
+ root.classList.remove(paintedColorClass);
10269
+ paintedColorClass = null;
10270
+ };
10271
+ effect(() => {
10272
+ const next = rootColorClass();
10273
+ clearColorClass();
10274
+ if (next)
10275
+ root.classList.add(next);
10276
+ paintedColorClass = next;
10277
+ });
10278
+ const clearClasses = () => root.classList.remove(`${prefix}-scheme--light`, `${prefix}-scheme--dark`);
10279
+ const setMode = (next) => {
10280
+ clearClasses();
10281
+ if (next !== 'system')
10282
+ root.classList.add(`${prefix}-scheme--${next}`);
10283
+ mode.set(next);
10284
+ };
10285
+ inject(DestroyRef).onDestroy(() => {
10286
+ clearClasses();
10287
+ clearColorClass();
10288
+ });
10289
+ return { mode: mode.asReadonly(), type, rootSurface, setMode };
10290
+ }, { name: 'Color Scheme' });
10291
+ const provideColorSchemeState = /* @__PURE__ */ toProvideFn(COLOR_SCHEME_DEF);
10292
+ /**
10293
+ * Inject the app's color scheme: `mode()` is what the app asked for, `type()` the surface type the
10294
+ * root paints, `rootSurface()` the default surface theme of that type, and `setMode()` switches it.
10295
+ * Needs `provideColorScheme()`.
10296
+ */
10297
+ const injectColorScheme = /* @__PURE__ */ toInjectFn(COLOR_SCHEME_DEF);
10298
+ const injectSchemeUnresolved = () => {
10299
+ const { mode } = injectColorScheme();
10300
+ const isServer = isPlatformServer(inject(PLATFORM_ID));
10301
+ const defaultCount = injectSurfaceThemes({ optional: true })?.filter((theme) => theme.isDefault).length ?? 0;
10302
+ return computed(() => isServer && defaultCount > 1 && mode() === 'system');
10303
+ };
10304
+ /**
10305
+ * Lets the app switch between its default light and dark surface with a class on `<html>`, instead of
10306
+ * only following `prefers-color-scheme`. It also paints the root surface's `colorThemeVariants` entry for the
10307
+ * default accent on `<html>`. Add it to the application config, next to
10308
+ * `provideSurfaceThemesWithTailwind4()`.
10309
+ */
10310
+ const provideColorScheme = (config) => makeEnvironmentProviders([
10311
+ provideColorSchemeState(),
10312
+ { provide: COLOR_SCHEME_TYPE, useFactory: () => injectColorScheme().type },
10313
+ { provide: COLOR_SCHEME_UNRESOLVED, useFactory: injectSchemeUnresolved },
10314
+ provideEnvironmentInitializer(() => injectColorScheme().setMode(config?.mode ?? 'system')),
10315
+ ]);
10316
+ /**
10317
+ * Inject a signal of the default surface theme the root paints where nothing scopes one. If the app
10318
+ * registers a default for both surface types, it follows `injectColorScheme()`, and is `null` without
10319
+ * `provideColorScheme()`.
10320
+ */
10321
+ const injectRootSurfaceTheme = () => {
10322
+ const defaults = injectSurfaceThemes({ optional: true })?.filter((theme) => theme.isDefault) ?? [];
10323
+ const colorSchemeType = inject(COLOR_SCHEME_TYPE, { optional: true });
10324
+ return computed(() => findRootSurfaceTheme(defaults, colorSchemeType?.()));
10161
10325
  };
10162
10326
 
10163
10327
  let uniqueId = 0;
@@ -10207,6 +10371,8 @@ class AutoSurfaceDirective {
10207
10371
  this.surfaceContextTracker = injectSurfaceContextTracker();
10208
10372
  this.parentSurface = injectParentSurface();
10209
10373
  this.elementRef = inject(ElementRef);
10374
+ this.schemeUnresolved = inject(COLOR_SCHEME_UNRESOLVED, { optional: true });
10375
+ this.rootTheme = injectRootSurfaceTheme();
10210
10376
  /**
10211
10377
  * Explicit surface provider to resolve the surface relative to. Falls back to the
10212
10378
  * surface provider from the surrounding (trigger) context when not set.
@@ -10232,6 +10398,10 @@ class AutoSurfaceDirective {
10232
10398
  const overlaySurface = this.surfaceContextTracker.surfaceForElement(this.elementRef.nativeElement);
10233
10399
  const overlayElevation = overlaySurface?.elevation ?? null;
10234
10400
  const overlayType = overlaySurface?.type ?? null;
10401
+ // A surface derived from the root would bake the server's guessed scheme into the markup; inherit, and let CSS pick it.
10402
+ if (this.schemeUnresolved?.() && overlayElevation === null && contextTheme === this.rootTheme()) {
10403
+ return null;
10404
+ }
10235
10405
  // Must not re-derive from the declaration injector: it points at the trigger and would double-elevate the panel.
10236
10406
  if (this.isOverlaySurface()) {
10237
10407
  if (overlayElevation !== null) {
@@ -10579,11 +10749,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
10579
10749
 
10580
10750
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
10581
10751
  /** The version of `@ethlete/core` this build was cut from. */
10582
- const CORE_VERSION = '5.0.0-next.63';
10752
+ const CORE_VERSION = '5.0.0-next.65';
10583
10753
 
10584
10754
  /**
10585
10755
  * Generated bundle index. Do not edit.
10586
10756
  */
10587
10757
 
10588
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, ANIMATION_ERROR_CODES, 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, EasingTokensStylesComponent, EthleteValidators, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MARKDOWN_VERBATIM_ATTR, MUST_MATCH, MarkdownToHtmlPipe, MatchStateType, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, 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_CONFIRM, UNSAVED_CHANGES_ERROR_CODES, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, VisuallyHiddenStylesComponent, 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, boolBreakpointTransform, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDestroy, createDocumentElementSignal, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createIsRenderedSignal, createLogger, createObjectUrlHandle, createPropertyBinding, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, 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, injectQueryParamAll, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectSemanticColorTheme, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceColorPalette, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElement, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isHTMLOrSVGElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isSafeLinkUrl, isSafeUrl, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, mountEasingTokens, mountVisuallyHidden, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointTransform, onOverlayViewportInsetsChange, optionalBooleanAttribute, overlayViewportInsets, overlayViewportInsetsFor, ownsActiveElement, 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, provideUnsavedChangesConfirm, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, reserveOverlayViewportSpace, resolveAppRootColorProvider, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalCountdown, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
10758
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, ANIMATION_ERROR_CODES, 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, EasingTokensStylesComponent, EthleteValidators, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MARKDOWN_VERBATIM_ATTR, MUST_MATCH, MarkdownToHtmlPipe, MatchStateType, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, 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_CONFIRM, UNSAVED_CHANGES_ERROR_CODES, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, VisuallyHiddenStylesComponent, 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, boolBreakpointTransform, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDestroy, createDocumentElementSignal, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createIsRenderedSignal, createLogger, createObjectUrlHandle, createPropertyBinding, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, 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, hasAnchoredOverlayPositionExtras, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectAppUpdates, injectAppUpdatesConfig, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorPalette, injectColorScheme, 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, injectQueryParamAll, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRootSurfaceTheme, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectSemanticColorTheme, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceColorPalette, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElement, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isHTMLOrSVGElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isSafeLinkUrl, isSafeUrl, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, mountEasingTokens, mountVisuallyHidden, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointTransform, onOverlayViewportInsetsChange, optionalBooleanAttribute, overlayViewportInsets, overlayViewportInsetsFor, ownsActiveElement, previousSignalValue, provideAppUpdates, provideAppUpdatesConfig, provideAppUpdatesInstance, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorPalette, provideColorScheme, provideColorThemes, provideColorThemesWithTailwind4, provideFaviconStore, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideNotifications, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideUnsavedChangesConfirm, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, reserveOverlayViewportSpace, resolveAppRootColorProvider, resolveColorThemeVariant, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalCountdown, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
10589
10759
  //# sourceMappingURL=ethlete-core.mjs.map