@ethlete/core 5.0.0-next.1 → 5.0.0-next.10

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,12 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, NgZone, signal, isSignal, untracked, linkedSignal, DOCUMENT, isDevMode, computed, afterNextRender, effect, Injector, runInInjectionContext, RendererStyleFlags2, PLATFORM_ID, ApplicationRef, RendererFactory2, model, ViewContainerRef, input, booleanAttribute, output, numberAttribute, Pipe, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { takeUntilDestroyed, toObservable, toSignal, outputFromObservable } from '@angular/core/rxjs-interop';
4
- import { Subject, BehaviorSubject, debounceTime, combineLatest, map, merge, fromEvent, filter, tap, switchMap, startWith, of, timer, takeUntil, distinctUntilChanged, pairwise, take, Observable } from 'rxjs';
2
+ import { InjectionToken, inject, ElementRef, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, NgZone, signal, isSignal, untracked, DOCUMENT, linkedSignal, isDevMode, computed, afterNextRender, effect, Injector, booleanAttribute, numberAttribute, runInInjectionContext, RendererStyleFlags2, PLATFORM_ID, ApplicationRef, RendererFactory2, EnvironmentInjector, createComponent, model, ViewContainerRef, input, output, inputBinding, Pipe, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { takeUntilDestroyed, toSignal, toObservable, outputFromObservable } from '@angular/core/rxjs-interop';
4
+ import { Subject, BehaviorSubject, debounceTime, combineLatest, map, merge, fromEvent, filter, tap, switchMap, startWith, of, timer, takeUntil, pairwise, distinctUntilChanged, take, Observable, concatMap, EMPTY, concat, defer, exhaustMap, share } from 'rxjs';
5
5
  import { FormGroup, FormArray, FormControl } from '@angular/forms';
6
6
  import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
7
- import { coerceElement } from '@angular/cdk/coercion';
8
7
  import { BreakpointObserver } from '@angular/cdk/layout';
9
- import { isPlatformBrowser, DOCUMENT as DOCUMENT$1 } from '@angular/common';
8
+ import { coerceElement } from '@angular/cdk/coercion';
9
+ import { DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
10
10
  import { Router, NavigationEnd, NavigationSkipped } from '@angular/router';
11
11
  import { Overlay } from '@angular/cdk/overlay';
12
12
  import { ComponentPortal } from '@angular/cdk/portal';
@@ -77,15 +77,15 @@ class AnimatableDirective {
77
77
  this.activeAnimationCount = clampedVal;
78
78
  this.hostActiveAnimationCount$.next(clampedVal);
79
79
  }
80
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
81
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.1", type: AnimatableDirective, isStandalone: true, selector: "[etAnimatable]", providers: [
80
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
81
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: AnimatableDirective, isStandalone: true, selector: "[etAnimatable]", providers: [
82
82
  {
83
83
  provide: ANIMATABLE_TOKEN,
84
84
  useExisting: AnimatableDirective,
85
85
  },
86
86
  ], exportAs: ["etAnimatable"], ngImport: i0 }); }
87
87
  }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatableDirective, decorators: [{
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatableDirective, decorators: [{
89
89
  type: Directive,
90
90
  args: [{
91
91
  selector: '[etAnimatable]',
@@ -623,7 +623,7 @@ const signalAnimatedNumber = (source, options = {}) => {
623
623
  const easing = options.easing ?? easeOut;
624
624
  const round = options.round ?? ((v) => Math.round(v));
625
625
  const initialValue = options.initialValue ?? 0;
626
- const animatedValue = signal(initialValue, ...(ngDevMode ? [{ debugName: "animatedValue" }] : []));
626
+ const animatedValue = signal(initialValue, ...(ngDevMode ? [{ debugName: "animatedValue" }] : /* istanbul ignore next */ []));
627
627
  let rafId = null;
628
628
  let currentAnimatedValue = initialValue;
629
629
  const cancelAnimation = () => {
@@ -710,41 +710,82 @@ const easeOutBackStrong = (t) => {
710
710
  return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
711
711
  };
712
712
 
713
- const controlValueSignal = (control, options) => {
714
- const getRawValueSafe = (ctrl) => {
715
- try {
716
- return isSignal(ctrl) ? (ctrl()?.getRawValue() ?? null) : (ctrl?.getRawValue() ?? null);
717
- }
718
- catch {
719
- // Ignore errors. This can happen if the passed control is a required input and is not yet initialized.
720
- return null;
721
- }
722
- };
723
- const initialValue = getRawValueSafe(control);
724
- const controlStream = isSignal(control)
725
- ? toObservable(control)
726
- : of(control);
727
- const controlObs = controlStream.pipe(switchMap((ctrl) => {
728
- if (!ctrl)
729
- return of(null);
730
- const vcsObs = options?.debounceTime
731
- ? ctrl.valueChanges.pipe(debounceTime(options.debounceTime))
732
- : ctrl.valueChanges;
733
- return vcsObs.pipe(startWith(ctrl.getRawValue()), map(() => ctrl.getRawValue()));
734
- }));
735
- const obs = !options?.debounceFirst ? merge(of(initialValue), controlObs) : controlObs;
736
- return toSignal(obs.pipe(distinctUntilChanged((a, b) => equal(a, b))), {
737
- initialValue,
738
- });
739
- };
713
+ const BREAKPOINT_ORDER = ['xs', 'sm', 'md', 'lg', 'xl', '2xl'];
740
714
  /**
741
- * The first item in the pair is the previous value and the second item is the current value.
715
+ * Default viewport config based on Tailwind CSS.
716
+ * @see https://tailwindcss.com/docs/screens
742
717
  */
743
- const controlValueSignalWithPrevious = (control, options) => {
744
- const data = linkedSignal({ ...(ngDevMode ? { debugName: "data" } : {}), source: controlValueSignal(control, options),
745
- computation: (curr, prev) => [prev?.source ?? null, curr] });
746
- return data.asReadonly();
718
+ const DEFAULT_VIEWPORT_CONFIG = {
719
+ breakpoints: {
720
+ xs: [0, 639],
721
+ sm: [640, 767],
722
+ md: [768, 1023],
723
+ lg: [1024, 1279],
724
+ xl: [1280, 1535],
725
+ '2xl': [1536, Infinity],
726
+ },
747
727
  };
728
+ const [provideViewportConfig, injectViewportConfig] = createStaticRootProvider(DEFAULT_VIEWPORT_CONFIG, {
729
+ name: 'Viewport Config',
730
+ });
731
+ const [provideBreakpointObserver, injectBreakpointObserver] = createRootProvider(() => {
732
+ const breakpointObserver = inject(BreakpointObserver);
733
+ const viewportConfig = injectViewportConfig();
734
+ const isMediaQueryMatched = (mediaQuery) => breakpointObserver.isMatched(mediaQuery);
735
+ const observeMediaQuery = (mediaQuery) => {
736
+ return toSignal(breakpointObserver.observe(mediaQuery).pipe(map((x) => x.matches), startWith(isMediaQueryMatched(mediaQuery))), { requireSync: true });
737
+ };
738
+ const observeBreakpoint = (options) => observeMediaQuery(buildMediaQueryString(options));
739
+ const isBreakpointMatched = (options) => isMediaQueryMatched(buildMediaQueryString(options));
740
+ const getBreakpointSize = (type, option) => {
741
+ const index = option === 'min' ? 0 : 1;
742
+ const size = viewportConfig.breakpoints[type][index];
743
+ if (size === Infinity || size === 0) {
744
+ return size;
745
+ }
746
+ if (option === 'min') {
747
+ return size;
748
+ }
749
+ // Due to scaling, the actual size of the viewport may be a decimal number.
750
+ // Eg. on Windows 11 with 150% scaling, the viewport size may be 1535.33px
751
+ // and thus not matching any of the default breakpoints.
752
+ return size + 0.9;
753
+ };
754
+ const buildMediaQueryString = (options) => {
755
+ if (!options.min && !options.max) {
756
+ throw new Error('At least one of min or max must be defined');
757
+ }
758
+ const mediaQueryParts = [];
759
+ if (options.min) {
760
+ if (typeof options.min === 'number') {
761
+ mediaQueryParts.push(`(min-width: ${options.min}px)`);
762
+ }
763
+ else {
764
+ mediaQueryParts.push(`(min-width: ${getBreakpointSize(options.min, 'min')}px)`);
765
+ }
766
+ }
767
+ if (options.min && options.max) {
768
+ mediaQueryParts.push('and');
769
+ }
770
+ if (options.max) {
771
+ if (typeof options.max === 'number') {
772
+ mediaQueryParts.push(`(max-width: ${options.max}px)`);
773
+ }
774
+ else {
775
+ mediaQueryParts.push(`(max-width: ${getBreakpointSize(options.max, 'max')}px)`);
776
+ }
777
+ }
778
+ return mediaQueryParts.join(' ');
779
+ };
780
+ return {
781
+ observeBreakpoint,
782
+ isBreakpointMatched,
783
+ getBreakpointSize,
784
+ buildMediaQueryString,
785
+ observeMediaQuery,
786
+ isMediaQueryMatched,
787
+ };
788
+ }, { name: 'Breakpoint Observer' });
748
789
 
749
790
  const isElementSignal = (el) => {
750
791
  if (!isSignal(el))
@@ -860,12 +901,12 @@ const firstElementSignal = (el) => computed(() => {
860
901
  });
861
902
 
862
903
  const signalIsRendered = () => {
863
- const isRendered = signal(false, ...(ngDevMode ? [{ debugName: "isRendered" }] : []));
904
+ const isRendered = signal(false, ...(ngDevMode ? [{ debugName: "isRendered" }] : /* istanbul ignore next */ []));
864
905
  afterNextRender(() => isRendered.set(true));
865
906
  return isRendered.asReadonly();
866
907
  };
867
908
  const createIsRenderedSignal = () => {
868
- const value = signal(false, ...(ngDevMode ? [{ debugName: "value" }] : []));
909
+ const value = signal(false, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
869
910
  nextFrame(() => {
870
911
  if (!value()) {
871
912
  console.error('Render signal was not set to true. This can cause unexpected behavior. Make sure to .bind() the render signal at the end of the constructor.');
@@ -877,7 +918,7 @@ const createIsRenderedSignal = () => {
877
918
  };
878
919
  };
879
920
  const createCanAnimateSignal = () => {
880
- const value = signal(false, ...(ngDevMode ? [{ debugName: "value" }] : []));
921
+ const value = signal(false, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
881
922
  nextFrame(() => {
882
923
  value.set(true);
883
924
  });
@@ -886,102 +927,535 @@ const createCanAnimateSignal = () => {
886
927
  };
887
928
  };
888
929
 
889
- const signalElementMutations = (el, options) => {
930
+ const boundingClientRectToElementRect = (rect) => ({
931
+ bottom: rect.bottom,
932
+ height: rect.height,
933
+ left: rect.left,
934
+ right: rect.right,
935
+ top: rect.top,
936
+ width: rect.width,
937
+ x: rect.x,
938
+ y: rect.y,
939
+ });
940
+ const createElementDimensions = (el, rect) => {
941
+ if (!el) {
942
+ return {
943
+ rect: null,
944
+ client: null,
945
+ scroll: null,
946
+ offset: null,
947
+ };
948
+ }
949
+ const cachedNormalizedRect = rect ? boundingClientRectToElementRect(rect) : null;
950
+ const rectFn = () => cachedNormalizedRect ? cachedNormalizedRect : boundingClientRectToElementRect(el.getBoundingClientRect());
951
+ return {
952
+ rect: rectFn,
953
+ client: { width: el.clientWidth, height: el.clientHeight },
954
+ scroll: { width: el.scrollWidth, height: el.scrollHeight },
955
+ offset: { width: el.offsetWidth, height: el.offsetHeight },
956
+ };
957
+ };
958
+ const signalElementDimensions = (el) => {
890
959
  const destroyRef = inject(DestroyRef);
891
960
  const elements = buildElementSignal(el);
892
961
  const firstEl = firstElementSignal(elements);
893
962
  const zone = inject(NgZone);
894
963
  const isRendered = signalIsRendered();
895
- const elementMutationsSignal = signal(null, ...(ngDevMode ? [{ debugName: "elementMutationsSignal" }] : []));
896
- const observer = new MutationObserver((e) => {
964
+ const initialValue = () => createElementDimensions(firstEl().currentElement);
965
+ const elementDimensionsSignal = signal(initialValue(), ...(ngDevMode ? [{ debugName: "elementDimensionsSignal" }] : /* istanbul ignore next */ []));
966
+ const observer = new ResizeObserver((e) => {
897
967
  if (!isRendered())
898
968
  return;
899
969
  const entry = e[0];
900
970
  if (entry) {
901
- zone.run(() => elementMutationsSignal.set(entry));
971
+ const target = entry.target;
972
+ const newDimensions = createElementDimensions(target);
973
+ zone.run(() => elementDimensionsSignal.set(newDimensions));
902
974
  }
903
975
  });
904
976
  effect(() => {
905
977
  const els = firstEl();
906
- elementMutationsSignal.set(null);
907
- if (els.previousElement) {
908
- observer.disconnect();
909
- }
910
- if (els.currentElement) {
911
- observer.observe(els.currentElement, options);
912
- }
978
+ untracked(() => {
979
+ elementDimensionsSignal.set(initialValue());
980
+ if (els.previousElement) {
981
+ observer.disconnect();
982
+ }
983
+ if (els.currentElement) {
984
+ const computedDisplay = getComputedStyle(els.currentElement).display;
985
+ const currentElIsAngularComponent = els.currentElement?.tagName.toLowerCase().includes('-');
986
+ if (computedDisplay === 'inline' && isDevMode() && currentElIsAngularComponent) {
987
+ console.error(`Element <${els.currentElement?.tagName.toLowerCase()}> is an Angular component and has a display of 'inline'. Inline elements cannot be observed for dimensions. Please change it to 'block' or something else.`);
988
+ }
989
+ observer.observe(els.currentElement);
990
+ }
991
+ });
913
992
  });
914
993
  destroyRef.onDestroy(() => observer.disconnect());
915
- return elementMutationsSignal.asReadonly();
994
+ return computed(() => elementDimensionsSignal(), {
995
+ equal: (a, b) => equal(a, b),
996
+ });
916
997
  };
917
- const signalHostElementMutations = (options) => signalElementMutations(inject(ElementRef), options);
918
-
919
- const signalElementChildren = (el) => {
920
- const elements = buildElementSignal(el);
921
- const firstEl = firstElementSignal(elements);
922
- const isRendered = signalIsRendered();
923
- const elementMutations = signalElementMutations(elements, { childList: true, subtree: true, attributes: true });
924
- return computed(() => {
925
- if (!isRendered())
926
- return [];
927
- const els = firstEl();
928
- // We are not interested what the mutation is, just that there is one.
929
- // Changes to the DOM may affect the children of the element.
930
- elementMutations();
931
- if (!els.currentElement)
932
- return [];
933
- const children = [];
934
- for (let index = 0; index < els.currentElement.children.length; index++) {
935
- const element = els.currentElement.children[index];
936
- if (element instanceof HTMLElement) {
937
- children.push(element);
938
- }
939
- }
940
- return children;
941
- }, { equal: (a, b) => a.length === b.length && a.every((v, i) => v === b[i]) });
998
+ const signalHostElementDimensions = () => signalElementDimensions(inject(ElementRef));
999
+ const injectViewportSize = () => {
1000
+ const document = inject(DOCUMENT$1);
1001
+ const zone = inject(NgZone);
1002
+ const destroyRef = inject(DestroyRef);
1003
+ const getSize = () => {
1004
+ const vv = document.defaultView?.visualViewport;
1005
+ if (vv)
1006
+ return { width: vv.width, height: vv.height };
1007
+ const win = document.defaultView;
1008
+ return { width: win?.innerWidth ?? 0, height: win?.innerHeight ?? 0 };
1009
+ };
1010
+ const size = signal(getSize(), ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1011
+ const onResize = () => zone.run(() => size.set(getSize()));
1012
+ const vv = document.defaultView?.visualViewport;
1013
+ if (vv) {
1014
+ vv.addEventListener('resize', onResize);
1015
+ destroyRef.onDestroy(() => vv.removeEventListener('resize', onResize));
1016
+ }
1017
+ else {
1018
+ const win = document.defaultView;
1019
+ win?.addEventListener('resize', onResize);
1020
+ destroyRef.onDestroy(() => win?.removeEventListener('resize', onResize));
1021
+ }
1022
+ return size;
942
1023
  };
943
1024
 
944
- const buildSignalEffects = (el, config) => {
945
- const elements = buildElementSignal(el);
946
- const injector = inject(Injector);
947
- effect(() => {
948
- const { currentElements, previousElements } = elements();
949
- for (const previousEl of previousElements) {
950
- if (currentElements.includes(previousEl))
951
- continue;
952
- const tokens = Object.keys(config.tokenMap)
953
- .map((key) => key.split(' '))
954
- .flat();
955
- if (!tokens.length)
956
- continue;
957
- config.cleanupFn(previousEl, tokens);
1025
+ const previousSignalValue = (signal) => {
1026
+ const obs = toObservable(signal).pipe(pairwise(), map(([prev]) => prev));
1027
+ return toSignal(obs);
1028
+ };
1029
+ const syncSignal = (from, to, options) => {
1030
+ let isFirstRun = options?.skipSyncRead ? false : true;
1031
+ if (!options?.skipSyncRead) {
1032
+ try {
1033
+ // this might throw if the signal is not yet initialized (eg. a required signal input inside the constructor)
1034
+ // in that case we just skip the initial sync
1035
+ to.set(from());
958
1036
  }
959
- for (const currentEl of currentElements) {
960
- if (previousElements.includes(currentEl))
961
- continue;
962
- for (const [tokens, condition] of Object.entries(config.tokenMap)) {
963
- untracked(() => {
964
- const tokenArray = tokens.split(' ');
965
- if (!tokenArray.length)
966
- return;
967
- config.updateFn(currentEl, tokenArray, condition());
968
- });
1037
+ catch {
1038
+ isFirstRun = false;
1039
+ if (isDevMode()) {
1040
+ console.warn('Failed to sync signals. The target signal is not yet initialized.', { from, to });
969
1041
  }
970
1042
  }
971
- });
972
- const effects = {};
973
- const has = (tokens) => tokens in effects;
974
- const push = (tokens, signal) => {
975
- if (has(tokens))
1043
+ }
1044
+ const ref = effect(() => {
1045
+ const formVal = from();
1046
+ if (options?.skipFirstRun && isFirstRun) {
1047
+ isFirstRun = false;
976
1048
  return;
977
- runInInjectionContext(injector, () => {
978
- effects[tokens] = effect(() => {
979
- const { currentElements } = untracked(() => elements());
980
- const value = signal();
981
- for (const el of currentElements) {
982
- const tokenArray = tokens.split(' ');
983
- if (!tokenArray.length)
984
- continue;
1049
+ }
1050
+ untracked(() => {
1051
+ to.set(formVal);
1052
+ });
1053
+ }, ...(ngDevMode ? [{ debugName: "ref" }] : /* istanbul ignore next */ []));
1054
+ return ref;
1055
+ };
1056
+ const maybeSignalValue = (value) => {
1057
+ if (isSignal(value)) {
1058
+ return value();
1059
+ }
1060
+ return value;
1061
+ };
1062
+ /**
1063
+ * A computed that will only be reactive until the source signal contains a truthy value.
1064
+ * All subsequent changes inside the computation will be ignored.
1065
+ */
1066
+ const computedTillTruthy = (source) => {
1067
+ const value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1068
+ const ref = effect(() => {
1069
+ const val = source();
1070
+ if (val) {
1071
+ value.set(val);
1072
+ ref.destroy();
1073
+ }
1074
+ }, ...(ngDevMode ? [{ debugName: "ref" }] : /* istanbul ignore next */ []));
1075
+ return value.asReadonly();
1076
+ };
1077
+ /**
1078
+ * A computed that will only be reactive until the source signal contains a falsy value.
1079
+ * All subsequent changes inside the computation will be ignored.
1080
+ */
1081
+ const computedTillFalsy = (source) => {
1082
+ const value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1083
+ const ref = effect(() => {
1084
+ const val = source();
1085
+ if (!val) {
1086
+ value.set(val);
1087
+ ref.destroy();
1088
+ }
1089
+ }, ...(ngDevMode ? [{ debugName: "ref" }] : /* istanbul ignore next */ []));
1090
+ return value.asReadonly();
1091
+ };
1092
+ /**
1093
+ * A writeable signal that will be set to the provided value once all inputs are set.
1094
+ * During that time, the signal will be set to `null`.
1095
+ */
1096
+ const deferredSignal = (valueFn) => {
1097
+ const valueSignal = signal(null, ...(ngDevMode ? [{ debugName: "valueSignal" }] : /* istanbul ignore next */ []));
1098
+ afterNextRender(() => {
1099
+ valueSignal.set(valueFn());
1100
+ });
1101
+ return valueSignal;
1102
+ };
1103
+ const memoizeSignal = (factory) => {
1104
+ let cached = null;
1105
+ return () => {
1106
+ if (!cached)
1107
+ cached = factory();
1108
+ return cached;
1109
+ };
1110
+ };
1111
+
1112
+ /** Inject a signal containing a boolean value indicating if the viewport is xs */
1113
+ const injectIsXs = memoizeSignal(() => injectObserveBreakpoint({ max: 'xs' }));
1114
+ /** Inject a signal containing a boolean value indicating if the viewport is sm */
1115
+ const injectIsSm = memoizeSignal(() => injectObserveBreakpoint({ min: 'sm', max: 'sm' }));
1116
+ /** Inject a signal containing a boolean value indicating if the viewport is md */
1117
+ const injectIsMd = memoizeSignal(() => injectObserveBreakpoint({ min: 'md', max: 'md' }));
1118
+ /** Inject a signal containing a boolean value indicating if the viewport is lg */
1119
+ const injectIsLg = memoizeSignal(() => injectObserveBreakpoint({ min: 'lg', max: 'lg' }));
1120
+ /** Inject a signal containing a boolean value indicating if the viewport is xl */
1121
+ const injectIsXl = memoizeSignal(() => injectObserveBreakpoint({ min: 'xl', max: 'xl' }));
1122
+ /** Inject a signal containing a boolean value indicating if the viewport is 2xl */
1123
+ const injectIs2Xl = memoizeSignal(() => injectObserveBreakpoint({ min: '2xl' }));
1124
+ /**
1125
+ * Inject a boolean value indicating if the viewport is matching the provided options.
1126
+ * This value is not reactive. If you want to react to changes, use the {@link injectObserveBreakpoint} function instead.
1127
+ */
1128
+ const injectBreakpointIsMatched = (options) => injectBreakpointObserver().isBreakpointMatched(options);
1129
+ /**
1130
+ * Inject a boolean value indicating if the media query is matched.
1131
+ * This value is not reactive. If you want to react to changes, use the {@link injectObserveMediaQuery} function instead.
1132
+ */
1133
+ const injectMediaQueryIsMatched = (mediaQuery) => injectBreakpointObserver().isMediaQueryMatched(mediaQuery);
1134
+ /**
1135
+ * Inject a signal containing a boolean value indicating if the viewport is matching the provided options.
1136
+ */
1137
+ const injectObserveBreakpoint = (options) => injectBreakpointObserver().observeBreakpoint(options);
1138
+ /**
1139
+ * Inject a signal containing a boolean value indicating if the media query is matched.
1140
+ */
1141
+ const injectObserveMediaQuery = (mediaQuery) => injectBreakpointObserver().observeMediaQuery(mediaQuery);
1142
+ /** Inject a signal containing the current breakpoint. */
1143
+ const injectCurrentBreakpoint = memoizeSignal(() => {
1144
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1145
+ const first = BREAKPOINT_ORDER[0];
1146
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1147
+ const last = BREAKPOINT_ORDER[BREAKPOINT_ORDER.length - 1];
1148
+ const highToLow = [...BREAKPOINT_ORDER].reverse();
1149
+ const signals = highToLow.map((bp) => injectObserveBreakpoint(bp === first ? { max: bp } : bp === last ? { min: bp } : { min: bp, max: bp }));
1150
+ return computed(() => {
1151
+ for (let i = 0; i < highToLow.length; i++) {
1152
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1153
+ if (signals[i]())
1154
+ return highToLow[i];
1155
+ }
1156
+ return first;
1157
+ });
1158
+ });
1159
+ /** Inject a signal that indicates if the user is using a portrait display */
1160
+ const injectIsPortrait = memoizeSignal(() => injectObserveMediaQuery('(orientation: portrait)'));
1161
+ /** Inject a signal that indicates if the user is using a landscape display */
1162
+ const injectIsLandscape = memoizeSignal(() => injectObserveMediaQuery('(orientation: landscape)'));
1163
+ /** Inject a signal containing the current display orientation */
1164
+ const injectDisplayOrientation = memoizeSignal(() => {
1165
+ const isPortrait = injectIsPortrait();
1166
+ return computed(() => {
1167
+ if (isPortrait())
1168
+ return 'portrait';
1169
+ return 'landscape';
1170
+ });
1171
+ });
1172
+ /** Inject a signal that indicates if the device has a touch input */
1173
+ const injectHasTouchInput = memoizeSignal(() => injectObserveMediaQuery('(pointer: coarse)'));
1174
+ /** Inject a signal that indicates if the device has a fine input (mouse or stylus) */
1175
+ const injectHasPrecisionInput = memoizeSignal(() => injectObserveMediaQuery('(pointer: fine)'));
1176
+ /** Inject a signal containing the current device input type */
1177
+ const injectDeviceInputType = memoizeSignal(() => {
1178
+ const isTouch = injectHasTouchInput();
1179
+ return computed(() => {
1180
+ if (isTouch())
1181
+ return 'touch';
1182
+ return 'mouse';
1183
+ });
1184
+ });
1185
+ /** Inject a signal containing a boolean value indicating if the user can hover (eg. using a mouse) */
1186
+ const injectCanHover = memoizeSignal(() => injectObserveMediaQuery('(hover: hover)'));
1187
+ /** Inject a signal containing the viewport dimensions */
1188
+ const injectViewportDimensions = memoizeSignal(() => signalElementDimensions(createDocumentElementSignal()));
1189
+ /** Inject a signal containing the scrollbar dimensions. Dimensions will be 0 if scrollbars overlap the page contents (like on mobile). */
1190
+ const injectScrollbarDimensions = memoizeSignal(() => {
1191
+ const document = inject(DOCUMENT);
1192
+ const renderer = injectRenderer();
1193
+ const scrollbarRuler = renderer.createElement('div');
1194
+ scrollbarRuler.style.width = '100px';
1195
+ scrollbarRuler.style.height = '100px';
1196
+ scrollbarRuler.style.overflow = 'scroll';
1197
+ scrollbarRuler.style.position = 'absolute';
1198
+ scrollbarRuler.style.top = '-9999px';
1199
+ scrollbarRuler.style.scrollbarWidth = getComputedStyle(document.documentElement).scrollbarWidth;
1200
+ renderer.appendChild(document.body, scrollbarRuler);
1201
+ const scrollContainerDimensions = signalElementDimensions(scrollbarRuler);
1202
+ return computed(() => {
1203
+ const client = scrollContainerDimensions().client;
1204
+ if (!client)
1205
+ return null;
1206
+ return {
1207
+ width: Math.max(0, 100 - client.width),
1208
+ height: Math.max(0, 100 - client.height),
1209
+ };
1210
+ });
1211
+ });
1212
+
1213
+ const BREAKPOINT_KEY_SET = new Set(BREAKPOINT_ORDER);
1214
+ const isBreakpointMap = (value) => {
1215
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
1216
+ return false;
1217
+ const keys = Object.keys(value);
1218
+ return keys.length > 0 && keys.every((k) => BREAKPOINT_KEY_SET.has(k));
1219
+ };
1220
+ const resolveFromMap = (map, bp, defaultValue) => {
1221
+ const idx = BREAKPOINT_ORDER.indexOf(bp);
1222
+ for (let i = idx; i >= 0; i--) {
1223
+ const v = map[BREAKPOINT_ORDER[i]];
1224
+ if (v !== undefined)
1225
+ return v;
1226
+ }
1227
+ return defaultValue;
1228
+ };
1229
+ const breakpointTransformBase = (coerce) => {
1230
+ const currentBp = injectCurrentBreakpoint();
1231
+ const injector = inject(Injector);
1232
+ const raw = signal(undefined, ...(ngDevMode ? [{ debugName: "raw" }] : /* istanbul ignore next */ []));
1233
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1234
+ let capturedDefault = undefined;
1235
+ let initialized = false;
1236
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1237
+ let cachedSig = null;
1238
+ const transformFn = (value) => {
1239
+ const coerced = isBreakpointMap(value) ? value : coerce(value);
1240
+ if (!initialized) {
1241
+ capturedDefault = coerced;
1242
+ initialized = true;
1243
+ }
1244
+ raw.set(coerced);
1245
+ return isBreakpointMap(coerced)
1246
+ ? resolveFromMap(coerced, currentBp(), capturedDefault)
1247
+ : coerced;
1248
+ };
1249
+ effect(() => {
1250
+ const bp = currentBp();
1251
+ const r = raw();
1252
+ if (!cachedSig) {
1253
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1254
+ const instance = injector.get(BREAKPOINT_INSTANCE_TOKEN);
1255
+ for (const key of Object.keys(instance)) {
1256
+ const val = instance[key];
1257
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1258
+ if (val && typeof val === 'function' && val[SIGNAL]?.transformFn === transformFn) {
1259
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1260
+ cachedSig = val;
1261
+ break;
1262
+ }
1263
+ }
1264
+ }
1265
+ if (!cachedSig || r === undefined || !isBreakpointMap(r))
1266
+ return;
1267
+ const resolved = resolveFromMap(r, bp, capturedDefault);
1268
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1269
+ untracked(() => setInputSignal(cachedSig, resolved));
1270
+ });
1271
+ return transformFn;
1272
+ };
1273
+ /**
1274
+ * Transform factory for boolean inputs.
1275
+ * Coerces plain values with `booleanAttribute`; resolves {@link BreakpointMap} mobile-first.
1276
+ *
1277
+ * @example
1278
+ * snap = input(false, { transform: boolBreakpointTransform() });
1279
+ * // Template: `snap` | `[snap]="true"` | `[snap]="{ xs: false, md: true }"`
1280
+ */
1281
+ const boolBreakpointTransform = () => breakpointTransformBase(booleanAttribute);
1282
+ /**
1283
+ * Transform factory for number inputs.
1284
+ * Coerces plain values with `numberAttribute`; resolves {@link BreakpointMap} mobile-first.
1285
+ *
1286
+ * @example
1287
+ * scrollMargin = input(0, { transform: numberBreakpointTransform() });
1288
+ * // Template: `[scrollMargin]="16"` | `[scrollMargin]="{ xs: 0, md: 16 }"`
1289
+ */
1290
+ const numberBreakpointTransform = () => breakpointTransformBase((v) => numberAttribute(v));
1291
+ /**
1292
+ * Transform factory for any typed input (string unions, arrays, objects, etc.).
1293
+ * Passes plain values through as-is; resolves {@link BreakpointMap} mobile-first.
1294
+ * A value is treated as a {@link BreakpointMap} only when all its keys are valid breakpoint names.
1295
+ *
1296
+ * @example
1297
+ * itemSize = input('auto', { transform: typedBreakpointTransform<ScrollableItemSize>() });
1298
+ * tags = input([], { transform: typedBreakpointTransform<string[]>() });
1299
+ * // Template: `[itemSize]="'third'"` | `[itemSize]="{ xs: 'full', md: 'third' }"`
1300
+ */
1301
+ const typedBreakpointTransform = () => breakpointTransformBase((v) => v);
1302
+ const injectBreakpointInput = (inputSignal, defaultValue) => {
1303
+ const currentBreakpoint = injectCurrentBreakpoint();
1304
+ return computed(() => {
1305
+ const value = inputSignal();
1306
+ if (!isBreakpointMap(value))
1307
+ return value;
1308
+ return resolveFromMap(value, currentBreakpoint(), defaultValue);
1309
+ });
1310
+ };
1311
+ const booleanBreakpointAttribute = (value) => {
1312
+ if (isBreakpointMap(value))
1313
+ return value;
1314
+ return booleanAttribute(value);
1315
+ };
1316
+ const numberBreakpointAttribute = (value) => {
1317
+ if (isBreakpointMap(value))
1318
+ return value;
1319
+ return numberAttribute(value);
1320
+ };
1321
+ const BREAKPOINT_INSTANCE_TOKEN = new InjectionToken('BREAKPOINT_INSTANCE_TOKEN');
1322
+ const provideBreakpointInstance = (componentClass) => ({
1323
+ provide: BREAKPOINT_INSTANCE_TOKEN,
1324
+ useExisting: componentClass,
1325
+ });
1326
+
1327
+ const controlValueSignal = (control, options) => {
1328
+ const getRawValueSafe = (ctrl) => {
1329
+ try {
1330
+ return isSignal(ctrl) ? (ctrl()?.getRawValue() ?? null) : (ctrl?.getRawValue() ?? null);
1331
+ }
1332
+ catch {
1333
+ // Ignore errors. This can happen if the passed control is a required input and is not yet initialized.
1334
+ return null;
1335
+ }
1336
+ };
1337
+ const initialValue = getRawValueSafe(control);
1338
+ const controlStream = isSignal(control)
1339
+ ? toObservable(control)
1340
+ : of(control);
1341
+ const controlObs = controlStream.pipe(switchMap((ctrl) => {
1342
+ if (!ctrl)
1343
+ return of(null);
1344
+ const vcsObs = options?.debounceTime
1345
+ ? ctrl.valueChanges.pipe(debounceTime(options.debounceTime))
1346
+ : ctrl.valueChanges;
1347
+ return vcsObs.pipe(startWith(ctrl.getRawValue()), map(() => ctrl.getRawValue()));
1348
+ }));
1349
+ const obs = !options?.debounceFirst ? merge(of(initialValue), controlObs) : controlObs;
1350
+ return toSignal(obs.pipe(distinctUntilChanged((a, b) => equal(a, b))), {
1351
+ initialValue,
1352
+ });
1353
+ };
1354
+ /**
1355
+ * The first item in the pair is the previous value and the second item is the current value.
1356
+ */
1357
+ const controlValueSignalWithPrevious = (control, options) => {
1358
+ const data = linkedSignal({ ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), source: controlValueSignal(control, options),
1359
+ computation: (curr, prev) => [prev?.source ?? null, curr] });
1360
+ return data.asReadonly();
1361
+ };
1362
+
1363
+ const signalElementMutations = (el, options) => {
1364
+ const destroyRef = inject(DestroyRef);
1365
+ const elements = buildElementSignal(el);
1366
+ const firstEl = firstElementSignal(elements);
1367
+ const zone = inject(NgZone);
1368
+ const isRendered = signalIsRendered();
1369
+ const elementMutationsSignal = signal(null, ...(ngDevMode ? [{ debugName: "elementMutationsSignal" }] : /* istanbul ignore next */ []));
1370
+ const observer = new MutationObserver((e) => {
1371
+ if (!isRendered())
1372
+ return;
1373
+ const entry = e[0];
1374
+ if (entry) {
1375
+ zone.run(() => elementMutationsSignal.set(entry));
1376
+ }
1377
+ });
1378
+ effect(() => {
1379
+ const els = firstEl();
1380
+ elementMutationsSignal.set(null);
1381
+ if (els.previousElement) {
1382
+ observer.disconnect();
1383
+ }
1384
+ if (els.currentElement) {
1385
+ observer.observe(els.currentElement, options);
1386
+ }
1387
+ });
1388
+ destroyRef.onDestroy(() => observer.disconnect());
1389
+ return elementMutationsSignal.asReadonly();
1390
+ };
1391
+ const signalHostElementMutations = (options) => signalElementMutations(inject(ElementRef), options);
1392
+
1393
+ const signalElementChildren = (el) => {
1394
+ const elements = buildElementSignal(el);
1395
+ const firstEl = firstElementSignal(elements);
1396
+ const isRendered = signalIsRendered();
1397
+ const elementMutations = signalElementMutations(elements, { childList: true, subtree: true, attributes: true });
1398
+ return computed(() => {
1399
+ if (!isRendered())
1400
+ return [];
1401
+ const els = firstEl();
1402
+ // We are not interested what the mutation is, just that there is one.
1403
+ // Changes to the DOM may affect the children of the element.
1404
+ elementMutations();
1405
+ if (!els.currentElement)
1406
+ return [];
1407
+ const children = [];
1408
+ for (let index = 0; index < els.currentElement.children.length; index++) {
1409
+ const element = els.currentElement.children[index];
1410
+ if (element instanceof HTMLElement) {
1411
+ children.push(element);
1412
+ }
1413
+ }
1414
+ return children;
1415
+ }, { equal: (a, b) => a.length === b.length && a.every((v, i) => v === b[i]) });
1416
+ };
1417
+
1418
+ const buildSignalEffects = (el, config) => {
1419
+ const elements = buildElementSignal(el);
1420
+ const injector = inject(Injector);
1421
+ effect(() => {
1422
+ const { currentElements, previousElements } = elements();
1423
+ for (const previousEl of previousElements) {
1424
+ if (currentElements.includes(previousEl))
1425
+ continue;
1426
+ const tokens = Object.keys(config.tokenMap)
1427
+ .map((key) => key.split(' '))
1428
+ .flat();
1429
+ if (!tokens.length)
1430
+ continue;
1431
+ config.cleanupFn(previousEl, tokens);
1432
+ }
1433
+ for (const currentEl of currentElements) {
1434
+ if (previousElements.includes(currentEl))
1435
+ continue;
1436
+ for (const [tokens, condition] of Object.entries(config.tokenMap)) {
1437
+ untracked(() => {
1438
+ const tokenArray = tokens.split(' ');
1439
+ if (!tokenArray.length)
1440
+ return;
1441
+ config.updateFn(currentEl, tokenArray, condition());
1442
+ });
1443
+ }
1444
+ }
1445
+ });
1446
+ const effects = {};
1447
+ const has = (tokens) => tokens in effects;
1448
+ const push = (tokens, signal) => {
1449
+ if (has(tokens))
1450
+ return;
1451
+ runInInjectionContext(injector, () => {
1452
+ effects[tokens] = effect(() => {
1453
+ const { currentElements } = untracked(() => elements());
1454
+ const value = signal();
1455
+ for (const el of currentElements) {
1456
+ const tokenArray = tokens.split(' ');
1457
+ if (!tokenArray.length)
1458
+ continue;
985
1459
  config.updateFn(el, tokenArray, value);
986
1460
  }
987
1461
  });
@@ -1075,75 +1549,293 @@ const signalStyles = (el, styleMap) => {
1075
1549
  };
1076
1550
  const signalHostStyles = (styleMap) => signalStyles(inject(ElementRef), styleMap);
1077
1551
 
1078
- const boundingClientRectToElementRect = (rect) => ({
1079
- bottom: rect.bottom,
1080
- height: rect.height,
1081
- left: rect.left,
1082
- right: rect.right,
1083
- top: rect.top,
1084
- width: rect.width,
1085
- x: rect.x,
1086
- y: rect.y,
1552
+ const elementCanScroll = (element, direction) => {
1553
+ const el = element || document.documentElement;
1554
+ const { scrollHeight, clientHeight, scrollWidth, clientWidth } = el;
1555
+ if (direction === 'x') {
1556
+ return scrollWidth > clientWidth;
1557
+ }
1558
+ else if (direction === 'y') {
1559
+ return scrollHeight > clientHeight;
1560
+ }
1561
+ return scrollHeight > clientHeight || scrollWidth > clientWidth;
1562
+ };
1563
+ const createViewportRect = () => ({
1564
+ left: 0,
1565
+ top: 0,
1566
+ right: window.innerWidth,
1567
+ bottom: window.innerHeight,
1568
+ width: window.innerWidth,
1569
+ height: window.innerHeight,
1570
+ x: 0,
1571
+ y: 0,
1572
+ toJSON: () => ({}),
1087
1573
  });
1088
- const createElementDimensions = (el, rect) => {
1089
- if (!el) {
1574
+ const isElementVisible = (options) => {
1575
+ const { container, element } = options;
1576
+ if (!element) {
1577
+ return null;
1578
+ }
1579
+ const elementRect = options.elementRect || element.getBoundingClientRect();
1580
+ const containerRect = container ? options.containerRect || container.getBoundingClientRect() : createViewportRect();
1581
+ const canScroll = elementCanScroll(container);
1582
+ if (!canScroll) {
1090
1583
  return {
1091
- rect: null,
1092
- client: null,
1093
- scroll: null,
1094
- offset: null,
1584
+ inline: true,
1585
+ block: true,
1586
+ blockIntersection: 1,
1587
+ inlineIntersection: 1,
1588
+ intersectionRatio: 1,
1589
+ isIntersecting: true,
1590
+ element,
1591
+ containerRect,
1592
+ elementRect,
1095
1593
  };
1096
1594
  }
1097
- const cachedNormalizedRect = rect ? boundingClientRectToElementRect(rect) : null;
1098
- const rectFn = () => cachedNormalizedRect ? cachedNormalizedRect : boundingClientRectToElementRect(el.getBoundingClientRect());
1595
+ const elLeft = elementRect.left;
1596
+ const elTop = elementRect.top;
1597
+ const elWidth = elementRect.width || 1;
1598
+ const elHeight = elementRect.height || 1;
1599
+ const elRight = elLeft + elWidth;
1600
+ const elBottom = elTop + elHeight;
1601
+ const conLeft = containerRect.left;
1602
+ const conTop = containerRect.top;
1603
+ const conRight = conLeft + containerRect.width;
1604
+ const conBottom = conTop + containerRect.height;
1605
+ const isElementInlineVisible = elLeft >= conLeft && elRight <= conRight;
1606
+ const isElementBlockVisible = elTop >= conTop && elBottom <= conBottom;
1607
+ const inlineIntersection = Math.min(elRight, conRight) - Math.max(elLeft, conLeft);
1608
+ const blockIntersection = Math.min(elBottom, conBottom) - Math.max(elTop, conTop);
1609
+ const inlineIntersectionPercentage = clamp(inlineIntersection / elWidth, 0, 1);
1610
+ const blockIntersectionPercentage = clamp(blockIntersection / elHeight, 0, 1);
1611
+ return {
1612
+ inline: isElementInlineVisible,
1613
+ block: isElementBlockVisible,
1614
+ inlineIntersection: inlineIntersectionPercentage,
1615
+ blockIntersection: blockIntersectionPercentage,
1616
+ isIntersecting: isElementInlineVisible && isElementBlockVisible,
1617
+ element,
1618
+ containerRect,
1619
+ elementRect,
1620
+ // Round the intersection ratio to the nearest 0.01 to avoid floating point errors and system scaling issues.
1621
+ intersectionRatio: Math.round(Math.min(inlineIntersectionPercentage, blockIntersectionPercentage) * 100) / 100,
1622
+ };
1623
+ };
1624
+ const getElementScrollCoordinates = (options) => {
1625
+ const { container, element, direction, behavior = 'smooth', origin = 'nearest', scrollBlockMargin = 0, scrollInlineMargin = 0, } = options;
1626
+ if (!element || !container || !elementCanScroll(container)) {
1627
+ return {
1628
+ behavior,
1629
+ left: undefined,
1630
+ top: undefined,
1631
+ };
1632
+ }
1633
+ const elementRect = element.getBoundingClientRect();
1634
+ const containerRect = container.getBoundingClientRect();
1635
+ const { scrollLeft, scrollTop } = container;
1636
+ const elWidth = elementRect.width;
1637
+ const elHeight = elementRect.height;
1638
+ const elLeft = elementRect.left;
1639
+ const elTop = elementRect.top;
1640
+ const elRight = elementRect.right;
1641
+ const elBottom = elementRect.bottom;
1642
+ const conWidth = containerRect.width;
1643
+ const conHeight = containerRect.height;
1644
+ const conLeft = containerRect.left;
1645
+ const conTop = containerRect.top;
1646
+ const conRight = containerRect.right;
1647
+ const conBottom = containerRect.bottom;
1648
+ const shouldScrollLeft = direction === 'inline' || direction === 'both' || !direction;
1649
+ const shouldScrollTop = direction === 'block' || direction === 'both' || !direction;
1650
+ let scrollLeftTo = scrollLeft;
1651
+ let scrollTopTo = scrollTop;
1652
+ const relativeTop = elTop - conTop;
1653
+ const relativeLeft = elLeft - conLeft;
1654
+ const calculateScrollToStart = () => {
1655
+ scrollLeftTo = scrollLeft + relativeLeft - scrollInlineMargin;
1656
+ scrollTopTo = scrollTop + relativeTop - scrollBlockMargin;
1657
+ };
1658
+ const calculateScrollToEnd = () => {
1659
+ scrollLeftTo = scrollLeft + relativeLeft - conWidth + elWidth + scrollInlineMargin;
1660
+ scrollTopTo = scrollTop + relativeTop - conHeight + elHeight + scrollBlockMargin;
1661
+ };
1662
+ const calculateScrollToCenter = () => {
1663
+ scrollLeftTo = scrollLeft + relativeLeft - conWidth / 2 + elWidth / 2;
1664
+ scrollTopTo = scrollTop + relativeTop - conHeight / 2 + elHeight / 2;
1665
+ };
1666
+ const calculateScrollToNearest = () => {
1667
+ const isAbove = elBottom < conTop;
1668
+ const isPartialAbove = elTop < conTop && elBottom > conTop;
1669
+ const isBelow = elTop > conBottom;
1670
+ const isPartialBelow = elTop < conBottom && elBottom > conBottom;
1671
+ const isLeft = elRight < conLeft;
1672
+ const isPartialLeft = elLeft < conLeft && elRight > conLeft;
1673
+ const isRight = elLeft > conRight;
1674
+ const isPartialRight = elLeft < conRight && elRight > conRight;
1675
+ if (isAbove || isPartialAbove || isLeft || isPartialLeft) {
1676
+ calculateScrollToStart();
1677
+ }
1678
+ else if (isBelow || isPartialBelow || isRight || isPartialRight) {
1679
+ calculateScrollToEnd();
1680
+ }
1681
+ };
1682
+ switch (origin) {
1683
+ case 'start':
1684
+ calculateScrollToStart();
1685
+ break;
1686
+ case 'end':
1687
+ calculateScrollToEnd();
1688
+ break;
1689
+ case 'center':
1690
+ calculateScrollToCenter();
1691
+ break;
1692
+ case 'nearest':
1693
+ calculateScrollToNearest();
1694
+ break;
1695
+ }
1099
1696
  return {
1100
- rect: rectFn,
1101
- client: { width: el.clientWidth, height: el.clientHeight },
1102
- scroll: { width: el.scrollWidth, height: el.scrollHeight },
1103
- offset: { width: el.offsetWidth, height: el.offsetHeight },
1697
+ behavior,
1698
+ left: shouldScrollLeft ? scrollLeftTo : undefined,
1699
+ top: shouldScrollTop ? scrollTopTo : undefined,
1104
1700
  };
1105
1701
  };
1106
- const signalElementDimensions = (el) => {
1107
- const destroyRef = inject(DestroyRef);
1108
- const elements = buildElementSignal(el);
1109
- const firstEl = firstElementSignal(elements);
1110
- const zone = inject(NgZone);
1111
- const isRendered = signalIsRendered();
1112
- const initialValue = () => createElementDimensions(firstEl().currentElement);
1113
- const elementDimensionsSignal = signal(initialValue(), ...(ngDevMode ? [{ debugName: "elementDimensionsSignal" }] : []));
1114
- const observer = new ResizeObserver((e) => {
1115
- if (!isRendered())
1116
- return;
1117
- const entry = e[0];
1118
- if (entry) {
1119
- const target = entry.target;
1120
- const newDimensions = createElementDimensions(target);
1121
- zone.run(() => elementDimensionsSignal.set(newDimensions));
1702
+ const scrollToElement = (options) => {
1703
+ options.container?.scrollTo(getElementScrollCoordinates(options));
1704
+ };
1705
+
1706
+ const MIN_SNAP_DELTA_PX = 1;
1707
+ const getScrollSnapTarget = (items, container, direction, origin, margin = 0) => {
1708
+ if (!items.length)
1709
+ return null;
1710
+ const containerRect = container.getBoundingClientRect();
1711
+ const containerSize = direction === 'horizontal' ? containerRect.width : containerRect.height;
1712
+ let bestElement = null;
1713
+ let bestOrigin = 'start';
1714
+ let bestAbsDelta = Infinity;
1715
+ const updateBest = (element, o, delta) => {
1716
+ const abs = Math.abs(delta);
1717
+ if (abs < bestAbsDelta) {
1718
+ bestAbsDelta = abs;
1719
+ bestElement = element;
1720
+ bestOrigin = o;
1122
1721
  }
1123
- });
1124
- effect(() => {
1125
- const els = firstEl();
1126
- untracked(() => {
1127
- elementDimensionsSignal.set(initialValue());
1128
- if (els.previousElement) {
1129
- observer.disconnect();
1722
+ };
1723
+ for (const item of items) {
1724
+ const itemRect = item.getBoundingClientRect();
1725
+ const itemSize = direction === 'horizontal' ? itemRect.width : itemRect.height;
1726
+ const relativeStart = direction === 'horizontal' ? itemRect.left - containerRect.left : itemRect.top - containerRect.top;
1727
+ const relativeEnd = relativeStart + itemSize;
1728
+ if (itemSize > containerSize) {
1729
+ const isStartEdgeVisible = relativeStart >= 0;
1730
+ const isEndEdgeVisible = relativeEnd <= containerSize;
1731
+ if (!isStartEdgeVisible && !isEndEdgeVisible)
1732
+ continue;
1733
+ if (isStartEdgeVisible) {
1734
+ updateBest(item, 'start', relativeStart - margin);
1130
1735
  }
1131
- if (els.currentElement) {
1132
- const computedDisplay = getComputedStyle(els.currentElement).display;
1133
- const currentElIsAngularComponent = els.currentElement?.tagName.toLowerCase().includes('-');
1134
- if (computedDisplay === 'inline' && isDevMode() && currentElIsAngularComponent) {
1135
- console.error(`Element <${els.currentElement?.tagName.toLowerCase()}> is an Angular component and has a display of 'inline'. Inline elements cannot be observed for dimensions. Please change it to 'block' or something else.`);
1736
+ else {
1737
+ updateBest(item, 'end', relativeEnd - containerSize + margin);
1738
+ }
1739
+ continue;
1740
+ }
1741
+ const computeDelta = (o) => {
1742
+ switch (o) {
1743
+ case 'start':
1744
+ return relativeStart - margin;
1745
+ case 'end':
1746
+ return relativeEnd - containerSize + margin;
1747
+ case 'center':
1748
+ return relativeStart + itemSize / 2 - containerSize / 2;
1749
+ }
1750
+ };
1751
+ if (origin === 'auto') {
1752
+ for (const o of ['start', 'center', 'end']) {
1753
+ updateBest(item, o, computeDelta(o));
1754
+ }
1755
+ }
1756
+ else {
1757
+ updateBest(item, origin, computeDelta(origin));
1758
+ }
1759
+ }
1760
+ if (!bestElement || bestAbsDelta < MIN_SNAP_DELTA_PX)
1761
+ return null;
1762
+ return { element: bestElement, origin: bestOrigin };
1763
+ };
1764
+ const getScrollContainerTarget = (entries, direction) => {
1765
+ const firstVisible = entries.find((i) => i.intersectionRatio > 0);
1766
+ const lastVisible = [...entries].reverse().find((i) => i.intersectionRatio > 0);
1767
+ const relevantEntry = direction === 'start' ? firstVisible : lastVisible;
1768
+ if (!relevantEntry)
1769
+ return null;
1770
+ const relevantIndex = entries.indexOf(relevantEntry);
1771
+ const nextIndex = relevantEntry.intersectionRatio !== 1
1772
+ ? relevantIndex
1773
+ : direction === 'start'
1774
+ ? relevantIndex - 1
1775
+ : relevantIndex + 1;
1776
+ const element = entries[nextIndex]?.target ?? relevantEntry.target;
1777
+ return { element, origin: direction === 'end' ? 'start' : 'end' };
1778
+ };
1779
+ const getScrollItemTarget = (entries, container, direction, scrollOrigin, axisDirection) => {
1780
+ const firstVisible = entries.find((i) => i.intersectionRatio > 0);
1781
+ const lastVisible = [...entries].reverse().find((i) => i.intersectionRatio > 0);
1782
+ if (!firstVisible || !lastVisible)
1783
+ return null;
1784
+ const firstIndex = entries.indexOf(firstVisible);
1785
+ const lastIndex = entries.indexOf(lastVisible);
1786
+ const containerRect = container.getBoundingClientRect();
1787
+ // Only a single item is visible — it must be oversized (wider/taller than the container).
1788
+ if (firstVisible === lastVisible) {
1789
+ const itemRect = firstVisible.target.getBoundingClientRect();
1790
+ const isStartEdgeVisible = axisDirection === 'horizontal'
1791
+ ? Math.round(itemRect.left) >= Math.round(containerRect.left)
1792
+ : Math.round(itemRect.top) >= Math.round(containerRect.top);
1793
+ const isEndEdgeVisible = axisDirection === 'horizontal'
1794
+ ? Math.round(itemRect.right) <= Math.round(containerRect.right)
1795
+ : Math.round(itemRect.bottom) <= Math.round(containerRect.bottom);
1796
+ if (!isStartEdgeVisible || !isEndEdgeVisible) {
1797
+ if (direction === 'start') {
1798
+ if (isStartEdgeVisible) {
1799
+ const prevIndex = firstIndex - 1;
1800
+ const element = entries[prevIndex]?.target;
1801
+ if (!element)
1802
+ return null;
1803
+ return { element, index: prevIndex, origin: 'end' };
1136
1804
  }
1137
- observer.observe(els.currentElement);
1805
+ return { element: firstVisible.target, index: firstIndex, origin: 'start' };
1138
1806
  }
1139
- });
1140
- });
1141
- destroyRef.onDestroy(() => observer.disconnect());
1142
- return computed(() => elementDimensionsSignal(), {
1143
- equal: (a, b) => equal(a, b),
1144
- });
1807
+ else {
1808
+ if (isEndEdgeVisible) {
1809
+ const nextIndex = lastIndex + 1;
1810
+ const element = entries[nextIndex]?.target;
1811
+ if (!element)
1812
+ return null;
1813
+ return { element, index: nextIndex, origin: 'start' };
1814
+ }
1815
+ return { element: lastVisible.target, index: lastIndex, origin: 'end' };
1816
+ }
1817
+ }
1818
+ }
1819
+ else if (scrollOrigin === 'center') {
1820
+ const entry = direction === 'start' ? firstVisible : lastVisible;
1821
+ const index = direction === 'start' ? firstIndex : lastIndex;
1822
+ return { element: entry.target, index, origin: 'center' };
1823
+ }
1824
+ const entry = direction === 'start' ? firstVisible : lastVisible;
1825
+ const entryIndex = direction === 'start' ? firstIndex : lastIndex;
1826
+ if (Math.round(entry.intersectionRatio) === 1) {
1827
+ if (direction === 'start' && entryIndex === 0)
1828
+ return null;
1829
+ if (direction === 'end' && entryIndex === entries.length - 1)
1830
+ return null;
1831
+ const nextIndex = direction === 'start' ? entryIndex - 1 : entryIndex + 1;
1832
+ const element = entries[nextIndex]?.target;
1833
+ if (!element)
1834
+ return null;
1835
+ return { element, index: nextIndex, origin: direction };
1836
+ }
1837
+ return { element: entry.target, index: entryIndex, origin: direction };
1145
1838
  };
1146
- const signalHostElementDimensions = () => signalElementDimensions(inject(ElementRef));
1147
1839
 
1148
1840
  const createPositionObject = (entry) => {
1149
1841
  const boundingRect = entry.boundingClientRect;
@@ -1175,8 +1867,8 @@ const signalElementIntersection = (el, options) => {
1175
1867
  const zone = inject(NgZone);
1176
1868
  const isRendered = signalIsRendered();
1177
1869
  const isEnabled = options?.enabled ?? signal(true);
1178
- const elementIntersectionSignal = signal([], ...(ngDevMode ? [{ debugName: "elementIntersectionSignal" }] : []));
1179
- const observer = signal(null, ...(ngDevMode ? [{ debugName: "observer" }] : []));
1870
+ const elementIntersectionSignal = signal([], ...(ngDevMode ? [{ debugName: "elementIntersectionSignal" }] : /* istanbul ignore next */ []));
1871
+ const observer = signal(null, ...(ngDevMode ? [{ debugName: "observer" }] : /* istanbul ignore next */ []));
1180
1872
  const currentlyObservedElements = new Set();
1181
1873
  const updateIntersections = (entries) => {
1182
1874
  let currentValues = [...elementIntersectionSignal()];
@@ -1292,7 +1984,7 @@ const signalElementLastScrollDirection = (el) => {
1292
1984
  const elements = buildElementSignal(el);
1293
1985
  const element = firstElementSignal(elements);
1294
1986
  const destroyRef = inject(DestroyRef);
1295
- const lastScrollDirection = signal(null, ...(ngDevMode ? [{ debugName: "lastScrollDirection" }] : []));
1987
+ const lastScrollDirection = signal(null, ...(ngDevMode ? [{ debugName: "lastScrollDirection" }] : /* istanbul ignore next */ []));
1296
1988
  let lastScrollTop = 0;
1297
1989
  let lastScrollLeft = 0;
1298
1990
  toObservable(element)
@@ -1353,7 +2045,7 @@ const signalElementScrollState = (el, options) => {
1353
2045
  element.scrollTop = scrollPosition.top;
1354
2046
  ref.destroy();
1355
2047
  }
1356
- }, ...(ngDevMode ? [{ debugName: "ref" }] : []));
2048
+ }, ...(ngDevMode ? [{ debugName: "ref" }] : /* istanbul ignore next */ []));
1357
2049
  }
1358
2050
  const notScrollable = (dimensions) => ({
1359
2051
  canScroll: false,
@@ -1361,214 +2053,26 @@ const signalElementScrollState = (el, options) => {
1361
2053
  canScrollVertically: false,
1362
2054
  elementDimensions: dimensions,
1363
2055
  });
1364
- return computed(() => {
1365
- const element = observedEl().currentElement;
1366
- const dimensions = elementDimensions();
1367
- // We are not interested what the mutation is, just that there is one.
1368
- // Changes to the DOM can affect the scroll state of the element.
1369
- elementMutations();
1370
- if (!element || !isRendered())
1371
- return notScrollable(dimensions);
1372
- const { scrollWidth, scrollHeight, clientHeight, clientWidth } = element;
1373
- const canScrollHorizontally = scrollWidth > clientWidth;
1374
- const canScrollVertically = scrollHeight > clientHeight;
1375
- return {
1376
- canScroll: canScrollHorizontally || canScrollVertically,
1377
- canScrollHorizontally,
1378
- canScrollVertically,
1379
- elementDimensions: dimensions,
1380
- };
1381
- }, { equal: (a, b) => areScrollStatesEqual(a, b) });
1382
- };
1383
- const signalHostElementScrollState = () => signalElementScrollState(inject(ElementRef));
1384
-
1385
- const previousSignalValue = (signal) => {
1386
- const obs = toObservable(signal).pipe(pairwise(), map(([prev]) => prev));
1387
- return toSignal(obs);
1388
- };
1389
- const syncSignal = (from, to, options) => {
1390
- let isFirstRun = options?.skipSyncRead ? false : true;
1391
- if (!options?.skipSyncRead) {
1392
- try {
1393
- // this might throw if the signal is not yet initialized (eg. a required signal input inside the constructor)
1394
- // in that case we just skip the initial sync
1395
- to.set(from());
1396
- }
1397
- catch {
1398
- isFirstRun = false;
1399
- if (isDevMode()) {
1400
- console.warn('Failed to sync signals. The target signal is not yet initialized.', { from, to });
1401
- }
1402
- }
1403
- }
1404
- const ref = effect(() => {
1405
- const formVal = from();
1406
- if (options?.skipFirstRun && isFirstRun) {
1407
- isFirstRun = false;
1408
- return;
1409
- }
1410
- untracked(() => {
1411
- to.set(formVal);
1412
- });
1413
- }, ...(ngDevMode ? [{ debugName: "ref" }] : []));
1414
- return ref;
1415
- };
1416
- const maybeSignalValue = (value) => {
1417
- if (isSignal(value)) {
1418
- return value();
1419
- }
1420
- return value;
1421
- };
1422
- /**
1423
- * A computed that will only be reactive until the source signal contains a truthy value.
1424
- * All subsequent changes inside the computation will be ignored.
1425
- */
1426
- const computedTillTruthy = (source) => {
1427
- const value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
1428
- const ref = effect(() => {
1429
- const val = source();
1430
- if (val) {
1431
- value.set(val);
1432
- ref.destroy();
1433
- }
1434
- }, ...(ngDevMode ? [{ debugName: "ref" }] : []));
1435
- return value.asReadonly();
1436
- };
1437
- /**
1438
- * A computed that will only be reactive until the source signal contains a falsy value.
1439
- * All subsequent changes inside the computation will be ignored.
1440
- */
1441
- const computedTillFalsy = (source) => {
1442
- const value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
1443
- const ref = effect(() => {
1444
- const val = source();
1445
- if (!val) {
1446
- value.set(val);
1447
- ref.destroy();
1448
- }
1449
- }, ...(ngDevMode ? [{ debugName: "ref" }] : []));
1450
- return value.asReadonly();
1451
- };
1452
- /**
1453
- * A writeable signal that will be set to the provided value once all inputs are set.
1454
- * During that time, the signal will be set to `null`.
1455
- */
1456
- const deferredSignal = (valueFn) => {
1457
- const valueSignal = signal(null, ...(ngDevMode ? [{ debugName: "valueSignal" }] : []));
1458
- afterNextRender(() => {
1459
- valueSignal.set(valueFn());
1460
- });
1461
- return valueSignal;
1462
- };
1463
- const memoizeSignal = (factory) => {
1464
- let cached = null;
1465
- return () => {
1466
- if (!cached)
1467
- cached = factory();
1468
- return cached;
1469
- };
1470
- };
1471
-
1472
- /** Inject a signal containing a boolean value indicating if the viewport is xs */
1473
- const injectIsXs = memoizeSignal(() => injectObserveBreakpoint({ max: 'xs' }));
1474
- /** Inject a signal containing a boolean value indicating if the viewport is sm */
1475
- const injectIsSm = memoizeSignal(() => injectObserveBreakpoint({ min: 'sm', max: 'sm' }));
1476
- /** Inject a signal containing a boolean value indicating if the viewport is md */
1477
- const injectIsMd = memoizeSignal(() => injectObserveBreakpoint({ min: 'md', max: 'md' }));
1478
- /** Inject a signal containing a boolean value indicating if the viewport is lg */
1479
- const injectIsLg = memoizeSignal(() => injectObserveBreakpoint({ min: 'lg', max: 'lg' }));
1480
- /** Inject a signal containing a boolean value indicating if the viewport is xl */
1481
- const injectIsXl = memoizeSignal(() => injectObserveBreakpoint({ min: 'xl', max: 'xl' }));
1482
- /** Inject a signal containing a boolean value indicating if the viewport is 2xl */
1483
- const injectIs2Xl = memoizeSignal(() => injectObserveBreakpoint({ min: '2xl' }));
1484
- /**
1485
- * Inject a boolean value indicating if the viewport is matching the provided options.
1486
- * This value is not reactive. If you want to react to changes, use the {@link injectObserveBreakpoint} function instead.
1487
- */
1488
- const injectBreakpointIsMatched = (options) => injectBreakpointObserver().isBreakpointMatched(options);
1489
- /**
1490
- * Inject a boolean value indicating if the media query is matched.
1491
- * This value is not reactive. If you want to react to changes, use the {@link injectObserveMediaQuery} function instead.
1492
- */
1493
- const injectMediaQueryIsMatched = (mediaQuery) => injectBreakpointObserver().isMediaQueryMatched(mediaQuery);
1494
- /**
1495
- * Inject a signal containing a boolean value indicating if the viewport is matching the provided options.
1496
- */
1497
- const injectObserveBreakpoint = (options) => injectBreakpointObserver().observeBreakpoint(options);
1498
- /**
1499
- * Inject a signal containing a boolean value indicating if the media query is matched.
1500
- */
1501
- const injectObserveMediaQuery = (mediaQuery) => injectBreakpointObserver().observeMediaQuery(mediaQuery);
1502
- /** Inject a signal containing the current breakpoint. */
1503
- const injectCurrentBreakpoint = memoizeSignal(() => {
1504
- const isXs = injectIsXs();
1505
- const isSm = injectIsSm();
1506
- const isMd = injectIsMd();
1507
- const isLg = injectIsLg();
1508
- const isXl = injectIsXl();
1509
- const is2Xl = injectIs2Xl();
1510
- return computed(() => {
1511
- switch (true) {
1512
- case is2Xl():
1513
- return '2xl';
1514
- case isXl():
1515
- return 'xl';
1516
- case isLg():
1517
- return 'lg';
1518
- case isMd():
1519
- return 'md';
1520
- case isSm():
1521
- return 'sm';
1522
- case isXs():
1523
- default:
1524
- return 'xs';
1525
- }
1526
- });
1527
- });
1528
- /** Inject a signal that indicates if the user is using a portrait display */
1529
- const injectIsPortrait = memoizeSignal(() => injectObserveMediaQuery('(orientation: portrait)'));
1530
- /** Inject a signal that indicates if the user is using a landscape display */
1531
- const injectIsLandscape = memoizeSignal(() => injectObserveMediaQuery('(orientation: landscape)'));
1532
- /** Inject a signal containing the current display orientation */
1533
- const injectDisplayOrientation = memoizeSignal(() => {
1534
- const isPortrait = injectIsPortrait();
1535
- return computed(() => {
1536
- if (isPortrait())
1537
- return 'portrait';
1538
- return 'landscape';
1539
- });
1540
- });
1541
- /** Inject a signal that indicates if the device has a touch input */
1542
- const injectHasTouchInput = memoizeSignal(() => injectObserveMediaQuery('(pointer: coarse)'));
1543
- /** Inject a signal that indicates if the device has a fine input (mouse or stylus) */
1544
- const injectHasPrecisionInput = memoizeSignal(() => injectObserveMediaQuery('(pointer: fine)'));
1545
- /** Inject a signal containing the current device input type */
1546
- const injectDeviceInputType = memoizeSignal(() => {
1547
- const isTouch = injectHasTouchInput();
1548
- return computed(() => {
1549
- if (isTouch())
1550
- return 'touch';
1551
- return 'mouse';
1552
- });
1553
- });
1554
- /** Inject a signal containing a boolean value indicating if the user can hover (eg. using a mouse) */
1555
- const injectCanHover = memoizeSignal(() => injectObserveMediaQuery('(hover: hover)'));
1556
- /** Inject a signal containing the viewport dimensions */
1557
- const injectViewportDimensions = memoizeSignal(() => signalElementDimensions(createDocumentElementSignal()));
1558
- /** Inject a signal containing the scrollbar dimensions. Dimensions will be 0 if scrollbars overlap the page contents (like on mobile). */
1559
- const injectScrollbarDimensions = memoizeSignal(() => {
1560
- const document = inject(DOCUMENT);
1561
- const renderer = injectRenderer();
1562
- const scrollbarRuler = renderer.createElement('div');
1563
- scrollbarRuler.style.width = '100px';
1564
- scrollbarRuler.style.height = '100px';
1565
- scrollbarRuler.style.overflow = 'scroll';
1566
- scrollbarRuler.style.position = 'absolute';
1567
- scrollbarRuler.style.top = '-9999px';
1568
- renderer.appendChild(document.body, scrollbarRuler);
1569
- const scrollContainerDimensions = signalElementDimensions(scrollbarRuler);
1570
- return scrollContainerDimensions;
1571
- });
2056
+ return computed(() => {
2057
+ const element = observedEl().currentElement;
2058
+ const dimensions = elementDimensions();
2059
+ // We are not interested what the mutation is, just that there is one.
2060
+ // Changes to the DOM can affect the scroll state of the element.
2061
+ elementMutations();
2062
+ if (!element || !isRendered())
2063
+ return notScrollable(dimensions);
2064
+ const { scrollWidth, scrollHeight, clientHeight, clientWidth } = element;
2065
+ const canScrollHorizontally = scrollWidth > clientWidth;
2066
+ const canScrollVertically = scrollHeight > clientHeight;
2067
+ return {
2068
+ canScroll: canScrollHorizontally || canScrollVertically,
2069
+ canScrollHorizontally,
2070
+ canScrollVertically,
2071
+ elementDimensions: dimensions,
2072
+ };
2073
+ }, { equal: (a, b) => areScrollStatesEqual(a, b) });
2074
+ };
2075
+ const signalHostElementScrollState = () => signalElementScrollState(inject(ElementRef));
1572
2076
 
1573
2077
  let hasWrittenScrollbarSizes = false;
1574
2078
  /**
@@ -1588,7 +2092,7 @@ const writeScrollbarSizeToCssVariables = () => {
1588
2092
  const renderer = injectRenderer();
1589
2093
  const scrollbarDimensions = injectScrollbarDimensions();
1590
2094
  effect(() => {
1591
- const dimensions = scrollbarDimensions().rect?.();
2095
+ const dimensions = scrollbarDimensions();
1592
2096
  if (!dimensions)
1593
2097
  return;
1594
2098
  renderer.setCssProperties(document.documentElement, {
@@ -1638,11 +2142,11 @@ const useCursorDragScroll = (el, options) => {
1638
2142
  const { enabled = signal(true), allowedDirection = 'both' } = options ?? {};
1639
2143
  const scrollState = signalElementScrollState(elements);
1640
2144
  const renderer = injectRenderer();
1641
- const isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
1642
- const isInitDragging = signal(false, ...(ngDevMode ? [{ debugName: "isInitDragging" }] : []));
1643
- const initialDragPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "initialDragPosition" }] : []));
1644
- const initialScrollPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "initialScrollPosition" }] : []));
1645
- const dragAmount = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "dragAmount" }] : []));
2145
+ const isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
2146
+ const isInitDragging = signal(false, ...(ngDevMode ? [{ debugName: "isInitDragging" }] : /* istanbul ignore next */ []));
2147
+ const initialDragPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "initialDragPosition" }] : /* istanbul ignore next */ []));
2148
+ const initialScrollPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "initialScrollPosition" }] : /* istanbul ignore next */ []));
2149
+ const dragAmount = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "dragAmount" }] : /* istanbul ignore next */ []));
1646
2150
  const document = inject(DOCUMENT);
1647
2151
  const canScroll = computed(() => {
1648
2152
  const currentScrollState = scrollState();
@@ -1655,7 +2159,7 @@ const useCursorDragScroll = (el, options) => {
1655
2159
  case 'vertical':
1656
2160
  return currentScrollState.canScrollVertically;
1657
2161
  }
1658
- }, ...(ngDevMode ? [{ debugName: "canScroll" }] : []));
2162
+ }, ...(ngDevMode ? [{ debugName: "canScroll" }] : /* istanbul ignore next */ []));
1659
2163
  // Cleanup if the element the cursor drag scroll is bound to gets changed
1660
2164
  effect(() => {
1661
2165
  const { previousElement } = element();
@@ -1871,7 +2375,7 @@ const createRouterState = (router) => {
1871
2375
  const injectRouterState = memoizeSignal(() => {
1872
2376
  const event = injectRouterEvent();
1873
2377
  const router = inject(Router);
1874
- const routerState = signal(createRouterState(router), ...(ngDevMode ? [{ debugName: "routerState" }] : []));
2378
+ const routerState = signal(createRouterState(router), ...(ngDevMode ? [{ debugName: "routerState" }] : /* istanbul ignore next */ []));
1875
2379
  effect(() => {
1876
2380
  const e = event();
1877
2381
  untracked(() => {
@@ -1888,31 +2392,31 @@ const injectRouterState = memoizeSignal(() => {
1888
2392
  /** Inject a signal containing the current route fragment (the part after the # inside the url if present) */
1889
2393
  const injectFragment = (config) => {
1890
2394
  const routerState = injectRouterState();
1891
- const fragment = computed(() => routerState().fragment, ...(ngDevMode ? [{ debugName: "fragment" }] : []));
2395
+ const fragment = computed(() => routerState().fragment, ...(ngDevMode ? [{ debugName: "fragment" }] : /* istanbul ignore next */ []));
1892
2396
  return transformOrReturn(fragment, config);
1893
2397
  };
1894
2398
  /** Inject all currently available query parameters as a signal */
1895
2399
  const injectQueryParams = () => {
1896
2400
  const routerState = injectRouterState();
1897
- const queryParams = computed(() => routerState().queryParams, ...(ngDevMode ? [{ debugName: "queryParams" }] : []));
2401
+ const queryParams = computed(() => routerState().queryParams, ...(ngDevMode ? [{ debugName: "queryParams" }] : /* istanbul ignore next */ []));
1898
2402
  return queryParams;
1899
2403
  };
1900
2404
  /** Inject all currently available route data as a signal */
1901
2405
  const injectRouteData = () => {
1902
2406
  const routerState = injectRouterState();
1903
- const data = computed(() => routerState().data, ...(ngDevMode ? [{ debugName: "data" }] : []));
2407
+ const data = computed(() => routerState().data, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
1904
2408
  return data;
1905
2409
  };
1906
2410
  /** Inject the current route title as a signal */
1907
2411
  const injectRouteTitle = (config) => {
1908
2412
  const routerState = injectRouterState();
1909
- const title = computed(() => routerState().title, ...(ngDevMode ? [{ debugName: "title" }] : []));
2413
+ const title = computed(() => routerState().title, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
1910
2414
  return transformOrReturn(title, config);
1911
2415
  };
1912
2416
  /** Inject all currently available path parameters as a signal */
1913
2417
  const injectPathParams = () => {
1914
2418
  const routerState = injectRouterState();
1915
- const pathParams = computed(() => routerState().pathParams, ...(ngDevMode ? [{ debugName: "pathParams" }] : []));
2419
+ const pathParams = computed(() => routerState().pathParams, ...(ngDevMode ? [{ debugName: "pathParams" }] : /* istanbul ignore next */ []));
1916
2420
  return pathParams;
1917
2421
  };
1918
2422
  const getQueryParamFromUrl = (key) => {
@@ -2099,10 +2603,9 @@ const getObjectProperty = (obj, prop) => {
2099
2603
 
2100
2604
  const RUNTIME_ERROR_NO_DATA = '__ET_NO_DATA__';
2101
2605
  class RuntimeError extends Error {
2102
- constructor(code, message, devOnly = false, data = RUNTIME_ERROR_NO_DATA) {
2103
- super(formatRuntimeError(code, message, devOnly));
2606
+ constructor(code, message, data = RUNTIME_ERROR_NO_DATA) {
2607
+ super(formatRuntimeError(code, message));
2104
2608
  this.code = code;
2105
- this.devOnly = devOnly;
2106
2609
  this.data = data;
2107
2610
  if (data !== RUNTIME_ERROR_NO_DATA) {
2108
2611
  try {
@@ -2119,295 +2622,150 @@ class RuntimeError extends Error {
2119
2622
  }
2120
2623
  }
2121
2624
  }
2122
- function formatRuntimeError(code, message, devOnly) {
2625
+ function formatRuntimeError(code, message) {
2123
2626
  // prefix code with zeros if it's less than 100
2124
2627
  const codeWithZeros = code < 10 ? `00${code}` : code < 100 ? `0${code}` : code;
2125
2628
  const fullCode = `ET${codeWithZeros}`;
2126
- const devOnlyText = devOnly ? ' [DEV ONLY] ' : '';
2127
- return `${devOnlyText}${fullCode}${message ? ': ' + message : ''}`;
2629
+ return `${fullCode}${message ? ': ' + message : ''}`;
2128
2630
  }
2129
2631
 
2130
- /**
2131
- * Checks if an element or the viewport can scroll in a given direction.
2132
- * @param element The element to check. If null/undefined, checks if the viewport can scroll.
2133
- * @param direction The direction to check. If not provided, checks both directions.
2134
- * @returns true if the element or viewport can scroll in the given direction.
2135
- */
2136
- const elementCanScroll = (element, direction) => {
2137
- const el = element || document.documentElement;
2138
- const { scrollHeight, clientHeight, scrollWidth, clientWidth } = el;
2139
- if (direction === 'x') {
2140
- return scrollWidth > clientWidth;
2141
- }
2142
- else if (direction === 'y') {
2143
- return scrollHeight > clientHeight;
2632
+ const createAutoSessionMemoryKey = ({ element, prefix }) => {
2633
+ const pathSegments = [];
2634
+ let currentElement = element;
2635
+ while (currentElement) {
2636
+ const currentElementName = currentElement.localName;
2637
+ const parentElement = currentElement.parentElement;
2638
+ if (!parentElement) {
2639
+ pathSegments.unshift(currentElementName);
2640
+ break;
2641
+ }
2642
+ const siblingElements = Array.from(parentElement.children);
2643
+ const siblingIndex = siblingElements.indexOf(currentElement);
2644
+ pathSegments.unshift(`${currentElementName}[${siblingIndex}]`);
2645
+ currentElement = parentElement;
2144
2646
  }
2145
- return scrollHeight > clientHeight || scrollWidth > clientWidth;
2647
+ const locationPath = element.ownerDocument.defaultView?.location.pathname ?? 'root';
2648
+ return `${prefix}:${locationPath}:${pathSegments.join('/')}`;
2146
2649
  };
2147
- const createViewportRect = () => ({
2148
- left: 0,
2149
- top: 0,
2150
- right: window.innerWidth,
2151
- bottom: window.innerHeight,
2152
- width: window.innerWidth,
2153
- height: window.innerHeight,
2154
- x: 0,
2155
- y: 0,
2156
- toJSON: () => ({}),
2157
- });
2158
- const isElementVisible = (options) => {
2159
- const { container, element } = options;
2160
- if (!element) {
2161
- return null;
2650
+ const canUseSessionMemory = () => {
2651
+ try {
2652
+ if (typeof globalThis.window === 'undefined') {
2653
+ return false;
2654
+ }
2655
+ if (typeof globalThis.document === 'undefined') {
2656
+ return false;
2657
+ }
2658
+ return globalThis.sessionStorage != null;
2162
2659
  }
2163
- const elementRect = options.elementRect || element.getBoundingClientRect();
2164
- const containerRect = container ? options.containerRect || container.getBoundingClientRect() : createViewportRect();
2165
- const canScroll = elementCanScroll(container);
2166
- if (!canScroll) {
2167
- return {
2168
- inline: true,
2169
- block: true,
2170
- blockIntersection: 1,
2171
- inlineIntersection: 1,
2172
- intersectionRatio: 1,
2173
- isIntersecting: true,
2174
- element,
2175
- containerRect,
2176
- elementRect,
2177
- };
2660
+ catch {
2661
+ return false;
2178
2662
  }
2179
- const elLeft = elementRect.left;
2180
- const elTop = elementRect.top;
2181
- const elWidth = elementRect.width || 1;
2182
- const elHeight = elementRect.height || 1;
2183
- const elRight = elLeft + elWidth;
2184
- const elBottom = elTop + elHeight;
2185
- const conLeft = containerRect.left;
2186
- const conTop = containerRect.top;
2187
- const conRight = conLeft + containerRect.width;
2188
- const conBottom = conTop + containerRect.height;
2189
- const isElementInlineVisible = elLeft >= conLeft && elRight <= conRight;
2190
- const isElementBlockVisible = elTop >= conTop && elBottom <= conBottom;
2191
- const inlineIntersection = Math.min(elRight, conRight) - Math.max(elLeft, conLeft);
2192
- const blockIntersection = Math.min(elBottom, conBottom) - Math.max(elTop, conTop);
2193
- const inlineIntersectionPercentage = clamp(inlineIntersection / elWidth, 0, 1);
2194
- const blockIntersectionPercentage = clamp(blockIntersection / elHeight, 0, 1);
2195
- return {
2196
- inline: isElementInlineVisible,
2197
- block: isElementBlockVisible,
2198
- inlineIntersection: inlineIntersectionPercentage,
2199
- blockIntersection: blockIntersectionPercentage,
2200
- isIntersecting: isElementInlineVisible && isElementBlockVisible,
2201
- element,
2202
- containerRect,
2203
- elementRect,
2204
- // Round the intersection ratio to the nearest 0.01 to avoid floating point errors and system scaling issues.
2205
- intersectionRatio: Math.round(Math.min(inlineIntersectionPercentage, blockIntersectionPercentage) * 100) / 100,
2206
- };
2207
2663
  };
2208
- const getElementScrollCoordinates = (options) => {
2209
- const { container, element, direction, behavior = 'smooth', origin = 'nearest', scrollBlockMargin = 0, scrollInlineMargin = 0, } = options;
2210
- if (!element || !container || !elementCanScroll(container)) {
2211
- return {
2212
- behavior,
2213
- left: undefined,
2214
- top: undefined,
2215
- };
2664
+ const getSessionStorage = () => {
2665
+ if (!canUseSessionMemory()) {
2666
+ return null;
2216
2667
  }
2217
- const elementRect = element.getBoundingClientRect();
2218
- const containerRect = container.getBoundingClientRect();
2219
- const { scrollLeft, scrollTop } = container;
2220
- const elWidth = elementRect.width;
2221
- const elHeight = elementRect.height;
2222
- const elLeft = elementRect.left;
2223
- const elTop = elementRect.top;
2224
- const elRight = elementRect.right;
2225
- const elBottom = elementRect.bottom;
2226
- const conWidth = containerRect.width;
2227
- const conHeight = containerRect.height;
2228
- const conLeft = containerRect.left;
2229
- const conTop = containerRect.top;
2230
- const conRight = containerRect.right;
2231
- const conBottom = containerRect.bottom;
2232
- const shouldScrollLeft = direction === 'inline' || direction === 'both' || !direction;
2233
- const shouldScrollTop = direction === 'block' || direction === 'both' || !direction;
2234
- let scrollLeftTo = scrollLeft;
2235
- let scrollTopTo = scrollTop;
2236
- const relativeTop = elTop - conTop;
2237
- const relativeLeft = elLeft - conLeft;
2238
- const calculateScrollToStart = () => {
2239
- scrollLeftTo = scrollLeft + relativeLeft - scrollInlineMargin;
2240
- scrollTopTo = scrollTop + relativeTop - scrollBlockMargin;
2241
- };
2242
- const calculateScrollToEnd = () => {
2243
- scrollLeftTo = scrollLeft + relativeLeft - conWidth + elWidth + scrollInlineMargin;
2244
- scrollTopTo = scrollTop + relativeTop - conHeight + elHeight + scrollBlockMargin;
2245
- };
2246
- const calculateScrollToCenter = () => {
2247
- scrollLeftTo = scrollLeft + relativeLeft - conWidth / 2 + elWidth / 2;
2248
- scrollTopTo = scrollTop + relativeTop - conHeight / 2 + elHeight / 2;
2249
- };
2250
- const calculateScrollToNearest = () => {
2251
- const isAbove = elBottom < conTop;
2252
- const isPartialAbove = elTop < conTop && elBottom > conTop;
2253
- const isBelow = elTop > conBottom;
2254
- const isPartialBelow = elTop < conBottom && elBottom > conBottom;
2255
- const isLeft = elRight < conLeft;
2256
- const isPartialLeft = elLeft < conLeft && elRight > conLeft;
2257
- const isRight = elLeft > conRight;
2258
- const isPartialRight = elLeft < conRight && elRight > conRight;
2259
- if (isAbove || isPartialAbove || isLeft || isPartialLeft) {
2260
- calculateScrollToStart();
2668
+ return globalThis.sessionStorage;
2669
+ };
2670
+ const createSessionMemory = ({ key, parse, serialize }) => {
2671
+ const read = () => {
2672
+ const sessionStorage = getSessionStorage();
2673
+ if (!sessionStorage) {
2674
+ return null;
2261
2675
  }
2262
- else if (isBelow || isPartialBelow || isRight || isPartialRight) {
2263
- calculateScrollToEnd();
2676
+ try {
2677
+ const storedValue = sessionStorage.getItem(key);
2678
+ if (storedValue === null) {
2679
+ return null;
2680
+ }
2681
+ return parse(storedValue);
2264
2682
  }
2265
- };
2266
- switch (origin) {
2267
- case 'start':
2268
- calculateScrollToStart();
2269
- break;
2270
- case 'end':
2271
- calculateScrollToEnd();
2272
- break;
2273
- case 'center':
2274
- calculateScrollToCenter();
2275
- break;
2276
- case 'nearest':
2277
- calculateScrollToNearest();
2278
- break;
2279
- }
2280
- return {
2281
- behavior,
2282
- left: shouldScrollLeft ? scrollLeftTo : undefined,
2283
- top: shouldScrollTop ? scrollTopTo : undefined,
2284
- };
2285
- };
2286
- const scrollToElement = (options) => {
2287
- options.container?.scrollTo(getElementScrollCoordinates(options));
2288
- };
2289
-
2290
- const [, injectAngularRootElement] = createRootProvider(() => {
2291
- const appRef = inject(ApplicationRef);
2292
- const rootElement = signal(null, ...(ngDevMode ? [{ debugName: "rootElement" }] : []));
2293
- setTimeout(() => {
2294
- const appComponents = appRef.components;
2295
- if (appComponents.length > 0) {
2296
- rootElement.set(appComponents[0]?.location.nativeElement);
2683
+ catch {
2684
+ return null;
2297
2685
  }
2298
- });
2299
- return rootElement;
2300
- });
2301
-
2302
- const [provideBoundaryElement, injectBoundaryElement, BOUNDARY_ELEMENT_TOKEN] = createProvider(() => {
2303
- const hostElement = inject(ElementRef, { optional: true });
2304
- const document = inject(DOCUMENT);
2305
- const override = signal(null, ...(ngDevMode ? [{ debugName: "override" }] : []));
2306
- const value = computed(() => override() ?? hostElement?.nativeElement ?? document.documentElement, ...(ngDevMode ? [{ debugName: "value" }] : []));
2307
- return {
2308
- value,
2309
- override,
2310
- };
2311
- }, { name: 'Boundary Element' });
2312
-
2313
- /**
2314
- * Default viewport config based on Tailwind CSS.
2315
- * @see https://tailwindcss.com/docs/screens
2316
- */
2317
- const DEFAULT_VIEWPORT_CONFIG = {
2318
- breakpoints: {
2319
- xs: [0, 639],
2320
- sm: [640, 767],
2321
- md: [768, 1023],
2322
- lg: [1024, 1279],
2323
- xl: [1280, 1535],
2324
- '2xl': [1536, Infinity],
2325
- },
2326
- };
2327
- const [provideViewportConfig, injectViewportConfig] = createStaticRootProvider(DEFAULT_VIEWPORT_CONFIG, {
2328
- name: 'Viewport Config',
2329
- });
2330
- const [provideBreakpointObserver, injectBreakpointObserver] = createRootProvider(() => {
2331
- const breakpointObserver = inject(BreakpointObserver);
2332
- const viewportConfig = injectViewportConfig();
2333
- const isMediaQueryMatched = (mediaQuery) => breakpointObserver.isMatched(mediaQuery);
2334
- const observeMediaQuery = (mediaQuery) => {
2335
- return toSignal(breakpointObserver.observe(mediaQuery).pipe(map((x) => x.matches), startWith(isMediaQueryMatched(mediaQuery))), { requireSync: true });
2336
2686
  };
2337
- const observeBreakpoint = (options) => observeMediaQuery(buildMediaQueryString(options));
2338
- const isBreakpointMatched = (options) => isMediaQueryMatched(buildMediaQueryString(options));
2339
- const getBreakpointSize = (type, option) => {
2340
- const index = option === 'min' ? 0 : 1;
2341
- const size = viewportConfig.breakpoints[type][index];
2342
- if (size === Infinity || size === 0) {
2343
- return size;
2687
+ const write = (value) => {
2688
+ const sessionStorage = getSessionStorage();
2689
+ if (!sessionStorage) {
2690
+ return false;
2344
2691
  }
2345
- if (option === 'min') {
2346
- return size;
2692
+ try {
2693
+ sessionStorage.setItem(key, serialize(value));
2694
+ return true;
2695
+ }
2696
+ catch {
2697
+ return false;
2347
2698
  }
2348
- // Due to scaling, the actual size of the viewport may be a decimal number.
2349
- // Eg. on Windows 11 with 150% scaling, the viewport size may be 1535.33px
2350
- // and thus not matching any of the default breakpoints.
2351
- return size + 0.9;
2352
2699
  };
2353
- const buildMediaQueryString = (options) => {
2354
- if (!options.min && !options.max) {
2355
- throw new Error('At least one of min or max must be defined');
2700
+ const remove = () => {
2701
+ const sessionStorage = getSessionStorage();
2702
+ if (!sessionStorage) {
2703
+ return false;
2356
2704
  }
2357
- const mediaQueryParts = [];
2358
- if (options.min) {
2359
- if (typeof options.min === 'number') {
2360
- mediaQueryParts.push(`(min-width: ${options.min}px)`);
2361
- }
2362
- else {
2363
- mediaQueryParts.push(`(min-width: ${getBreakpointSize(options.min, 'min')}px)`);
2364
- }
2705
+ try {
2706
+ sessionStorage.removeItem(key);
2707
+ return true;
2365
2708
  }
2366
- if (options.min && options.max) {
2367
- mediaQueryParts.push('and');
2709
+ catch {
2710
+ return false;
2368
2711
  }
2369
- if (options.max) {
2370
- if (typeof options.max === 'number') {
2371
- mediaQueryParts.push(`(max-width: ${options.max}px)`);
2372
- }
2373
- else {
2374
- mediaQueryParts.push(`(max-width: ${getBreakpointSize(options.max, 'max')}px)`);
2375
- }
2712
+ };
2713
+ return {
2714
+ read,
2715
+ write,
2716
+ remove,
2717
+ };
2718
+ };
2719
+
2720
+ const [, injectAngularRootElement] = createRootProvider(() => {
2721
+ const appRef = inject(ApplicationRef);
2722
+ const rootElement = signal(null, ...(ngDevMode ? [{ debugName: "rootElement" }] : /* istanbul ignore next */ []));
2723
+ const poll = () => {
2724
+ const appComponents = appRef.components;
2725
+ if (appComponents.length > 0) {
2726
+ rootElement.set(appComponents[0]?.location.nativeElement);
2727
+ }
2728
+ else {
2729
+ setTimeout(poll, 25);
2376
2730
  }
2377
- return mediaQueryParts.join(' ');
2378
2731
  };
2732
+ setTimeout(poll);
2733
+ return rootElement;
2734
+ });
2735
+
2736
+ const [provideBoundaryElement, injectBoundaryElement, BOUNDARY_ELEMENT_TOKEN] = createProvider(() => {
2737
+ const hostElement = inject(ElementRef, { optional: true });
2738
+ const document = inject(DOCUMENT);
2739
+ const override = signal(null, ...(ngDevMode ? [{ debugName: "override" }] : /* istanbul ignore next */ []));
2740
+ const value = computed(() => override() ?? hostElement?.nativeElement ?? document.documentElement, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2379
2741
  return {
2380
- observeBreakpoint,
2381
- isBreakpointMatched,
2382
- getBreakpointSize,
2383
- buildMediaQueryString,
2384
- observeMediaQuery,
2385
- isMediaQueryMatched,
2742
+ value,
2743
+ override,
2386
2744
  };
2387
- }, { name: 'Breakpoint Observer' });
2745
+ }, { name: 'Boundary Element' });
2388
2746
 
2389
2747
  const [provideFocusVisibleTracker, injectFocusVisibleTracker, FOCUS_VISIBLE_TRACKER_TOKEN] = createRootProvider(() => {
2390
2748
  const document = inject(DOCUMENT);
2391
2749
  const destroyRef = inject(DestroyRef);
2392
- const isFocusVisible = signal(false, ...(ngDevMode ? [{ debugName: "isFocusVisible" }] : []));
2750
+ const isFocusVisible = signal(false, ...(ngDevMode ? [{ debugName: "isFocusVisible" }] : /* istanbul ignore next */ []));
2393
2751
  let hadKeyboardEvent = false;
2394
2752
  const onKeyDown = (e) => {
2395
2753
  if (e.key === 'Tab' || e.key === 'Shift' || e.key === 'Meta' || e.key === 'Alt' || e.key === 'Control') {
2396
2754
  hadKeyboardEvent = true;
2397
- isFocusVisible.set(true);
2755
+ queueMicrotask(() => isFocusVisible.set(true));
2398
2756
  }
2399
2757
  };
2400
2758
  const onPointerDown = () => {
2401
2759
  hadKeyboardEvent = false;
2402
- isFocusVisible.set(false);
2760
+ queueMicrotask(() => isFocusVisible.set(false));
2403
2761
  };
2404
2762
  const onFocus = () => {
2405
2763
  if (hadKeyboardEvent) {
2406
- isFocusVisible.set(true);
2764
+ queueMicrotask(() => isFocusVisible.set(true));
2407
2765
  }
2408
2766
  };
2409
2767
  const onBlur = () => {
2410
- isFocusVisible.set(false);
2768
+ queueMicrotask(() => isFocusVisible.set(false));
2411
2769
  };
2412
2770
  document.addEventListener('keydown', onKeyDown, true);
2413
2771
  document.addEventListener('mousedown', onPointerDown, true);
@@ -2429,7 +2787,7 @@ const [provideFocusVisibleTracker, injectFocusVisibleTracker, FOCUS_VISIBLE_TRAC
2429
2787
  }, { name: 'Focus Visible Tracker' });
2430
2788
 
2431
2789
  const [provideLocale, injectLocale] = createRootProvider(() => {
2432
- const currentLocale = signal('en', ...(ngDevMode ? [{ debugName: "currentLocale" }] : []));
2790
+ const currentLocale = signal('en', ...(ngDevMode ? [{ debugName: "currentLocale" }] : /* istanbul ignore next */ []));
2433
2791
  return {
2434
2792
  currentLocale,
2435
2793
  };
@@ -2571,6 +2929,20 @@ const [provideRenderer, injectRenderer] = createRootProvider(() => {
2571
2929
  setAttribute(element, `data-${key}`, value);
2572
2930
  });
2573
2931
  };
2932
+ const moveBefore = (config) => {
2933
+ const { newParent, child, before = null } = config;
2934
+ if ('moveBefore' in newParent) {
2935
+ try {
2936
+ newParent.moveBefore(child, before);
2937
+ }
2938
+ catch {
2939
+ newParent.insertBefore(child, before);
2940
+ }
2941
+ }
2942
+ else {
2943
+ newParent.insertBefore(child, before);
2944
+ }
2945
+ };
2574
2946
  return {
2575
2947
  addClass,
2576
2948
  removeClass,
@@ -2602,10 +2974,80 @@ const [provideRenderer, injectRenderer] = createRootProvider(() => {
2602
2974
  setDataAttributes,
2603
2975
  setCssProperty,
2604
2976
  setCssProperties,
2977
+ moveBefore,
2605
2978
  renderer,
2606
2979
  };
2607
2980
  }, { name: 'Angular Renderer' });
2608
2981
 
2982
+ const [provideStyleManager, injectStyleManager] = createRootProvider(() => {
2983
+ const appRef = inject(ApplicationRef);
2984
+ const destroyRef = inject(DestroyRef);
2985
+ const document = inject(DOCUMENT);
2986
+ const envInjector = inject(EnvironmentInjector);
2987
+ const renderer = injectRenderer();
2988
+ let container = null;
2989
+ const mountedComponents = new Map();
2990
+ const getContainerParent = () => {
2991
+ return document.body ?? document.documentElement;
2992
+ };
2993
+ const ensureContainer = () => {
2994
+ if (container) {
2995
+ return container;
2996
+ }
2997
+ const nextContainer = renderer.createElement('div');
2998
+ renderer.addClass(nextContainer, 'et-style-manager');
2999
+ renderer.setAttribute(nextContainer, 'aria-hidden', 'true');
3000
+ renderer.setStyle(nextContainer, { display: 'none' });
3001
+ renderer.appendChild(getContainerParent(), nextContainer);
3002
+ container = nextContainer;
3003
+ return nextContainer;
3004
+ };
3005
+ const cleanupContainer = () => {
3006
+ if (!container) {
3007
+ return;
3008
+ }
3009
+ const parent = renderer.parentNode(container);
3010
+ if (parent) {
3011
+ renderer.removeChild(parent, container);
3012
+ }
3013
+ container = null;
3014
+ };
3015
+ const mount = (component) => {
3016
+ const existingComponent = mountedComponents.get(component);
3017
+ if (existingComponent) {
3018
+ return existingComponent;
3019
+ }
3020
+ const componentRef = createComponent(component, { environmentInjector: envInjector });
3021
+ appRef.attachView(componentRef.hostView);
3022
+ renderer.appendChild(ensureContainer(), componentRef.location.nativeElement);
3023
+ mountedComponents.set(component, componentRef);
3024
+ return componentRef;
3025
+ };
3026
+ destroyRef.onDestroy(() => {
3027
+ if (appRef.destroyed) {
3028
+ mountedComponents.clear();
3029
+ cleanupContainer();
3030
+ return;
3031
+ }
3032
+ mountedComponents.forEach((componentRef) => {
3033
+ appRef.detachView(componentRef.hostView);
3034
+ componentRef.destroy();
3035
+ });
3036
+ mountedComponents.clear();
3037
+ cleanupContainer();
3038
+ });
3039
+ return { mount };
3040
+ }, { name: 'StyleManager' });
3041
+
3042
+ const createUserConsentProvider = (options) => ({
3043
+ provide: options.for,
3044
+ useFactory: () => ({
3045
+ isGranted: options.isGranted(),
3046
+ grant: options.grant(),
3047
+ ...(options.revoke ? { revoke: options.revoke() } : {}),
3048
+ }),
3049
+ });
3050
+
2609
3051
  const nextFrame = (cb) => {
2610
3052
  requestAnimationFrame(() => {
2611
3053
  requestAnimationFrame(cb);
@@ -2651,7 +3093,7 @@ class AnimatedLifecycleDirective {
2651
3093
  this.currentFrameId = 0;
2652
3094
  this.state$ = new BehaviorSubject('init');
2653
3095
  this.stateChange = outputFromObservable(this.state$);
2654
- this.skipNextEnter = model(false, ...(ngDevMode ? [{ debugName: "skipNextEnter" }] : []));
3096
+ this.skipNextEnter = model(false, ...(ngDevMode ? [{ debugName: "skipNextEnter" }] : /* istanbul ignore next */ []));
2655
3097
  this.state$
2656
3098
  .pipe(tap((state) => {
2657
3099
  if (state !== 'init') {
@@ -2838,7 +3280,7 @@ class AnimatedLifecycleDirective {
2838
3280
  const { removeClasses, addClasses, expectedState, transitionId, onComplete, cancelSignal } = config;
2839
3281
  this.removeClasses(...removeClasses);
2840
3282
  addClasses.forEach((cls) => this.addClass(cls));
2841
- timer(0)
3283
+ fromNextFrame()
2842
3284
  .pipe(switchMap(() => this.animatable.isAnimating$), take(1), switchMap((isAnimating) => {
2843
3285
  if (!isAnimating && this.state$.value === expectedState) {
2844
3286
  return of({ cancelled: false, transitionId });
@@ -2869,15 +3311,15 @@ class AnimatedLifecycleDirective {
2869
3311
  updateState(newState) {
2870
3312
  this.state$.next(newState);
2871
3313
  }
2872
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedLifecycleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2873
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: AnimatedLifecycleDirective, isStandalone: true, selector: "[etAnimatedLifecycle]", inputs: { skipNextEnter: { classPropertyName: "skipNextEnter", publicName: "skipNextEnter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stateChange: "stateChange", skipNextEnter: "skipNextEnterChange" }, host: { classAttribute: "et-force-invisible" }, providers: [
3314
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedLifecycleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3315
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: AnimatedLifecycleDirective, isStandalone: true, selector: "[etAnimatedLifecycle]", inputs: { skipNextEnter: { classPropertyName: "skipNextEnter", publicName: "skipNextEnter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stateChange: "stateChange", skipNextEnter: "skipNextEnterChange" }, host: { classAttribute: "et-force-invisible" }, providers: [
2874
3316
  {
2875
3317
  provide: ANIMATED_LIFECYCLE_TOKEN,
2876
3318
  useExisting: AnimatedLifecycleDirective,
2877
3319
  },
2878
3320
  ], exportAs: ["etAnimatedLifecycle"], hostDirectives: [{ directive: AnimatableDirective }], ngImport: i0 }); }
2879
3321
  }
2880
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedLifecycleDirective, decorators: [{
3322
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedLifecycleDirective, decorators: [{
2881
3323
  type: Directive,
2882
3324
  args: [{
2883
3325
  selector: '[etAnimatedLifecycle]',
@@ -2902,7 +3344,7 @@ class AnimatedIfDirective {
2902
3344
  this.viewContainerRef = inject(ViewContainerRef);
2903
3345
  this.animatedLifecycle = inject(ANIMATED_LIFECYCLE_TOKEN);
2904
3346
  this.hasView = false;
2905
- this.ifValue = input(null, { ...(ngDevMode ? { debugName: "ifValue" } : {}), alias: 'etAnimatedIf' });
3347
+ this.ifValue = input(null, { ...(ngDevMode ? { debugName: "ifValue" } : /* istanbul ignore next */ {}), alias: 'etAnimatedIf' });
2906
3348
  toObservable(this.ifValue)
2907
3349
  .pipe(switchMap((value) => {
2908
3350
  if (value) {
@@ -2924,15 +3366,15 @@ class AnimatedIfDirective {
2924
3366
  }), takeUntilDestroyed())
2925
3367
  .subscribe();
2926
3368
  }
2927
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedIfDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2928
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: AnimatedIfDirective, isStandalone: true, selector: "[etAnimatedIf]", inputs: { ifValue: { classPropertyName: "ifValue", publicName: "etAnimatedIf", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3369
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedIfDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3370
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: AnimatedIfDirective, isStandalone: true, selector: "[etAnimatedIf]", inputs: { ifValue: { classPropertyName: "ifValue", publicName: "etAnimatedIf", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
2929
3371
  {
2930
3372
  provide: ANIMATED_IF_TOKEN,
2931
3373
  useExisting: AnimatedIfDirective,
2932
3374
  },
2933
3375
  ], ngImport: i0 }); }
2934
3376
  }
2935
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedIfDirective, decorators: [{
3377
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedIfDirective, decorators: [{
2936
3378
  type: Directive,
2937
3379
  args: [{
2938
3380
  selector: '[etAnimatedIf]',
@@ -2956,17 +3398,17 @@ class AnimatedOverlayDirective {
2956
3398
  this.destroyRef = inject(DestroyRef);
2957
3399
  this.floatingElCleanupFn = null;
2958
3400
  this.unmountSubscription = null;
2959
- this.placement = input('bottom', ...(ngDevMode ? [{ debugName: "placement" }] : []));
2960
- this.fallbackPlacements = input(...(ngDevMode ? [undefined, { debugName: "fallbackPlacements" }] : []));
2961
- this.offset = input(null, ...(ngDevMode ? [{ debugName: "offset" }] : []));
2962
- this.arrowPadding = input(4, ...(ngDevMode ? [{ debugName: "arrowPadding" }] : []));
2963
- this.viewportPadding = input(8, ...(ngDevMode ? [{ debugName: "viewportPadding" }] : []));
2964
- this.autoResize = input(false, { ...(ngDevMode ? { debugName: "autoResize" } : {}), transform: booleanAttribute });
2965
- this.shift = input(true, { ...(ngDevMode ? { debugName: "shift" } : {}), transform: booleanAttribute });
2966
- this.autoHide = input(false, { ...(ngDevMode ? { debugName: "autoHide" } : {}), transform: booleanAttribute });
2967
- this.autoCloseIfReferenceHidden = input(false, { ...(ngDevMode ? { debugName: "autoCloseIfReferenceHidden" } : {}), transform: booleanAttribute });
2968
- this.referenceElement = input(this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "referenceElement" }] : []));
2969
- this.mirrorWidth = input(false, { ...(ngDevMode ? { debugName: "mirrorWidth" } : {}), transform: booleanAttribute });
3401
+ this.placement = input('bottom', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
3402
+ this.fallbackPlacements = input(...(ngDevMode ? [undefined, { debugName: "fallbackPlacements" }] : /* istanbul ignore next */ []));
3403
+ this.offset = input(null, ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
3404
+ this.arrowPadding = input(4, ...(ngDevMode ? [{ debugName: "arrowPadding" }] : /* istanbul ignore next */ []));
3405
+ this.viewportPadding = input(8, ...(ngDevMode ? [{ debugName: "viewportPadding" }] : /* istanbul ignore next */ []));
3406
+ this.autoResize = input(false, { ...(ngDevMode ? { debugName: "autoResize" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3407
+ this.shift = input(true, { ...(ngDevMode ? { debugName: "shift" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3408
+ this.autoHide = input(false, { ...(ngDevMode ? { debugName: "autoHide" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3409
+ this.autoCloseIfReferenceHidden = input(false, { ...(ngDevMode ? { debugName: "autoCloseIfReferenceHidden" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3410
+ this.referenceElement = input(this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "referenceElement" }] : /* istanbul ignore next */ []));
3411
+ this.mirrorWidth = input(false, { ...(ngDevMode ? { debugName: "mirrorWidth" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2970
3412
  this.portal = null;
2971
3413
  this.overlayRef = null;
2972
3414
  this.componentRef = null;
@@ -2974,14 +3416,14 @@ class AnimatedOverlayDirective {
2974
3416
  this.afterOpened$ = new Subject();
2975
3417
  this.beforeClosed$ = new Subject();
2976
3418
  this.afterClosed$ = new Subject();
2977
- this.state = signal('init', ...(ngDevMode ? [{ debugName: "state" }] : []));
2978
- this.isMounted = computed(() => this.state() === 'mounted', ...(ngDevMode ? [{ debugName: "isMounted" }] : []));
2979
- this.isMounting = computed(() => this.state() === 'mounting', ...(ngDevMode ? [{ debugName: "isMounting" }] : []));
2980
- this.isUnmounted = computed(() => this.state() === 'unmounted', ...(ngDevMode ? [{ debugName: "isUnmounted" }] : []));
2981
- this.isUnmounting = computed(() => this.state() === 'unmounting', ...(ngDevMode ? [{ debugName: "isUnmounting" }] : []));
2982
- this.canMount = computed(() => !this.isMounted() && !this.isMounting(), ...(ngDevMode ? [{ debugName: "canMount" }] : []));
2983
- this.canUnmount = computed(() => (this.isMounted() || this.isMounting()) && !this.isUnmounting(), ...(ngDevMode ? [{ debugName: "canUnmount" }] : []));
2984
- this.isHidden = signal(false, ...(ngDevMode ? [{ debugName: "isHidden" }] : []));
3419
+ this.state = signal('init', ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
3420
+ this.isMounted = computed(() => this.state() === 'mounted', ...(ngDevMode ? [{ debugName: "isMounted" }] : /* istanbul ignore next */ []));
3421
+ this.isMounting = computed(() => this.state() === 'mounting', ...(ngDevMode ? [{ debugName: "isMounting" }] : /* istanbul ignore next */ []));
3422
+ this.isUnmounted = computed(() => this.state() === 'unmounted', ...(ngDevMode ? [{ debugName: "isUnmounted" }] : /* istanbul ignore next */ []));
3423
+ this.isUnmounting = computed(() => this.state() === 'unmounting', ...(ngDevMode ? [{ debugName: "isUnmounting" }] : /* istanbul ignore next */ []));
3424
+ this.canMount = computed(() => !this.isMounted() && !this.isMounting(), ...(ngDevMode ? [{ debugName: "canMount" }] : /* istanbul ignore next */ []));
3425
+ this.canUnmount = computed(() => (this.isMounted() || this.isMounting()) && !this.isUnmounting(), ...(ngDevMode ? [{ debugName: "canUnmount" }] : /* istanbul ignore next */ []));
3426
+ this.isHidden = signal(false, ...(ngDevMode ? [{ debugName: "isHidden" }] : /* istanbul ignore next */ []));
2985
3427
  this.isMounted$ = toObservable(this.isMounted);
2986
3428
  this.isMounting$ = toObservable(this.isMounting);
2987
3429
  this.isUnmounted$ = toObservable(this.isUnmounted);
@@ -3011,7 +3453,7 @@ class AnimatedOverlayDirective {
3011
3453
  this.unmountSubscription?.unsubscribe();
3012
3454
  this.unmountSubscription = null;
3013
3455
  this.applyComponentData(config.data);
3014
- this.applyThemeProvider(config.themeProvider);
3456
+ this.applyColorProvider(config.colorProvider);
3015
3457
  const lifecycle = this.componentRef.instance.animatedLifecycle();
3016
3458
  if (lifecycle) {
3017
3459
  this.state.set('mounting');
@@ -3034,7 +3476,7 @@ class AnimatedOverlayDirective {
3034
3476
  }
3035
3477
  return;
3036
3478
  }
3037
- const { component, providers, data, themeProvider } = config;
3479
+ const { component, providers, data, colorProvider } = config;
3038
3480
  this.state.set('mounting');
3039
3481
  this.beforeOpened$.next();
3040
3482
  const injector = Injector.create({
@@ -3045,7 +3487,7 @@ class AnimatedOverlayDirective {
3045
3487
  this.portal = new ComponentPortal(component, this.viewContainerRef, injector);
3046
3488
  this.componentRef = this.overlayRef.attach(this.portal);
3047
3489
  this.applyComponentData(data);
3048
- this.applyThemeProvider(themeProvider);
3490
+ this.applyColorProvider(colorProvider);
3049
3491
  this.updateOverlaySize();
3050
3492
  this.setupFloatingUI();
3051
3493
  return this.componentRef.instance;
@@ -3091,10 +3533,10 @@ class AnimatedOverlayDirective {
3091
3533
  Object.assign(this.componentRef.instance, data);
3092
3534
  this.componentRef.changeDetectorRef.markForCheck();
3093
3535
  }
3094
- applyThemeProvider(themeProvider) {
3095
- if (!this.componentRef || !themeProvider)
3536
+ applyColorProvider(colorProvider) {
3537
+ if (!this.componentRef || !colorProvider)
3096
3538
  return;
3097
- this.componentRef.instance.setThemeFromProvider(themeProvider);
3539
+ this.componentRef.instance.setColorFromProvider(colorProvider);
3098
3540
  }
3099
3541
  updateOverlaySize() {
3100
3542
  if (!this.overlayRef || !this.mirrorWidth())
@@ -3232,10 +3674,10 @@ class AnimatedOverlayDirective {
3232
3674
  this.state.set('unmounted');
3233
3675
  this.afterClosed$.next();
3234
3676
  }
3235
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedOverlayDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3236
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: AnimatedOverlayDirective, isStandalone: true, selector: "[etAnimatedOverlay]", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, fallbackPlacements: { classPropertyName: "fallbackPlacements", publicName: "fallbackPlacements", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, viewportPadding: { classPropertyName: "viewportPadding", publicName: "viewportPadding", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, shift: { classPropertyName: "shift", publicName: "shift", isSignal: true, isRequired: false, transformFunction: null }, autoHide: { classPropertyName: "autoHide", publicName: "autoHide", isSignal: true, isRequired: false, transformFunction: null }, autoCloseIfReferenceHidden: { classPropertyName: "autoCloseIfReferenceHidden", publicName: "autoCloseIfReferenceHidden", isSignal: true, isRequired: false, transformFunction: null }, referenceElement: { classPropertyName: "referenceElement", publicName: "referenceElement", isSignal: true, isRequired: false, transformFunction: null }, mirrorWidth: { classPropertyName: "mirrorWidth", publicName: "mirrorWidth", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "et-animated-overlay" }, exportAs: ["etAnimatedOverlay"], ngImport: i0 }); }
3677
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedOverlayDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3678
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: AnimatedOverlayDirective, isStandalone: true, selector: "[etAnimatedOverlay]", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, fallbackPlacements: { classPropertyName: "fallbackPlacements", publicName: "fallbackPlacements", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, viewportPadding: { classPropertyName: "viewportPadding", publicName: "viewportPadding", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, shift: { classPropertyName: "shift", publicName: "shift", isSignal: true, isRequired: false, transformFunction: null }, autoHide: { classPropertyName: "autoHide", publicName: "autoHide", isSignal: true, isRequired: false, transformFunction: null }, autoCloseIfReferenceHidden: { classPropertyName: "autoCloseIfReferenceHidden", publicName: "autoCloseIfReferenceHidden", isSignal: true, isRequired: false, transformFunction: null }, referenceElement: { classPropertyName: "referenceElement", publicName: "referenceElement", isSignal: true, isRequired: false, transformFunction: null }, mirrorWidth: { classPropertyName: "mirrorWidth", publicName: "mirrorWidth", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "et-animated-overlay" }, exportAs: ["etAnimatedOverlay"], ngImport: i0 }); }
3237
3679
  }
3238
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AnimatedOverlayDirective, decorators: [{
3680
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AnimatedOverlayDirective, decorators: [{
3239
3681
  type: Directive,
3240
3682
  args: [{
3241
3683
  selector: '[etAnimatedOverlay]',
@@ -3334,88 +3776,669 @@ const createFlipAnimation = (config) => {
3334
3776
  cleanup();
3335
3777
  };
3336
3778
  return {
3337
- updateInit,
3338
- play,
3339
- cancel,
3340
- onStart$: onStart$.asObservable(),
3341
- onFinish$: onFinish$.asObservable(),
3342
- onCancel$: onCancel$.asObservable(),
3779
+ updateInit,
3780
+ play,
3781
+ cancel,
3782
+ onStart$: onStart$.asObservable(),
3783
+ onFinish$: onFinish$.asObservable(),
3784
+ onCancel$: onCancel$.asObservable(),
3785
+ };
3786
+ };
3787
+
3788
+ class ClickOutsideDirective {
3789
+ constructor() {
3790
+ this.elementRef = inject(ElementRef);
3791
+ this.document = inject(DOCUMENT);
3792
+ this.didClickOutside = output({ alias: 'etClickOutside' });
3793
+ fromEvent(this.document.documentElement, 'click')
3794
+ .pipe(tap((event) => {
3795
+ const activeElement = event.target;
3796
+ const isInside = this.elementRef.nativeElement.contains(activeElement);
3797
+ if (isInside)
3798
+ return;
3799
+ this.didClickOutside.emit(event);
3800
+ }), takeUntilDestroyed())
3801
+ .subscribe();
3802
+ }
3803
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3804
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ClickOutsideDirective, isStandalone: true, selector: "[etClickOutside]", outputs: { didClickOutside: "etClickOutside" }, ngImport: i0 }); }
3805
+ }
3806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ClickOutsideDirective, decorators: [{
3807
+ type: Directive,
3808
+ args: [{
3809
+ selector: '[etClickOutside]',
3810
+ }]
3811
+ }], ctorParameters: () => [], propDecorators: { didClickOutside: [{ type: i0.Output, args: ["etClickOutside"] }] } });
3812
+
3813
+ class RepeatDirective {
3814
+ constructor() {
3815
+ this.mainTemplateRef = inject(TemplateRef);
3816
+ this.viewContainerRef = inject(ViewContainerRef);
3817
+ this.repeatCount = input(2, { ...(ngDevMode ? { debugName: "repeatCount" } : /* istanbul ignore next */ {}), alias: 'etRepeat', transform: numberAttribute });
3818
+ this.views = linkedSignal({ ...(ngDevMode ? { debugName: "views" } : /* istanbul ignore next */ {}), source: this.repeatCount,
3819
+ computation: (count, previous) => {
3820
+ const prevCount = previous?.source ?? 0;
3821
+ const views = previous?.value ?? [];
3822
+ if (count === prevCount && previous?.value) {
3823
+ return previous.value;
3824
+ }
3825
+ const viewsToCreate = count - prevCount;
3826
+ if (viewsToCreate > 0) {
3827
+ for (let i = 0; i < viewsToCreate; i++) {
3828
+ views.push(this.viewContainerRef.createEmbeddedView(this.mainTemplateRef));
3829
+ }
3830
+ }
3831
+ else if (viewsToCreate < 0) {
3832
+ for (let i = 0; i < -viewsToCreate; i++) {
3833
+ this.viewContainerRef.remove(this.viewContainerRef.length - 1);
3834
+ }
3835
+ views.splice(viewsToCreate);
3836
+ }
3837
+ return views;
3838
+ } });
3839
+ // Ugly but needed to trigger the linked signal.
3840
+ // Otherwise it has no consumers and won't run.
3841
+ effect(() => this.views());
3842
+ }
3843
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: RepeatDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3844
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: RepeatDirective, isStandalone: true, selector: "[etRepeat]", inputs: { repeatCount: { classPropertyName: "repeatCount", publicName: "etRepeat", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
3845
+ }
3846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: RepeatDirective, decorators: [{
3847
+ type: Directive,
3848
+ args: [{
3849
+ selector: '[etRepeat]',
3850
+ }]
3851
+ }], ctorParameters: () => [], propDecorators: { repeatCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "etRepeat", required: false }] }] } });
3852
+
3853
+ class ScrollObserverDirective {
3854
+ constructor() {
3855
+ this.elementRef = inject(ElementRef);
3856
+ this.enabled = model(true, ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
3857
+ this._startEl = signal(null, ...(ngDevMode ? [{ debugName: "_startEl" }] : /* istanbul ignore next */ []));
3858
+ this._endEl = signal(null, ...(ngDevMode ? [{ debugName: "_endEl" }] : /* istanbul ignore next */ []));
3859
+ this._startIntersection = signalElementIntersection(this._startEl, {
3860
+ root: this.elementRef,
3861
+ enabled: this.enabled,
3862
+ });
3863
+ this._endIntersection = signalElementIntersection(this._endEl, {
3864
+ root: this.elementRef,
3865
+ enabled: this.enabled,
3866
+ });
3867
+ this.isAtStart = computed(() => this._startIntersection()[0]?.isIntersecting ?? false, ...(ngDevMode ? [{ debugName: "isAtStart" }] : /* istanbul ignore next */ []));
3868
+ this.isAtEnd = computed(() => this._endIntersection()[0]?.isIntersecting ?? false, ...(ngDevMode ? [{ debugName: "isAtEnd" }] : /* istanbul ignore next */ []));
3869
+ }
3870
+ _registerStart(el) {
3871
+ this._startEl.set(el);
3872
+ }
3873
+ _registerEnd(el) {
3874
+ this._endEl.set(el);
3875
+ }
3876
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3877
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: ScrollObserverDirective, isStandalone: true, selector: "[etScrollObserver]", inputs: { enabled: { classPropertyName: "enabled", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { enabled: "enabledChange" }, exportAs: ["etScrollObserver"], ngImport: i0 }); }
3878
+ }
3879
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverDirective, decorators: [{
3880
+ type: Directive,
3881
+ args: [{
3882
+ selector: '[etScrollObserver]',
3883
+ exportAs: 'etScrollObserver',
3884
+ }]
3885
+ }], propDecorators: { enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "enabled", required: false }] }, { type: i0.Output, args: ["enabledChange"] }] } });
3886
+
3887
+ class ScrollObserverEndDirective {
3888
+ constructor() {
3889
+ this.elementRef = inject(ElementRef);
3890
+ this.host = inject(ScrollObserverDirective);
3891
+ this.host._registerEnd(this.elementRef);
3892
+ }
3893
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverEndDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3894
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ScrollObserverEndDirective, isStandalone: true, selector: "[etScrollObserverEnd]", ngImport: i0 }); }
3895
+ }
3896
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverEndDirective, decorators: [{
3897
+ type: Directive,
3898
+ args: [{
3899
+ selector: '[etScrollObserverEnd]',
3900
+ }]
3901
+ }], ctorParameters: () => [] });
3902
+
3903
+ class ScrollObserverStartDirective {
3904
+ constructor() {
3905
+ this.elementRef = inject(ElementRef);
3906
+ this.host = inject(ScrollObserverDirective);
3907
+ this.host._registerStart(this.elementRef);
3908
+ }
3909
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverStartDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3910
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ScrollObserverStartDirective, isStandalone: true, selector: "[etScrollObserverStart]", ngImport: i0 }); }
3911
+ }
3912
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ScrollObserverStartDirective, decorators: [{
3913
+ type: Directive,
3914
+ args: [{
3915
+ selector: '[etScrollObserverStart]',
3916
+ }]
3917
+ }], ctorParameters: () => [] });
3918
+
3919
+ const setupDragObservable = (startEvent, el, commitThreshold) => {
3920
+ const { pointerId, clientX: startX, clientY: startY } = startEvent;
3921
+ const end$ = merge(fromEvent(document, 'pointerup'), fromEvent(document, 'pointercancel')).pipe(filter((e) => e.pointerId === pointerId), take(1));
3922
+ let lastX = startX;
3923
+ let lastY = startY;
3924
+ let committed = false;
3925
+ const moves$ = fromEvent(document, 'pointermove').pipe(filter((e) => e.pointerId === pointerId), concatMap((e) => {
3926
+ if (!committed) {
3927
+ if (Math.abs(e.clientX - startX) < commitThreshold && Math.abs(e.clientY - startY) < commitThreshold) {
3928
+ return EMPTY;
3929
+ }
3930
+ committed = true;
3931
+ el.setPointerCapture(pointerId);
3932
+ lastX = e.clientX;
3933
+ lastY = e.clientY;
3934
+ return of({ type: 'start' });
3935
+ }
3936
+ const stepX = e.clientX - lastX;
3937
+ const stepY = e.clientY - lastY;
3938
+ lastX = e.clientX;
3939
+ lastY = e.clientY;
3940
+ return of({ type: 'move', data: { stepX, stepY, clientX: e.clientX, clientY: e.clientY } });
3941
+ }), takeUntil(end$));
3942
+ return concat(moves$, defer(() => of(committed ? { type: 'end' } : { type: 'tapped' })));
3943
+ };
3944
+ class DragHandleDirective {
3945
+ constructor() {
3946
+ this.el = inject(ElementRef);
3947
+ this.commitThreshold = input(8, ...(ngDevMode ? [{ debugName: "commitThreshold" }] : /* istanbul ignore next */ []));
3948
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3949
+ this.gestureStart$ = new Subject();
3950
+ this.gesture$ = this.gestureStart$.pipe(exhaustMap((event) => setupDragObservable(event, this.el.nativeElement, this.commitThreshold())), takeUntilDestroyed(), share());
3951
+ this.dragTapped = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'tapped'), map(() => undefined)));
3952
+ this.dragStarted = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'start'), map(() => undefined)));
3953
+ this.dragMoved = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'move'), map((e) => e.data)));
3954
+ this.dragEnded = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'end'), map(() => undefined)));
3955
+ this.isDragging = toSignal(this.gesture$.pipe(map((e) => e.type === 'start' || e.type === 'move'), distinctUntilChanged()), { initialValue: false });
3956
+ applyHostListener('pointerdown', (e) => this.startGesture(e));
3957
+ }
3958
+ startGesture(event) {
3959
+ if (event.button !== 0 || this.disabled())
3960
+ return;
3961
+ event.stopPropagation();
3962
+ this.gestureStart$.next(event);
3963
+ }
3964
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: DragHandleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3965
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: DragHandleDirective, isStandalone: true, selector: "[etDragHandle]", inputs: { commitThreshold: { classPropertyName: "commitThreshold", publicName: "commitThreshold", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragTapped: "dragTapped", dragStarted: "dragStarted", dragMoved: "dragMoved", dragEnded: "dragEnded" }, ngImport: i0 }); }
3966
+ }
3967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: DragHandleDirective, decorators: [{
3968
+ type: Directive,
3969
+ args: [{
3970
+ selector: '[etDragHandle]',
3971
+ }]
3972
+ }], ctorParameters: () => [], propDecorators: { commitThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitThreshold", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dragTapped: [{ type: i0.Output, args: ["dragTapped"] }], dragStarted: [{ type: i0.Output, args: ["dragStarted"] }], dragMoved: [{ type: i0.Output, args: ["dragMoved"] }], dragEnded: [{ type: i0.Output, args: ["dragEnded"] }] } });
3973
+
3974
+ const FOCUSABLE_SELECTOR = [
3975
+ 'a[href]',
3976
+ 'area[href]',
3977
+ 'button:not([disabled])',
3978
+ 'input:not([disabled]):not([type="hidden"])',
3979
+ 'select:not([disabled])',
3980
+ 'textarea:not([disabled])',
3981
+ 'iframe',
3982
+ '[tabindex]:not([tabindex="-1"])',
3983
+ '[contenteditable="true"]',
3984
+ ].join(',');
3985
+ const isHTMLElement = (value) => {
3986
+ return value instanceof HTMLElement;
3987
+ };
3988
+ const isFocusable = (element, document) => {
3989
+ const view = document.defaultView;
3990
+ const style = view?.getComputedStyle(element);
3991
+ const isVisible = style?.display !== 'none' && style?.visibility !== 'hidden' && element.getClientRects().length > 0;
3992
+ return isVisible && !element.hasAttribute('disabled') && element.tabIndex >= 0;
3993
+ };
3994
+ const getFocusableElements = (container, document) => {
3995
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter((el) => isFocusable(el, document));
3996
+ };
3997
+ const getHeadingElement = (container) => {
3998
+ return container.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]');
3999
+ };
4000
+ const focusElement = (element) => {
4001
+ if (!element) {
4002
+ return;
4003
+ }
4004
+ element.focus({ preventScroll: true });
4005
+ };
4006
+ const applyInitialFocus = (paneElement, autoFocus, document) => {
4007
+ if (autoFocus === false) {
4008
+ return;
4009
+ }
4010
+ if (autoFocus === 'container') {
4011
+ focusElement(paneElement);
4012
+ return;
4013
+ }
4014
+ if (autoFocus === 'first-heading') {
4015
+ focusElement(getHeadingElement(paneElement) ?? paneElement);
4016
+ return;
4017
+ }
4018
+ if (autoFocus === 'first-tabbable') {
4019
+ focusElement(getFocusableElements(paneElement, document)[0] ?? paneElement);
4020
+ return;
4021
+ }
4022
+ focusElement(paneElement.querySelector(autoFocus) ?? paneElement);
4023
+ };
4024
+ const setupFocusTrap = (paneElement, overlayRef, enabled, isTopMost, document) => {
4025
+ if (!enabled) {
4026
+ return () => undefined;
4027
+ }
4028
+ const onKeyDown = (event) => {
4029
+ if (event.key !== 'Tab' || !isTopMost(overlayRef)) {
4030
+ return;
4031
+ }
4032
+ const focusableElements = getFocusableElements(paneElement, document);
4033
+ if (focusableElements.length === 0) {
4034
+ event.preventDefault();
4035
+ focusElement(paneElement);
4036
+ return;
4037
+ }
4038
+ const firstElement = focusableElements[0];
4039
+ const lastElement = focusableElements[focusableElements.length - 1];
4040
+ const activeElement = document.activeElement;
4041
+ if (event.shiftKey && activeElement === firstElement) {
4042
+ event.preventDefault();
4043
+ focusElement(lastElement ?? null);
4044
+ return;
4045
+ }
4046
+ if (!event.shiftKey && activeElement === lastElement) {
4047
+ event.preventDefault();
4048
+ focusElement(firstElement ?? null);
4049
+ }
4050
+ };
4051
+ paneElement.addEventListener('keydown', onKeyDown);
4052
+ return () => {
4053
+ paneElement.removeEventListener('keydown', onKeyDown);
4054
+ };
4055
+ };
4056
+
4057
+ const setBaseElementStyles = (config, hostElement, paneElement, renderer) => {
4058
+ renderer.setStyle(hostElement, {
4059
+ position: 'fixed',
4060
+ top: '0',
4061
+ left: '0',
4062
+ right: '0',
4063
+ bottom: '0',
4064
+ display: 'block',
4065
+ pointerEvents: config.hasBackdrop === false ? 'none' : 'auto',
4066
+ });
4067
+ renderer.setStyle(paneElement, {
4068
+ pointerEvents: 'auto',
4069
+ outline: 'none',
4070
+ });
4071
+ };
4072
+ const setBackdropStyles = (backdropElement, renderer) => {
4073
+ renderer.setStyle(backdropElement, {
4074
+ position: 'absolute',
4075
+ top: '0',
4076
+ left: '0',
4077
+ right: '0',
4078
+ bottom: '0',
4079
+ });
4080
+ };
4081
+ const applyCenteredPosition = (hostElement, paneElement, renderer, _config) => {
4082
+ renderer.setStyle(hostElement, {
4083
+ display: 'grid',
4084
+ placeItems: 'center',
4085
+ padding: '16px',
4086
+ overflow: 'auto',
4087
+ });
4088
+ renderer.setStyle(paneElement, {
4089
+ position: 'relative',
4090
+ });
4091
+ };
4092
+ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, renderer) => {
4093
+ const arrowElement = paneElement.querySelector('[et-floating-arrow]');
4094
+ renderer.setStyle(paneElement, {
4095
+ position: 'absolute',
4096
+ top: '0',
4097
+ left: '0',
4098
+ width: strategy.mirrorWidth ? `${strategy.referenceElement.offsetWidth}px` : 'max-content',
4099
+ });
4100
+ const cleanup = autoUpdate(strategy.referenceElement, paneElement, () => {
4101
+ const middleware = [];
4102
+ middleware.push(offset(strategy.offset ?? 8));
4103
+ middleware.push(flip({
4104
+ fallbackPlacements: strategy.fallbackPlacements ?? undefined,
4105
+ fallbackAxisSideDirection: 'start',
4106
+ }));
4107
+ if (strategy.autoResize) {
4108
+ middleware.push(size({
4109
+ padding: strategy.viewportPadding ?? 8,
4110
+ apply({ availableHeight, availableWidth }) {
4111
+ renderer.setCssProperties(paneElement, {
4112
+ '--et-overlay-max-width': `${availableWidth}px`,
4113
+ '--et-overlay-max-height': `${availableHeight}px`,
4114
+ });
4115
+ },
4116
+ }));
4117
+ }
4118
+ if (strategy.shift !== false) {
4119
+ middleware.push(shift({
4120
+ limiter: limitShift(),
4121
+ padding: strategy.viewportPadding ?? 8,
4122
+ }));
4123
+ }
4124
+ if (arrowElement) {
4125
+ middleware.push(arrow({
4126
+ element: arrowElement,
4127
+ padding: strategy.arrowPadding ?? 4,
4128
+ }));
4129
+ }
4130
+ if (strategy.autoHide || strategy.autoCloseIfReferenceHidden) {
4131
+ middleware.push(hide({
4132
+ strategy: 'referenceHidden',
4133
+ }));
4134
+ }
4135
+ computePosition(strategy.referenceElement, paneElement, {
4136
+ placement: strategy.placement ?? 'bottom',
4137
+ strategy: 'absolute',
4138
+ middleware,
4139
+ }).then(({ x, y, placement, middlewareData }) => {
4140
+ renderer.setStyle(paneElement, {
4141
+ transform: `translate3d(${x}px, ${y}px, 0)`,
4142
+ width: strategy.mirrorWidth ? `${strategy.referenceElement.offsetWidth}px` : null,
4143
+ });
4144
+ renderer.setAttribute(paneElement, 'data-overlay-placement', placement);
4145
+ if (arrowElement && middlewareData.arrow) {
4146
+ renderer.setCssProperty(arrowElement, '--et-floating-arrow-translate', `translate3d(${middlewareData.arrow.x ?? 0}px, ${middlewareData.arrow.y ?? 0}px, 0)`);
4147
+ }
4148
+ if (middlewareData.hide?.referenceHidden) {
4149
+ if (strategy.autoCloseIfReferenceHidden) {
4150
+ overlayRef.close(undefined, 'api');
4151
+ return;
4152
+ }
4153
+ renderer.setStyle(paneElement, {
4154
+ visibility: strategy.autoHide ? 'hidden' : null,
4155
+ });
4156
+ return;
4157
+ }
4158
+ renderer.setStyle(paneElement, {
4159
+ visibility: null,
4160
+ });
4161
+ });
4162
+ });
4163
+ return () => {
4164
+ cleanup();
4165
+ };
4166
+ };
4167
+ const setupPositioning = (config, hostElement, paneElement, overlayRef, renderer) => {
4168
+ const strategy = config.positionStrategy ?? { kind: 'center' };
4169
+ if (strategy.kind === 'anchored') {
4170
+ renderer.setStyle(hostElement, {
4171
+ pointerEvents: config.hasBackdrop === false ? 'none' : 'auto',
4172
+ });
4173
+ return createAnchoredPositionCleanup(strategy, paneElement, overlayRef, renderer);
4174
+ }
4175
+ applyCenteredPosition(hostElement, paneElement, renderer, strategy);
4176
+ return () => undefined;
4177
+ };
4178
+
4179
+ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
4180
+ const _state = signal('mounting', ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
4181
+ const _componentInstance = signal(null, ...(ngDevMode ? [{ debugName: "_componentInstance" }] : /* istanbul ignore next */ []));
4182
+ const beforeOpenedSubject = new Subject();
4183
+ const afterOpenedSubject = new Subject();
4184
+ const beforeClosedSubject = new Subject();
4185
+ const afterClosedSubject = new Subject();
4186
+ return {
4187
+ id,
4188
+ config,
4189
+ elements,
4190
+ state: _state.asReadonly(),
4191
+ componentInstance: _componentInstance.asReadonly(),
4192
+ // Internal — driven by overlay-runtime.ts
4193
+ beforeOpenedSubject,
4194
+ close(result, source = 'api') {
4195
+ if (_state() === 'closing' || _state() === 'closed') {
4196
+ return;
4197
+ }
4198
+ requestClose(result, source);
4199
+ },
4200
+ beforeOpened() {
4201
+ return beforeOpenedSubject.asObservable();
4202
+ },
4203
+ afterOpened() {
4204
+ return afterOpenedSubject.asObservable();
4205
+ },
4206
+ beforeClosed() {
4207
+ return beforeClosedSubject.asObservable();
4208
+ },
4209
+ afterClosed() {
4210
+ return afterClosedSubject.asObservable();
4211
+ },
4212
+ attachComponentRef(componentRef) {
4213
+ _componentInstance.set(componentRef.instance);
4214
+ },
4215
+ markOpened() {
4216
+ if (_state() !== 'mounting') {
4217
+ return;
4218
+ }
4219
+ _state.set('mounted');
4220
+ afterOpenedSubject.next();
4221
+ afterOpenedSubject.complete();
4222
+ },
4223
+ beginClose(closeEvent) {
4224
+ if (_state() === 'closing' || _state() === 'closed') {
4225
+ return false;
4226
+ }
4227
+ _state.set('closing');
4228
+ beforeClosedSubject.next(closeEvent);
4229
+ beforeClosedSubject.complete();
4230
+ return true;
4231
+ },
4232
+ finishClose(closeEvent) {
4233
+ if (_state() === 'closed') {
4234
+ return;
4235
+ }
4236
+ _state.set('closed');
4237
+ _componentInstance.set(null);
4238
+ afterClosedSubject.next(closeEvent);
4239
+ afterClosedSubject.complete();
4240
+ },
3343
4241
  };
3344
4242
  };
3345
4243
 
3346
- class ClickOutsideDirective {
3347
- constructor() {
3348
- this.elementRef = inject(ElementRef);
3349
- this.document = inject(DOCUMENT);
3350
- this.didClickOutside = output({ alias: 'etClickOutside' });
3351
- fromEvent(this.document.documentElement, 'click')
3352
- .pipe(tap((event) => {
3353
- const activeElement = event.target;
3354
- const isInside = this.elementRef.nativeElement.contains(activeElement);
3355
- if (isInside)
4244
+ const [provideOverlayRuntime, injectOverlayRuntime] = createRootProvider(() => {
4245
+ const appRef = inject(ApplicationRef);
4246
+ const destroyRef = inject(DestroyRef);
4247
+ const document = inject(DOCUMENT);
4248
+ const environmentInjector = inject(EnvironmentInjector);
4249
+ const renderer = injectRenderer();
4250
+ const openEntriesState = signal([], ...(ngDevMode ? [{ debugName: "openEntriesState" }] : /* istanbul ignore next */ []));
4251
+ const openEntries = computed(() => openEntriesState(), ...(ngDevMode ? [{ debugName: "openEntries" }] : /* istanbul ignore next */ []));
4252
+ let rootElement = null;
4253
+ const getRootElement = () => {
4254
+ if (rootElement) {
4255
+ return rootElement;
4256
+ }
4257
+ rootElement = renderer.createElement('div');
4258
+ renderer.addClass(rootElement, 'et-overlay-runtime-root');
4259
+ renderer.setStyle(rootElement, {
4260
+ position: 'fixed',
4261
+ top: '0',
4262
+ left: '0',
4263
+ right: '0',
4264
+ bottom: '0',
4265
+ pointerEvents: 'none',
4266
+ zIndex: '1000',
4267
+ });
4268
+ renderer.appendChild(document.body, rootElement);
4269
+ return rootElement;
4270
+ };
4271
+ const maybeDestroyRootElement = () => {
4272
+ if (!rootElement || openEntriesState().length > 0) {
4273
+ return;
4274
+ }
4275
+ const parentNode = renderer.parentNode(rootElement);
4276
+ if (parentNode) {
4277
+ renderer.removeChild(parentNode, rootElement);
4278
+ }
4279
+ rootElement = null;
4280
+ };
4281
+ const isTopMost = (overlayRef) => {
4282
+ return openEntriesState().at(-1) === overlayRef;
4283
+ };
4284
+ const getAnimatedLifecycle = (componentRef) => {
4285
+ const componentLifecycle = componentRef.instance.animatedLifecycle?.();
4286
+ if (componentLifecycle) {
4287
+ return componentLifecycle;
4288
+ }
4289
+ return componentRef.injector.get(ANIMATED_LIFECYCLE_TOKEN, null);
4290
+ };
4291
+ const mount = (config) => {
4292
+ const root = getRootElement();
4293
+ const hostElement = renderer.createElement('div');
4294
+ const paneElement = renderer.createElement('div');
4295
+ const backdropElement = config.hasBackdrop === false ? null : renderer.createElement('div');
4296
+ const previousFocusedElement = isHTMLElement(document.activeElement) ? document.activeElement : null;
4297
+ const autoFocus = config.autoFocus ?? 'first-tabbable';
4298
+ renderer.addClass(hostElement, 'et-overlay-runtime-entry');
4299
+ renderer.addClass(paneElement, 'et-overlay-runtime-pane');
4300
+ setBaseElementStyles(config, hostElement, paneElement, renderer);
4301
+ renderer.setAttributes(hostElement, {
4302
+ 'data-overlay-id': config.id,
4303
+ role: config.role ?? null,
4304
+ tabindex: '-1',
4305
+ 'aria-modal': config.role ? `${config.modal !== false}` : null,
4306
+ 'aria-describedby': config.ariaDescribedBy ?? null,
4307
+ 'aria-labelledby': config.ariaLabelledBy ?? null,
4308
+ 'aria-label': config.ariaLabel ?? null,
4309
+ });
4310
+ renderer.addClass(hostElement, ...(config.hostClass ?? []));
4311
+ renderer.addClass(paneElement, ...(config.paneClass ?? []));
4312
+ if (backdropElement) {
4313
+ renderer.addClass(backdropElement, 'et-overlay-runtime-backdrop');
4314
+ setBackdropStyles(backdropElement, renderer);
4315
+ renderer.setAttribute(backdropElement, 'data-overlay-id', config.id);
4316
+ (config.backdropClass ?? []).forEach((className) => renderer.addClass(backdropElement, className));
4317
+ renderer.appendChild(hostElement, backdropElement);
4318
+ }
4319
+ renderer.appendChild(hostElement, paneElement);
4320
+ renderer.appendChild(root, hostElement);
4321
+ const overlayRef = createOverlayRuntimeRef(config.id, { ...config }, {
4322
+ rootElement: root,
4323
+ hostElement,
4324
+ backdropElement,
4325
+ paneElement,
4326
+ }, (result, source) => beginClose({ result, source }));
4327
+ const cleanupFns = [];
4328
+ const parentInjector = config.injector ?? config.viewContainerRef?.injector ?? environmentInjector;
4329
+ const elementInjector = Injector.create({
4330
+ parent: parentInjector,
4331
+ providers: config.providers ?? [],
4332
+ });
4333
+ const componentRef = createComponent(config.component, {
4334
+ environmentInjector,
4335
+ elementInjector,
4336
+ hostElement: paneElement,
4337
+ bindings: Object.entries(config.inputBindings ?? {}).map(([key, value]) => inputBinding(key, () => value)),
4338
+ });
4339
+ appRef.attachView(componentRef.hostView);
4340
+ overlayRef.attachComponentRef(componentRef);
4341
+ overlayRef.beforeOpenedSubject.next();
4342
+ overlayRef.beforeOpenedSubject.complete();
4343
+ openEntriesState.update((entries) => [...entries, overlayRef]);
4344
+ cleanupFns.push(setupPositioning(config, hostElement, paneElement, overlayRef, renderer));
4345
+ const destroyMountedOverlay = (closeEvent) => {
4346
+ cleanupFns.forEach((cleanup) => cleanup());
4347
+ appRef.detachView(componentRef.hostView);
4348
+ componentRef.destroy();
4349
+ const parentNode = renderer.parentNode(hostElement);
4350
+ if (parentNode) {
4351
+ renderer.removeChild(parentNode, hostElement);
4352
+ }
4353
+ openEntriesState.update((entries) => entries.filter((entry) => entry !== overlayRef));
4354
+ maybeDestroyRootElement();
4355
+ if (config.restoreFocus !== false && previousFocusedElement?.isConnected) {
4356
+ previousFocusedElement.focus({ preventScroll: true });
4357
+ }
4358
+ overlayRef.finishClose(closeEvent);
4359
+ };
4360
+ const beginClose = (closeEvent) => {
4361
+ if (!overlayRef.beginClose(closeEvent)) {
3356
4362
  return;
3357
- this.didClickOutside.emit(event);
3358
- }), takeUntilDestroyed())
3359
- .subscribe();
3360
- }
3361
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3362
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.1", type: ClickOutsideDirective, isStandalone: true, selector: "[etClickOutside]", outputs: { didClickOutside: "etClickOutside" }, ngImport: i0 }); }
3363
- }
3364
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ClickOutsideDirective, decorators: [{
3365
- type: Directive,
3366
- args: [{
3367
- selector: '[etClickOutside]',
3368
- }]
3369
- }], ctorParameters: () => [], propDecorators: { didClickOutside: [{ type: i0.Output, args: ["etClickOutside"] }] } });
3370
-
3371
- class RepeatDirective {
3372
- constructor() {
3373
- this.mainTemplateRef = inject(TemplateRef);
3374
- this.viewContainerRef = inject(ViewContainerRef);
3375
- this.repeatCount = input(2, { ...(ngDevMode ? { debugName: "repeatCount" } : {}), alias: 'etRepeat', transform: numberAttribute });
3376
- this.views = linkedSignal({ ...(ngDevMode ? { debugName: "views" } : {}), source: this.repeatCount,
3377
- computation: (count, previous) => {
3378
- const prevCount = previous?.source ?? 0;
3379
- const views = previous?.value ?? [];
3380
- if (count === prevCount && previous?.value) {
3381
- return previous.value;
4363
+ }
4364
+ const lifecycle = getAnimatedLifecycle(componentRef);
4365
+ if (!lifecycle) {
4366
+ destroyMountedOverlay(closeEvent);
4367
+ return;
4368
+ }
4369
+ lifecycle.leave();
4370
+ lifecycle.state$
4371
+ .pipe(filter((state) => state === 'left'), take(1))
4372
+ .subscribe(() => {
4373
+ destroyMountedOverlay(closeEvent);
4374
+ });
4375
+ };
4376
+ const closeOnEscape = config.closeOnEscape ?? true;
4377
+ if (closeOnEscape) {
4378
+ const onKeyDown = (event) => {
4379
+ if (event.key !== 'Escape' || !isTopMost(overlayRef)) {
4380
+ return;
3382
4381
  }
3383
- const viewsToCreate = count - prevCount;
3384
- if (viewsToCreate > 0) {
3385
- for (let i = 0; i < viewsToCreate; i++) {
3386
- views.push(this.viewContainerRef.createEmbeddedView(this.mainTemplateRef));
3387
- }
4382
+ event.preventDefault();
4383
+ overlayRef.close(undefined, 'escape');
4384
+ };
4385
+ document.addEventListener('keydown', onKeyDown, true);
4386
+ cleanupFns.push(() => document.removeEventListener('keydown', onKeyDown, true));
4387
+ }
4388
+ const closeOnOutsidePointer = config.closeOnOutsidePointer ?? config.modal === false;
4389
+ if (closeOnOutsidePointer) {
4390
+ const onPointerDown = (event) => {
4391
+ if (!isTopMost(overlayRef)) {
4392
+ return;
3388
4393
  }
3389
- else if (viewsToCreate < 0) {
3390
- for (let i = 0; i < -viewsToCreate; i++) {
3391
- this.viewContainerRef.remove(this.viewContainerRef.length - 1);
3392
- }
3393
- views.splice(viewsToCreate);
4394
+ const target = event.target;
4395
+ if (!isHTMLElement(target) || paneElement.contains(target)) {
4396
+ return;
3394
4397
  }
3395
- return views;
3396
- } });
3397
- // Ugly but needed to trigger the linked signal.
3398
- // Otherwise it has no consumers and won't run.
3399
- effect(() => this.views());
3400
- }
3401
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: RepeatDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3402
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: RepeatDirective, isStandalone: true, selector: "[etRepeat]", inputs: { repeatCount: { classPropertyName: "repeatCount", publicName: "etRepeat", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
3403
- }
3404
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: RepeatDirective, decorators: [{
3405
- type: Directive,
3406
- args: [{
3407
- selector: '[etRepeat]',
3408
- }]
3409
- }], ctorParameters: () => [], propDecorators: { repeatCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "etRepeat", required: false }] }] } });
4398
+ overlayRef.close(undefined, 'outside-pointer');
4399
+ };
4400
+ document.addEventListener('pointerdown', onPointerDown, true);
4401
+ cleanupFns.push(() => document.removeEventListener('pointerdown', onPointerDown, true));
4402
+ }
4403
+ cleanupFns.push(setupFocusTrap(paneElement, overlayRef, config.modal !== false, isTopMost, document));
4404
+ nextFrame(() => {
4405
+ if (overlayRef.state() !== 'mounting') {
4406
+ return;
4407
+ }
4408
+ const lifecycle = getAnimatedLifecycle(componentRef);
4409
+ if (!lifecycle) {
4410
+ applyInitialFocus(paneElement, autoFocus, document);
4411
+ overlayRef.markOpened();
4412
+ return;
4413
+ }
4414
+ lifecycle.enter();
4415
+ lifecycle.state$
4416
+ .pipe(filter((state) => state === 'entered'), take(1))
4417
+ .subscribe(() => {
4418
+ applyInitialFocus(paneElement, autoFocus, document);
4419
+ overlayRef.markOpened();
4420
+ });
4421
+ });
4422
+ return overlayRef;
4423
+ };
4424
+ destroyRef.onDestroy(() => {
4425
+ openEntriesState().forEach((entry) => entry.close(undefined, 'api'));
4426
+ maybeDestroyRootElement();
4427
+ });
4428
+ return {
4429
+ mount,
4430
+ openEntries,
4431
+ };
4432
+ }, { name: 'OverlayRuntime' });
3410
4433
 
3411
4434
  class NormalizeGameResultTypePipe {
3412
4435
  constructor() {
3413
4436
  this.transform = normalizeGameResultType;
3414
4437
  }
3415
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeGameResultTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3416
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: NormalizeGameResultTypePipe, isStandalone: true, name: "etNormalizeGameResultType" }); }
4438
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeGameResultTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4439
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: NormalizeGameResultTypePipe, isStandalone: true, name: "etNormalizeGameResultType" }); }
3417
4440
  }
3418
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeGameResultTypePipe, decorators: [{
4441
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeGameResultTypePipe, decorators: [{
3419
4442
  type: Pipe,
3420
4443
  args: [{ name: 'etNormalizeGameResultType' }]
3421
4444
  }] });
@@ -3457,10 +4480,10 @@ class NormalizeMatchStatePipe {
3457
4480
  constructor() {
3458
4481
  this.transform = normalizeMatchState;
3459
4482
  }
3460
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchStatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3461
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchStatePipe, isStandalone: true, name: "etNormalizeMatchState" }); }
4483
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchStatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4484
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchStatePipe, isStandalone: true, name: "etNormalizeMatchState" }); }
3462
4485
  }
3463
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchStatePipe, decorators: [{
4486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchStatePipe, decorators: [{
3464
4487
  type: Pipe,
3465
4488
  args: [{ name: 'etNormalizeMatchState' }]
3466
4489
  }] });
@@ -3487,10 +4510,10 @@ class NormalizeMatchParticipantsPipe {
3487
4510
  constructor() {
3488
4511
  this.transform = normalizeMatchParticipants;
3489
4512
  }
3490
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchParticipantsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3491
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchParticipantsPipe, isStandalone: true, name: "etNormalizeMatchParticipants" }); }
4513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchParticipantsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4514
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchParticipantsPipe, isStandalone: true, name: "etNormalizeMatchParticipants" }); }
3492
4515
  }
3493
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchParticipantsPipe, decorators: [{
4516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchParticipantsPipe, decorators: [{
3494
4517
  type: Pipe,
3495
4518
  args: [{ name: 'etNormalizeMatchParticipants' }]
3496
4519
  }] });
@@ -3544,10 +4567,10 @@ class NormalizeMatchScorePipe {
3544
4567
  constructor() {
3545
4568
  this.transform = normalizeMatchScore;
3546
4569
  }
3547
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchScorePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3548
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchScorePipe, isStandalone: true, name: "etNormalizeMatchScore" }); }
4570
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchScorePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4571
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchScorePipe, isStandalone: true, name: "etNormalizeMatchScore" }); }
3549
4572
  }
3550
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchScorePipe, decorators: [{
4573
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchScorePipe, decorators: [{
3551
4574
  type: Pipe,
3552
4575
  args: [{ name: 'etNormalizeMatchScore' }]
3553
4576
  }] });
@@ -3680,10 +4703,10 @@ class NormalizeMatchTypePipe {
3680
4703
  constructor() {
3681
4704
  this.transform = normalizeMatchType;
3682
4705
  }
3683
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3684
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchTypePipe, isStandalone: true, name: "etNormalizeMatchType" }); }
4706
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4707
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchTypePipe, isStandalone: true, name: "etNormalizeMatchType" }); }
3685
4708
  }
3686
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NormalizeMatchTypePipe, decorators: [{
4709
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: NormalizeMatchTypePipe, decorators: [{
3687
4710
  type: Pipe,
3688
4711
  args: [{ name: 'etNormalizeMatchType' }]
3689
4712
  }] });
@@ -3722,6 +4745,8 @@ const normalizeMatchType = (matchType) => {
3722
4745
  i18n: 'match-type.pools',
3723
4746
  text: 'Pools',
3724
4747
  };
4748
+ default:
4749
+ return null;
3725
4750
  }
3726
4751
  };
3727
4752
 
@@ -3729,10 +4754,10 @@ class InferMimeTypePipe {
3729
4754
  constructor() {
3730
4755
  this.transform = inferMimeType;
3731
4756
  }
3732
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: InferMimeTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3733
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: InferMimeTypePipe, isStandalone: true, name: "inferMimeType" }); }
4757
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InferMimeTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4758
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: InferMimeTypePipe, isStandalone: true, name: "inferMimeType" }); }
3734
4759
  }
3735
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: InferMimeTypePipe, decorators: [{
4760
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: InferMimeTypePipe, decorators: [{
3736
4761
  type: Pipe,
3737
4762
  args: [{
3738
4763
  name: 'inferMimeType',
@@ -3746,6 +4771,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
3746
4771
  const inferMimeType = (srcset) => {
3747
4772
  if (!srcset)
3748
4773
  return null;
4774
+ if (srcset.startsWith('data:')) {
4775
+ const match = /^data:([^;,]+)/.exec(srcset);
4776
+ return match?.[1] ?? null;
4777
+ }
3749
4778
  const urls = srcset.split(',');
3750
4779
  const firstUrl = urls[0];
3751
4780
  if (!firstUrl)
@@ -3938,10 +4967,10 @@ class ToArrayPipe {
3938
4967
  constructor() {
3939
4968
  this.transform = toArray;
3940
4969
  }
3941
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ToArrayPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3942
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.1", ngImport: i0, type: ToArrayPipe, isStandalone: true, name: "toArray" }); }
4970
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ToArrayPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4971
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.13", ngImport: i0, type: ToArrayPipe, isStandalone: true, name: "toArray" }); }
3943
4972
  }
3944
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ToArrayPipe, decorators: [{
4973
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ToArrayPipe, decorators: [{
3945
4974
  type: Pipe,
3946
4975
  args: [{ name: 'toArray' }]
3947
4976
  }] });
@@ -3973,14 +5002,14 @@ const createElementDictionary = () => {
3973
5002
  const firstElement = computed(() => {
3974
5003
  const id = dictionary.ids()[0];
3975
5004
  return id ? (dictionary.elements()[id] ?? null) : null;
3976
- }, ...(ngDevMode ? [{ debugName: "firstElement" }] : []));
5005
+ }, ...(ngDevMode ? [{ debugName: "firstElement" }] : /* istanbul ignore next */ []));
3977
5006
  const firstId = computed(() => {
3978
5007
  const id = dictionary.ids()[0];
3979
5008
  return id ?? null;
3980
- }, ...(ngDevMode ? [{ debugName: "firstId" }] : []));
3981
- const ids = computed(() => dictionary.ids(), ...(ngDevMode ? [{ debugName: "ids" }] : []));
3982
- const elements = computed(() => ids().map((id) => dictionary.elements()[id]), ...(ngDevMode ? [{ debugName: "elements" }] : []));
3983
- const isEmpty = computed(() => dictionary.ids().length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
5009
+ }, ...(ngDevMode ? [{ debugName: "firstId" }] : /* istanbul ignore next */ []));
5010
+ const ids = computed(() => dictionary.ids(), ...(ngDevMode ? [{ debugName: "ids" }] : /* istanbul ignore next */ []));
5011
+ const elements = computed(() => ids().map((id) => dictionary.elements()[id]), ...(ngDevMode ? [{ debugName: "elements" }] : /* istanbul ignore next */ []));
5012
+ const isEmpty = computed(() => dictionary.ids().length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
3984
5013
  const has = (id) => {
3985
5014
  return dictionary.ids().includes(id);
3986
5015
  };
@@ -4064,7 +5093,7 @@ const unbindProps = (config) => {
4064
5093
  const createProps = (props) => {
4065
5094
  const { bindId = false, single = true, classes: classBindings, attributes: attributeBindings, styles: styleBindings, staticAttributes: staticAttributeBindings = null, staticClasses: staticClassBindings = null, staticStyles: staticStyleBindings = null, listeners, name, } = props;
4066
5095
  const dictionary = createElementDictionary();
4067
- const attached = computed(() => !dictionary.isEmpty(), ...(ngDevMode ? [{ debugName: "attached" }] : []));
5096
+ const attached = computed(() => !dictionary.isEmpty(), ...(ngDevMode ? [{ debugName: "attached" }] : /* istanbul ignore next */ []));
4068
5097
  const attachedElements = {
4069
5098
  first: dictionary.firstElement,
4070
5099
  firstId: dictionary.firstId,
@@ -4150,7 +5179,7 @@ const createDependencyStash = (stash) => {
4150
5179
  class PropsDirective {
4151
5180
  constructor() {
4152
5181
  this.destroyRef = inject(DestroyRef);
4153
- this.props = input.required({ ...(ngDevMode ? { debugName: "props" } : {}), alias: 'etProps', transform: (d) => d });
5182
+ this.props = input.required({ ...(ngDevMode ? { debugName: "props" } : /* istanbul ignore next */ {}), alias: 'etProps', transform: (d) => d });
4154
5183
  this.propHandlers = createPropHandlers();
4155
5184
  afterNextRender({
4156
5185
  write: () => {
@@ -4167,10 +5196,10 @@ class PropsDirective {
4167
5196
  });
4168
5197
  });
4169
5198
  }
4170
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PropsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4171
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: PropsDirective, isStandalone: true, selector: "[etProps]", inputs: { props: { classPropertyName: "props", publicName: "etProps", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
5199
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PropsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5200
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: PropsDirective, isStandalone: true, selector: "[etProps]", inputs: { props: { classPropertyName: "props", publicName: "etProps", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
4172
5201
  }
4173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PropsDirective, decorators: [{
5202
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PropsDirective, decorators: [{
4174
5203
  type: Directive,
4175
5204
  args: [{
4176
5205
  selector: '[etProps]',
@@ -4217,6 +5246,76 @@ const templateComputed = (templateSignal) => computed(() => {
4217
5246
  };
4218
5247
  });
4219
5248
 
5249
+ const EDGE_CURSORS = {
5250
+ n: 'ns-resize',
5251
+ s: 'ns-resize',
5252
+ e: 'ew-resize',
5253
+ w: 'ew-resize',
5254
+ ne: 'nesw-resize',
5255
+ sw: 'nesw-resize',
5256
+ nw: 'nwse-resize',
5257
+ se: 'nwse-resize',
5258
+ };
5259
+ const setupResizeObservable = (startEvent, edge) => {
5260
+ const pointerId = startEvent.pointerId;
5261
+ const startX = startEvent.clientX;
5262
+ const startY = startEvent.clientY;
5263
+ const end$ = merge(fromEvent(document, 'pointerup'), fromEvent(document, 'pointercancel')).pipe(filter((e) => e.pointerId === pointerId), take(1));
5264
+ return concat(of({ type: 'start', edge }), fromEvent(document, 'pointermove').pipe(filter((e) => e.pointerId === pointerId), map((e) => ({ type: 'move', data: { edge, dx: e.clientX - startX, dy: e.clientY - startY } })), takeUntil(end$)), of({ type: 'end' }));
5265
+ };
5266
+ class ResizeHandlesComponent {
5267
+ constructor() {
5268
+ this.edges = input(['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'], ...(ngDevMode ? [{ debugName: "edges" }] : /* istanbul ignore next */ []));
5269
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5270
+ this.gestureStart$ = new Subject();
5271
+ this.gesture$ = this.gestureStart$.pipe(exhaustMap(({ event, edge }) => setupResizeObservable(event, edge)), takeUntilDestroyed(), share());
5272
+ this.resizeStarted = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'start'), map((e) => e.edge)));
5273
+ this.resizeMoved = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'move'), map((e) => e.data)));
5274
+ this.resizeEnded = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'end'), map(() => undefined)));
5275
+ this.isResizing = toSignal(this.gesture$.pipe(map((e) => e.type !== 'end'), distinctUntilChanged()), { initialValue: false });
5276
+ this.activeEdge = toSignal(this.gesture$.pipe(map((e) => {
5277
+ if (e.type === 'end')
5278
+ return null;
5279
+ if (e.type === 'start')
5280
+ return e.edge;
5281
+ return e.data.edge;
5282
+ }), distinctUntilChanged()), { initialValue: null });
5283
+ this.edgeCursors = EDGE_CURSORS;
5284
+ }
5285
+ startResizeGesture(event, edge) {
5286
+ if (event.button !== 0 || this.disabled())
5287
+ return;
5288
+ event.stopPropagation();
5289
+ this.gestureStart$.next({ event, edge });
5290
+ }
5291
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ResizeHandlesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5292
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: ResizeHandlesComponent, isStandalone: true, selector: "et-resize-handles", inputs: { edges: { classPropertyName: "edges", publicName: "edges", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resizeStarted: "resizeStarted", resizeMoved: "resizeMoved", resizeEnded: "resizeEnded" }, host: { properties: { "attr.inert": "disabled() ? \"\" : null", "attr.data-active-edge": "activeEdge()" }, classAttribute: "et-resize-handles" }, ngImport: i0, template: `
5293
+ @for (edge of edges(); track edge) {
5294
+ <div
5295
+ [style.cursor]="edgeCursors[edge]"
5296
+ (pointerdown)="startResizeGesture($event, edge)"
5297
+ class="et-resize-handle et-resize-handle--{{ edge }}"
5298
+ ></div>
5299
+ }
5300
+ `, isInline: true, styles: ["@property --et-resize-handles-z-index{syntax: \"<integer>\"; inherits: true; initial-value: 10;}@property --et-resize-handles-edge-size{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-resize-handles-corner-size{syntax: \"<length>\"; inherits: true; initial-value: 12px;}@property --et-resize-handles-edge-inset{syntax: \"<length>\"; inherits: true; initial-value: 8px;}@property --et-resize-handles-side-top{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --et-resize-handles-side-bottom{syntax: \"<length>\"; inherits: true; initial-value: 8px;}@property --et-resize-handles-touch-edge-size{syntax: \"<length>\"; inherits: true; initial-value: 20px;}@property --et-resize-handles-touch-corner-size{syntax: \"<length>\"; inherits: true; initial-value: 28px;}et-resize-handles{position:absolute;inset:0;pointer-events:none}.et-resize-handle{position:absolute;z-index:var(--et-resize-handles-z-index);touch-action:none;pointer-events:auto}.et-resize-handle--n{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handles-edge-size);top:0}.et-resize-handle--s{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handles-edge-size);bottom:0}.et-resize-handle--e,.et-resize-handle--w{top:var(--et-resize-handles-side-top);bottom:var(--et-resize-handles-side-bottom);width:var(--et-resize-handles-edge-size)}.et-resize-handle--e{right:0}.et-resize-handle--w{left:0}.et-resize-handle--ne,.et-resize-handle--nw{top:0;width:var(--et-resize-handles-corner-size);height:var(--et-resize-handles-corner-size)}.et-resize-handle--ne{right:0}.et-resize-handle--nw{left:0}.et-resize-handle--se,.et-resize-handle--sw{bottom:0;width:var(--et-resize-handles-corner-size);height:var(--et-resize-handles-corner-size)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(hover:none){.et-resize-handle--n,.et-resize-handle--s{height:var(--et-resize-handles-touch-edge-size)}.et-resize-handle--e,.et-resize-handle--w{width:var(--et-resize-handles-touch-edge-size)}.et-resize-handle--ne,.et-resize-handle--nw,.et-resize-handle--se,.et-resize-handle--sw{width:var(--et-resize-handles-touch-corner-size);height:var(--et-resize-handles-touch-corner-size)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
5301
+ }
5302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ResizeHandlesComponent, decorators: [{
5303
+ type: Component,
5304
+ args: [{ selector: 'et-resize-handles', template: `
5305
+ @for (edge of edges(); track edge) {
5306
+ <div
5307
+ [style.cursor]="edgeCursors[edge]"
5308
+ (pointerdown)="startResizeGesture($event, edge)"
5309
+ class="et-resize-handle et-resize-handle--{{ edge }}"
5310
+ ></div>
5311
+ }
5312
+ `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
5313
+ class: 'et-resize-handles',
5314
+ '[attr.inert]': 'disabled() ? "" : null',
5315
+ '[attr.data-active-edge]': 'activeEdge()',
5316
+ }, styles: ["@property --et-resize-handles-z-index{syntax: \"<integer>\"; inherits: true; initial-value: 10;}@property --et-resize-handles-edge-size{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-resize-handles-corner-size{syntax: \"<length>\"; inherits: true; initial-value: 12px;}@property --et-resize-handles-edge-inset{syntax: \"<length>\"; inherits: true; initial-value: 8px;}@property --et-resize-handles-side-top{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --et-resize-handles-side-bottom{syntax: \"<length>\"; inherits: true; initial-value: 8px;}@property --et-resize-handles-touch-edge-size{syntax: \"<length>\"; inherits: true; initial-value: 20px;}@property --et-resize-handles-touch-corner-size{syntax: \"<length>\"; inherits: true; initial-value: 28px;}et-resize-handles{position:absolute;inset:0;pointer-events:none}.et-resize-handle{position:absolute;z-index:var(--et-resize-handles-z-index);touch-action:none;pointer-events:auto}.et-resize-handle--n{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handles-edge-size);top:0}.et-resize-handle--s{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handles-edge-size);bottom:0}.et-resize-handle--e,.et-resize-handle--w{top:var(--et-resize-handles-side-top);bottom:var(--et-resize-handles-side-bottom);width:var(--et-resize-handles-edge-size)}.et-resize-handle--e{right:0}.et-resize-handle--w{left:0}.et-resize-handle--ne,.et-resize-handle--nw{top:0;width:var(--et-resize-handles-corner-size);height:var(--et-resize-handles-corner-size)}.et-resize-handle--ne{right:0}.et-resize-handle--nw{left:0}.et-resize-handle--se,.et-resize-handle--sw{bottom:0;width:var(--et-resize-handles-corner-size);height:var(--et-resize-handles-corner-size)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(hover:none){.et-resize-handle--n,.et-resize-handle--s{height:var(--et-resize-handles-touch-edge-size)}.et-resize-handle--e,.et-resize-handle--w{width:var(--et-resize-handles-touch-edge-size)}.et-resize-handle--ne,.et-resize-handle--nw,.et-resize-handle--se,.et-resize-handle--sw{width:var(--et-resize-handles-touch-corner-size);height:var(--et-resize-handles-touch-corner-size)}}\n"] }]
5317
+ }], propDecorators: { edges: [{ type: i0.Input, args: [{ isSignal: true, alias: "edges", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], resizeStarted: [{ type: i0.Output, args: ["resizeStarted"] }], resizeMoved: [{ type: i0.Output, args: ["resizeMoved"] }], resizeEnded: [{ type: i0.Output, args: ["resizeEnded"] }] } });
5318
+
4220
5319
  const applyHeadBinding = (binding, applyFn, removeFn, isValid) => {
4221
5320
  const destroyRef = inject(DestroyRef);
4222
5321
  const signalBinding = isSignal(binding) ? binding : signal(binding);
@@ -4250,7 +5349,7 @@ const createPropertyBinding = (configBuilder, applyConfigFn) => {
4250
5349
  const createArrayPropertyBinding = (configBuilder, applyConfigFn) => {
4251
5350
  return (binding) => {
4252
5351
  const valuesSignal = isSignal(binding) ? binding : signal(binding);
4253
- const valuesList = computed(() => untracked(() => valuesSignal()) ?? [], ...(ngDevMode ? [{ debugName: "valuesList" }] : []));
5352
+ const valuesList = computed(() => untracked(() => valuesSignal()) ?? [], ...(ngDevMode ? [{ debugName: "valuesList" }] : /* istanbul ignore next */ []));
4254
5353
  valuesList().forEach((value, index) => {
4255
5354
  applyConfigFn(computed(() => configBuilder(value, index)));
4256
5355
  });
@@ -4295,7 +5394,7 @@ const [provideLinkStoreConfig, injectLinkStoreConfig] = createStaticRootProvider
4295
5394
  const [provideLinkStore, injectLinkStore] = createRootProvider(() => {
4296
5395
  const document = inject(DOCUMENT$1);
4297
5396
  const config = injectLinkStoreConfig();
4298
- const linksByKey = signal(new Map(), ...(ngDevMode ? [{ debugName: "linksByKey" }] : []));
5397
+ const linksByKey = signal(new Map(), ...(ngDevMode ? [{ debugName: "linksByKey" }] : /* istanbul ignore next */ []));
4299
5398
  let priorityCounter = 0;
4300
5399
  const getLinkKey = (linkConfig) => {
4301
5400
  const isMultiInstance = config.multiInstanceRels.has(linkConfig.rel) || linkConfig.allowMultiple;
@@ -4457,7 +5556,7 @@ const [provideTitleConfig, injectTitleConfig] = createStaticRootProvider({
4457
5556
  }, { name: 'Title Config' });
4458
5557
  const [provideTitleStore, injectTitleStore] = createRootProvider(() => {
4459
5558
  const config = injectTitleConfig();
4460
- const titleParts = signal(new Map(), ...(ngDevMode ? [{ debugName: "titleParts" }] : []));
5559
+ const titleParts = signal(new Map(), ...(ngDevMode ? [{ debugName: "titleParts" }] : /* istanbul ignore next */ []));
4461
5560
  const { currentLocale } = injectLocale();
4462
5561
  const titleService = inject(Title);
4463
5562
  const isRouterInitialized = injectIsRouterInitialized();
@@ -4485,7 +5584,7 @@ const [provideTitleStore, injectTitleStore] = createRootProvider(() => {
4485
5584
  finalTextParts.push(config.transformer(config.suffixPart.text, currentLocale()));
4486
5585
  }
4487
5586
  return finalTextParts.join(` ${config.divider} `);
4488
- }, ...(ngDevMode ? [{ debugName: "title" }] : []));
5587
+ }, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
4489
5588
  const addPart = (id, part) => {
4490
5589
  titleParts.update((parts) => new Map(parts).set(id, part));
4491
5590
  };
@@ -4585,7 +5684,7 @@ const [provideMetaStore, injectMetaStore] = createRootProvider(() => {
4585
5684
  const metaService = inject(Meta);
4586
5685
  const config = injectMetaConfig();
4587
5686
  const { currentLocale } = injectLocale();
4588
- const metaTagsBySelector = signal(new Map(), ...(ngDevMode ? [{ debugName: "metaTagsBySelector" }] : []));
5687
+ const metaTagsBySelector = signal(new Map(), ...(ngDevMode ? [{ debugName: "metaTagsBySelector" }] : /* istanbul ignore next */ []));
4589
5688
  let priorityCounter = 0;
4590
5689
  const getSelector = (config) => {
4591
5690
  if (config.name)
@@ -5012,10 +6111,10 @@ class SeoDirective {
5012
6111
  }
5013
6112
  }
5014
6113
  }
5015
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SeoDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5016
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.1", type: SeoDirective, isStandalone: true, providers: [{ provide: SEO_DIRECTIVE_TOKEN, useExisting: SeoDirective }], ngImport: i0 }); }
6114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SeoDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6115
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: SeoDirective, isStandalone: true, providers: [{ provide: SEO_DIRECTIVE_TOKEN, useExisting: SeoDirective }], ngImport: i0 }); }
5017
6116
  }
5018
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SeoDirective, decorators: [{
6117
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SeoDirective, decorators: [{
5019
6118
  type: Directive,
5020
6119
  args: [{
5021
6120
  providers: [{ provide: SEO_DIRECTIVE_TOKEN, useExisting: SeoDirective }],
@@ -5029,7 +6128,7 @@ const [provideStructuredDataStore, injectStructuredDataStore] = createRootProvid
5029
6128
  const document = inject(DOCUMENT$1);
5030
6129
  const renderer = injectRenderer();
5031
6130
  const config = injectStructuredDataConfig();
5032
- const scripts = signal(new Map(), ...(ngDevMode ? [{ debugName: "scripts" }] : []));
6131
+ const scripts = signal(new Map(), ...(ngDevMode ? [{ debugName: "scripts" }] : /* istanbul ignore next */ []));
5033
6132
  const getTargetElement = () => {
5034
6133
  return config.placement === 'head' ? document.head : document.body;
5035
6134
  };
@@ -5070,7 +6169,7 @@ const applyStructuredDataBinding = (binding) => {
5070
6169
  class StructuredDataComponent {
5071
6170
  constructor() {
5072
6171
  this.sanitizer = inject(DomSanitizer);
5073
- this.data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : []));
6172
+ this.data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
5074
6173
  this.jsonLD = computed(() => {
5075
6174
  const data = this.data();
5076
6175
  if (!data) {
@@ -5079,12 +6178,12 @@ class StructuredDataComponent {
5079
6178
  const json = data ? JSON.stringify(data, null, 2).replace(/<\/script>/g, '<\\/script>') : '';
5080
6179
  const html = `<script type="application/ld+json">${json}</script>`;
5081
6180
  return this.sanitizer.bypassSecurityTrustHtml(html);
5082
- }, ...(ngDevMode ? [{ debugName: "jsonLD" }] : []));
6181
+ }, ...(ngDevMode ? [{ debugName: "jsonLD" }] : /* istanbul ignore next */ []));
5083
6182
  }
5084
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: StructuredDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5085
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.1", type: StructuredDataComponent, isStandalone: true, selector: "et-structured-data", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "innerHTML": "jsonLD()" }, styleAttribute: "display: none" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6183
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: StructuredDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6184
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.13", type: StructuredDataComponent, isStandalone: true, selector: "et-structured-data", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "innerHTML": "jsonLD()" }, styleAttribute: "display: none" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
5086
6185
  }
5087
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: StructuredDataComponent, decorators: [{
6186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: StructuredDataComponent, decorators: [{
5088
6187
  type: Component,
5089
6188
  args: [{
5090
6189
  selector: 'et-structured-data',
@@ -5098,15 +6197,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
5098
6197
  }]
5099
6198
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
5100
6199
 
5101
- const createCssThemeName = (name) => name.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);
6200
+ class ColorInteractiveStylesComponent {
6201
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6202
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: ColorInteractiveStylesComponent, isStandalone: true, selector: "et-color-interactive-styles", ngImport: i0, template: '', isInline: true, styles: [":where(.et-color-interactive:hover:not(:has(.et-color-interactive-exclude:hover))),:where(.et-color-interactive-container:hover) :where(.et-color-interactive){--et-theme-color-primary-rgb: var(--et-color-primary-hover, var(--et-color-primary));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var(--et-color-on-primary-hover, var(--et-color-on-primary));--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-hover, var(--et-color-primary))) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive:focus-visible){--et-theme-color-primary-rgb: var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary)) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)))) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive:active:not(:has(.et-color-interactive-exclude:hover))),:where(.et-color-interactive-container:active) :where(.et-color-interactive){--et-theme-color-primary-rgb: var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) );--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-active, var(--et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary))) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-active, var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var( --et-color-primary-ink, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) ) ) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive--has-focus:has(:focus-visible)){--et-theme-color-primary-rgb: var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary)) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)))) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[disabled]),:where(.et-color-interactive[aria-disabled=true]){--et-theme-color-primary-rgb: var( --et-color-primary-disabled, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) );--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-disabled, var( --et-color-on-primary-active, var(--et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary))) ) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-disabled, var( --et-color-primary-ink-active, var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var( --et-color-primary-ink, var( --et-color-primary-disabled, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) ) ) ) ) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6203
+ }
6204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveStylesComponent, decorators: [{
6205
+ type: Component,
6206
+ args: [{ selector: 'et-color-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":where(.et-color-interactive:hover:not(:has(.et-color-interactive-exclude:hover))),:where(.et-color-interactive-container:hover) :where(.et-color-interactive){--et-theme-color-primary-rgb: var(--et-color-primary-hover, var(--et-color-primary));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var(--et-color-on-primary-hover, var(--et-color-on-primary));--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-hover, var(--et-color-primary))) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive:focus-visible){--et-theme-color-primary-rgb: var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary)) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)))) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive:active:not(:has(.et-color-interactive-exclude:hover))),:where(.et-color-interactive-container:active) :where(.et-color-interactive){--et-theme-color-primary-rgb: var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) );--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-active, var(--et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary))) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-active, var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var( --et-color-primary-ink, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) ) ) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive--has-focus:has(:focus-visible)){--et-theme-color-primary-rgb: var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)));--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary)) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var(--et-color-primary-ink, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)))) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[disabled]),:where(.et-color-interactive[aria-disabled=true]){--et-theme-color-primary-rgb: var( --et-color-primary-disabled, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) );--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: var( --et-color-on-primary-disabled, var( --et-color-on-primary-active, var(--et-color-on-primary-focus, var(--et-color-on-primary-hover, var(--et-color-on-primary))) ) );--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var( --et-color-primary-ink-disabled, var( --et-color-primary-ink-active, var( --et-color-primary-ink-focus, var( --et-color-primary-ink-hover, var( --et-color-primary-ink, var( --et-color-primary-disabled, var( --et-color-primary-active, var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary))) ) ) ) ) ) ) );--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}\n"] }]
6207
+ }] });
6208
+
6209
+ class ColorInteractiveContainerDirective {
6210
+ constructor() {
6211
+ this.styleManager = injectStyleManager();
6212
+ this.styleManager.mount(ColorInteractiveStylesComponent);
6213
+ }
6214
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6215
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ColorInteractiveContainerDirective, isStandalone: true, selector: "[etColorInteractiveContainer]", host: { classAttribute: "et-color-interactive-container" }, ngImport: i0 }); }
6216
+ }
6217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveContainerDirective, decorators: [{
6218
+ type: Directive,
6219
+ args: [{
6220
+ selector: '[etColorInteractiveContainer]',
6221
+ host: {
6222
+ class: 'et-color-interactive-container',
6223
+ },
6224
+ }]
6225
+ }], ctorParameters: () => [] });
6226
+
6227
+ class ColorInteractiveExcludeDirective {
6228
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveExcludeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6229
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ColorInteractiveExcludeDirective, isStandalone: true, selector: "[etColorInteractiveExclude]", host: { classAttribute: "et-color-interactive-exclude" }, ngImport: i0 }); }
6230
+ }
6231
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveExcludeDirective, decorators: [{
6232
+ type: Directive,
6233
+ args: [{
6234
+ selector: '[etColorInteractiveExclude]',
6235
+ host: {
6236
+ class: 'et-color-interactive-exclude',
6237
+ },
6238
+ }]
6239
+ }] });
6240
+
6241
+ class ColorInteractiveHasFocusDirective {
6242
+ constructor() {
6243
+ this.styleManager = injectStyleManager();
6244
+ this.styleManager.mount(ColorInteractiveStylesComponent);
6245
+ }
6246
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveHasFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6247
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ColorInteractiveHasFocusDirective, isStandalone: true, selector: "[etColorInteractiveHasFocus]", host: { classAttribute: "et-color-interactive et-color-interactive--has-focus" }, ngImport: i0 }); }
6248
+ }
6249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveHasFocusDirective, decorators: [{
6250
+ type: Directive,
6251
+ args: [{
6252
+ selector: '[etColorInteractiveHasFocus]',
6253
+ host: {
6254
+ class: 'et-color-interactive et-color-interactive--has-focus',
6255
+ },
6256
+ }]
6257
+ }], ctorParameters: () => [] });
6258
+
6259
+ class ColorInteractiveDirective {
6260
+ constructor() {
6261
+ this.styleManager = injectStyleManager();
6262
+ this.styleManager.mount(ColorInteractiveStylesComponent);
6263
+ }
6264
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6265
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: ColorInteractiveDirective, isStandalone: true, selector: "[etColorInteractive]", host: { classAttribute: "et-color-interactive" }, ngImport: i0 }); }
6266
+ }
6267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ColorInteractiveDirective, decorators: [{
6268
+ type: Directive,
6269
+ args: [{
6270
+ selector: '[etColorInteractive]',
6271
+ host: {
6272
+ class: 'et-color-interactive',
6273
+ },
6274
+ }]
6275
+ }], ctorParameters: () => [] });
6276
+
6277
+ const createCssColorThemeName = (name) => name.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);
5102
6278
  const [ɵProvideColorThemes, injectColorThemes] = createStaticProvider(undefined, {
5103
6279
  name: 'Color Themes',
5104
6280
  });
5105
- const [ɵProvideThemesPrefix, injectThemesPrefix] = createStaticProvider('et', { name: 'Themes Prefix' });
6281
+ const [ɵProvideColorThemesPrefix, injectColorThemesPrefix] = createStaticProvider('et', {
6282
+ name: 'Themes Prefix',
6283
+ });
5106
6284
  const provideColorThemesWithTailwind4 = (themes, prefix = 'et') => [
5107
- ɵProvideColorThemes(themes.map((theme) => theme.name)),
5108
- ɵProvideThemesPrefix(prefix),
6285
+ ɵProvideColorThemes(themes),
6286
+ ɵProvideColorThemesPrefix(prefix),
5109
6287
  ];
6288
+ const injectColorThemeByType = (type) => {
6289
+ const themes = injectColorThemes();
6290
+ if (!themes) {
6291
+ throw new Error(`[injectColorThemeByType] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
6292
+ }
6293
+ const theme = themes.find((t) => t.type === type);
6294
+ if (!theme) {
6295
+ throw new Error(`[injectColorThemeByType] No color theme with type "${type}" found. Add a theme with type: "${type}" to provideColorThemesWithTailwind4().`);
6296
+ }
6297
+ if (isDevMode()) {
6298
+ const duplicates = themes.filter((t) => t.type === type);
6299
+ if (duplicates.length > 1) {
6300
+ console.error(`[injectColorThemeByType] Multiple themes with type "${type}" found: ${duplicates.map((t) => t.name).join(', ')}. Only the first one will be used.`);
6301
+ }
6302
+ }
6303
+ return theme;
6304
+ };
6305
+ const injectErrorTheme = () => injectColorThemeByType('error');
6306
+ const injectWarningTheme = () => injectColorThemeByType('warning');
6307
+ const injectSuccessTheme = () => injectColorThemeByType('success');
5110
6308
 
5111
6309
  /**
5112
6310
  * @deprecated Migrate to Tailwind v4. Intent to remove in v6.
@@ -5114,6 +6312,11 @@ const provideColorThemesWithTailwind4 = (themes, prefix = 'et') => [
5114
6312
  const createSwatchCss = (swatch, isAlt, data) => {
5115
6313
  const varSuffix = isAlt ? 'alt-' + swatch : swatch;
5116
6314
  const varOnSuffix = isAlt ? 'alt-' : '';
6315
+ const inkDefault = data.inkColor?.default || data.color.default;
6316
+ const inkHover = data.inkColor?.hover || inkDefault;
6317
+ const inkFocus = data.inkColor?.focus || data.inkColor?.hover || inkDefault;
6318
+ const inkActive = data.inkColor?.active || inkDefault;
6319
+ const inkDisabled = data.inkColor?.disabled || inkDefault;
5117
6320
  return `
5118
6321
  --et-color-${varSuffix}: ${data.color.default};
5119
6322
  --et-color-${varSuffix}-hover: ${data.color.hover};
@@ -5126,6 +6329,12 @@ const createSwatchCss = (swatch, isAlt, data) => {
5126
6329
  --et-color-${varOnSuffix}on-${swatch}-focus: ${data.onColor.focus || data.onColor.hover || data.onColor.default};
5127
6330
  --et-color-${varOnSuffix}on-${swatch}-active: ${data.onColor.active || data.onColor.default};
5128
6331
  --et-color-${varOnSuffix}on-${swatch}-disabled: ${data.onColor.disabled || data.onColor.default};
6332
+
6333
+ --et-color-${varSuffix}-ink: ${inkDefault};
6334
+ --et-color-${varSuffix}-ink-hover: ${inkHover};
6335
+ --et-color-${varSuffix}-ink-focus: ${inkFocus};
6336
+ --et-color-${varSuffix}-ink-active: ${inkActive};
6337
+ --et-color-${varSuffix}-ink-disabled: ${inkDisabled};
5129
6338
  `;
5130
6339
  };
5131
6340
  /**
@@ -5133,6 +6342,11 @@ const createSwatchCss = (swatch, isAlt, data) => {
5133
6342
  */
5134
6343
  const createRootThemeCss = (themes) => {
5135
6344
  const createVars = (name, swatch) => {
6345
+ const inkDefault = swatch.inkColor?.default || swatch.color.default;
6346
+ const inkHover = swatch.inkColor?.hover || inkDefault;
6347
+ const inkFocus = swatch.inkColor?.focus || swatch.inkColor?.hover || inkDefault;
6348
+ const inkActive = swatch.inkColor?.active || inkDefault;
6349
+ const inkDisabled = swatch.inkColor?.disabled || inkDefault;
5136
6350
  return `
5137
6351
  --et-color-${name}: ${swatch.color.default};
5138
6352
  --et-color-${name}-hover: ${swatch.color.hover};
@@ -5145,11 +6359,17 @@ const createRootThemeCss = (themes) => {
5145
6359
  --et-color-on-${name}-focus: ${swatch.onColor.focus || swatch.onColor.hover || swatch.onColor.default};
5146
6360
  --et-color-on-${name}-active: ${swatch.onColor.active || swatch.onColor.default};
5147
6361
  --et-color-on-${name}-disabled: ${swatch.onColor.disabled || swatch.onColor.default};
6362
+
6363
+ --et-color-${name}-ink: ${inkDefault};
6364
+ --et-color-${name}-ink-hover: ${inkHover};
6365
+ --et-color-${name}-ink-focus: ${inkFocus};
6366
+ --et-color-${name}-ink-active: ${inkActive};
6367
+ --et-color-${name}-ink-disabled: ${inkDisabled};
5148
6368
  `;
5149
6369
  };
5150
6370
  const vars = [];
5151
6371
  for (const theme of themes) {
5152
- const name = createCssThemeName(theme.name);
6372
+ const name = createCssColorThemeName(theme.name);
5153
6373
  if (theme.secondary || theme.tertiary) {
5154
6374
  vars.push(createVars(`${name}-primary`, theme.primary));
5155
6375
  if (theme.secondary) {
@@ -5177,7 +6397,7 @@ const createRootThemeCss = (themes) => {
5177
6397
  * @deprecated Migrate to Tailwind v4. Intent to remove in v6.
5178
6398
  */
5179
6399
  const createThemeStyle = (theme, isAlt) => {
5180
- const cssThemeName = createCssThemeName(theme.name);
6400
+ const cssThemeName = createCssColorThemeName(theme.name);
5181
6401
  const stringSuffix = isAlt ? '-alt' : '';
5182
6402
  const selectors = [
5183
6403
  ...((theme.isDefault && !isAlt) || (theme.isDefaultAlt && isAlt)
@@ -5229,6 +6449,23 @@ const createTailwindColorThemes = (themes, prefix = 'et') => {
5229
6449
  active: createTailwindRgbVar(theme.primary.onColor.active) || createTailwindRgbVar(theme.primary.onColor.default),
5230
6450
  disabled: createTailwindRgbVar(theme.primary.onColor.disabled) || createTailwindRgbVar(theme.primary.onColor.default),
5231
6451
  };
6452
+ const keyInk = `${prefix}-${theme.name}-ink`;
6453
+ twThemes[keyInk] = {
6454
+ DEFAULT: createTailwindRgbVar(theme.primary.inkColor?.default) || createTailwindRgbVar(theme.primary.color.default),
6455
+ hover: createTailwindRgbVar(theme.primary.inkColor?.hover) ||
6456
+ createTailwindRgbVar(theme.primary.inkColor?.default) ||
6457
+ createTailwindRgbVar(theme.primary.color.default),
6458
+ focus: createTailwindRgbVar(theme.primary.inkColor?.focus) ||
6459
+ createTailwindRgbVar(theme.primary.inkColor?.hover) ||
6460
+ createTailwindRgbVar(theme.primary.inkColor?.default) ||
6461
+ createTailwindRgbVar(theme.primary.color.default),
6462
+ active: createTailwindRgbVar(theme.primary.inkColor?.active) ||
6463
+ createTailwindRgbVar(theme.primary.inkColor?.default) ||
6464
+ createTailwindRgbVar(theme.primary.color.default),
6465
+ disabled: createTailwindRgbVar(theme.primary.inkColor?.disabled) ||
6466
+ createTailwindRgbVar(theme.primary.inkColor?.default) ||
6467
+ createTailwindRgbVar(theme.primary.color.default),
6468
+ };
5232
6469
  }
5233
6470
  return twThemes;
5234
6471
  };
@@ -5254,82 +6491,250 @@ const provideColorThemes = (themes) => {
5254
6491
  createThemeStyle(theme, true);
5255
6492
  }
5256
6493
  createRootThemeCss(themes);
5257
- return [ɵProvideColorThemes(themes.map((theme) => theme.name)), ɵProvideThemesPrefix('et')];
6494
+ return [ɵProvideColorThemes(themes), ɵProvideColorThemesPrefix('et')];
5258
6495
  };
5259
6496
 
5260
- const THEME_PROVIDER = new InjectionToken('ThemeProvider');
5261
- class ProvideThemeDirective {
6497
+ const COLOR_PROVIDER = new InjectionToken('ColorProvider');
6498
+ const FORCED_COLOR_UNSET = Symbol('FORCED_COLOR_UNSET');
6499
+ class ProvideColorDirective {
5262
6500
  constructor() {
5263
6501
  this.themes = injectColorThemes({ optional: true });
5264
- this.prefix = injectThemesPrefix({ optional: true });
6502
+ this.prefix = injectColorThemesPrefix({ optional: true });
5265
6503
  this.injector = inject(Injector);
5266
6504
  this.currentProviderSync = null;
5267
- this.mainTheme = input(undefined, { ...(ngDevMode ? { debugName: "mainTheme" } : {}), alias: 'etProvideTheme' });
5268
- this.altTheme = input(undefined, { ...(ngDevMode ? { debugName: "altTheme" } : {}), alias: 'etProvideAltTheme' });
5269
- this.mainThemeName = computed(() => {
5270
- const value = this.mainTheme();
5271
- if (!this.themes || !value)
5272
- return;
5273
- if (isDevMode() && !this.themes?.some((theme) => theme === value) && value !== null) {
5274
- console.error(`Theme ${value} does not exist. Please make sure to add it to provideColorThemes()`);
6505
+ this.forcedColor = signal(FORCED_COLOR_UNSET, ...(ngDevMode ? [{ debugName: "forcedColor" }] : /* istanbul ignore next */ []));
6506
+ this.color = input(undefined, { ...(ngDevMode ? { debugName: "color" } : /* istanbul ignore next */ {}), alias: 'etProvideColor' });
6507
+ this.effectiveColor = computed(() => {
6508
+ const forcedColor = this.forcedColor();
6509
+ if (forcedColor !== FORCED_COLOR_UNSET) {
6510
+ return forcedColor;
5275
6511
  }
5276
- return createCssThemeName(value);
5277
- }, ...(ngDevMode ? [{ debugName: "mainThemeName" }] : []));
5278
- this.altThemeName = computed(() => {
5279
- const value = this.altTheme();
6512
+ return this.color();
6513
+ }, ...(ngDevMode ? [{ debugName: "effectiveColor" }] : /* istanbul ignore next */ []));
6514
+ this.colorName = computed(() => {
6515
+ const raw = this.effectiveColor();
6516
+ const value = typeof raw === 'object' && raw !== null ? raw.name : raw;
5280
6517
  if (!this.themes || !value)
5281
6518
  return;
5282
- if (isDevMode() && !this.themes?.some((theme) => theme === value) && value !== null) {
5283
- console.warn(`Theme ${value} does not exist. Please make sure to add it to provideColorThemes()`);
6519
+ if (isDevMode() && !this.themes.some((theme) => theme.name === value) && value !== null) {
6520
+ console.error(`Theme ${value} does not exist. Please make sure to add it to provideColorThemesWithTailwind4()`);
5284
6521
  }
5285
- return createCssThemeName(value);
5286
- }, ...(ngDevMode ? [{ debugName: "altThemeName" }] : []));
6522
+ return createCssColorThemeName(value);
6523
+ }, ...(ngDevMode ? [{ debugName: "colorName" }] : /* istanbul ignore next */ []));
5287
6524
  this.themeClass = computed(() => {
5288
- const themes = [];
5289
6525
  const prefix = this.prefix || 'et';
5290
- if (this.mainThemeName()) {
5291
- themes.push(`${prefix}-theme--${this.mainThemeName()}`);
5292
- }
5293
- if (this.altThemeName()) {
5294
- themes.push(`${prefix}-theme-alt--${this.altThemeName()}`);
6526
+ if (this.colorName()) {
6527
+ return `${prefix}-color--${this.colorName()}`;
5295
6528
  }
5296
- return themes.join(' ');
5297
- }, ...(ngDevMode ? [{ debugName: "themeClass" }] : []));
6529
+ return `${prefix}-color--inherited`;
6530
+ }, ...(ngDevMode ? [{ debugName: "themeClass" }] : /* istanbul ignore next */ []));
5298
6531
  }
5299
6532
  syncWithProvider(provider) {
5300
6533
  this.currentProviderSync?.destroy();
5301
6534
  runInInjectionContext(this.injector, () => {
5302
6535
  this.currentProviderSync = effect(() => {
5303
- const provideMainTheme = provider.mainTheme();
5304
- const provideAltTheme = provider.altTheme();
6536
+ const provideColor = provider.effectiveColor();
5305
6537
  untracked(() => {
5306
- setInputSignal(this.mainTheme, provideMainTheme);
5307
- setInputSignal(this.altTheme, provideAltTheme);
6538
+ if (provideColor === undefined) {
6539
+ this.clearForcedColor();
6540
+ return;
6541
+ }
6542
+ this.forceColor(provideColor);
5308
6543
  });
5309
- }, ...(ngDevMode ? [{ debugName: "currentProviderSync" }] : []));
6544
+ }, ...(ngDevMode ? [{ debugName: "currentProviderSync" }] : /* istanbul ignore next */ []));
5310
6545
  });
5311
6546
  }
5312
6547
  stopSyncWithProvider() {
6548
+ const hadProviderSync = !!this.currentProviderSync;
5313
6549
  this.currentProviderSync?.destroy();
5314
6550
  this.currentProviderSync = null;
6551
+ if (hadProviderSync) {
6552
+ this.clearForcedColor();
6553
+ }
6554
+ }
6555
+ /** @internal */
6556
+ forceColor(color) {
6557
+ this.forcedColor.set(color);
6558
+ }
6559
+ /** @internal */
6560
+ clearForcedColor() {
6561
+ if (this.forcedColor() === FORCED_COLOR_UNSET) {
6562
+ return;
6563
+ }
6564
+ this.forcedColor.set(FORCED_COLOR_UNSET);
5315
6565
  }
5316
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ProvideThemeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5317
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: ProvideThemeDirective, isStandalone: true, selector: "[etProvideTheme]", inputs: { mainTheme: { classPropertyName: "mainTheme", publicName: "etProvideTheme", isSignal: true, isRequired: false, transformFunction: null }, altTheme: { classPropertyName: "altTheme", publicName: "etProvideAltTheme", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "themeClass()" } }, providers: [{ provide: THEME_PROVIDER, useExisting: ProvideThemeDirective }], ngImport: i0 }); }
6566
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ProvideColorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6567
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: ProvideColorDirective, isStandalone: true, selector: "[etProvideColor]", inputs: { color: { classPropertyName: "color", publicName: "etProvideColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "themeClass()" } }, providers: [{ provide: COLOR_PROVIDER, useExisting: ProvideColorDirective }], ngImport: i0 }); }
5318
6568
  }
5319
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ProvideThemeDirective, decorators: [{
6569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ProvideColorDirective, decorators: [{
5320
6570
  type: Directive,
5321
6571
  args: [{
5322
- selector: '[etProvideTheme]',
5323
- providers: [{ provide: THEME_PROVIDER, useExisting: ProvideThemeDirective }],
6572
+ selector: '[etProvideColor]',
6573
+ providers: [{ provide: COLOR_PROVIDER, useExisting: ProvideColorDirective }],
5324
6574
  host: {
5325
6575
  '[class]': 'themeClass()',
5326
6576
  },
5327
6577
  }]
5328
- }], propDecorators: { mainTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "etProvideTheme", required: false }] }], altTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "etProvideAltTheme", required: false }] }] } });
6578
+ }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "etProvideColor", required: false }] }] } });
6579
+
6580
+ const SURFACE_TYPE = {
6581
+ LIGHT: 'light',
6582
+ DARK: 'dark',
6583
+ };
6584
+ const createCssSurfaceName = (name) => name.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);
6585
+ const resolveSurfaceByElevation = (themes, type, elevation) => themes.find((t) => t.type === type && t.elevation === elevation) ?? null;
6586
+ const [ɵProvideSurfaceThemes, injectSurfaceThemes] = createStaticProvider(undefined, {
6587
+ name: 'Surface Themes',
6588
+ });
6589
+ const [ɵProvideSurfaceThemesPrefix, injectSurfaceThemesPrefix] = createStaticProvider('et', {
6590
+ name: 'Surface Themes Prefix',
6591
+ });
6592
+ const provideSurfaceThemesWithTailwind4 = (themes, prefix = 'et') => [
6593
+ ɵProvideSurfaceThemes(themes),
6594
+ ɵProvideSurfaceThemesPrefix(prefix),
6595
+ ];
6596
+
6597
+ const SURFACE_PROVIDER = new InjectionToken('SurfaceProvider');
6598
+ const FORCED_SURFACE_UNSET = Symbol('FORCED_SURFACE_UNSET');
6599
+ class ProvideSurfaceDirective {
6600
+ constructor() {
6601
+ this.themes = injectSurfaceThemes({ optional: true });
6602
+ this.prefix = injectSurfaceThemesPrefix({ optional: true });
6603
+ this.injector = inject(Injector);
6604
+ this.currentProviderSync = null;
6605
+ this.forcedSurface = signal(FORCED_SURFACE_UNSET, ...(ngDevMode ? [{ debugName: "forcedSurface" }] : /* istanbul ignore next */ []));
6606
+ this.surface = input(undefined, { ...(ngDevMode ? { debugName: "surface" } : /* istanbul ignore next */ {}), alias: 'etProvideSurface' });
6607
+ this.effectiveSurface = computed(() => {
6608
+ const forcedSurface = this.forcedSurface();
6609
+ if (forcedSurface !== FORCED_SURFACE_UNSET) {
6610
+ return forcedSurface;
6611
+ }
6612
+ return this.surface();
6613
+ }, ...(ngDevMode ? [{ debugName: "effectiveSurface" }] : /* istanbul ignore next */ []));
6614
+ this.resolvedTheme = computed(() => {
6615
+ const value = this.effectiveSurface();
6616
+ if (!this.themes || !value)
6617
+ return null;
6618
+ const theme = this.themes.find((t) => t.name === value) ?? null;
6619
+ if (isDevMode() && !theme && value !== null) {
6620
+ console.error(`Surface theme ${value} does not exist. Please make sure to add it to provideSurfaceThemesWithTailwind4()`);
6621
+ }
6622
+ return theme;
6623
+ }, ...(ngDevMode ? [{ debugName: "resolvedTheme" }] : /* istanbul ignore next */ []));
6624
+ this.elevation = computed(() => this.resolvedTheme()?.elevation ?? 0, ...(ngDevMode ? [{ debugName: "elevation" }] : /* istanbul ignore next */ []));
6625
+ this.surfaceType = computed(() => this.resolvedTheme()?.type ?? null, ...(ngDevMode ? [{ debugName: "surfaceType" }] : /* istanbul ignore next */ []));
6626
+ this.surfaceName = computed(() => {
6627
+ const value = this.effectiveSurface();
6628
+ if (!this.themes || !value)
6629
+ return;
6630
+ return createCssSurfaceName(value);
6631
+ }, ...(ngDevMode ? [{ debugName: "surfaceName" }] : /* istanbul ignore next */ []));
6632
+ this.surfaceClass = computed(() => {
6633
+ const prefix = this.prefix || 'et';
6634
+ if (this.surfaceName()) {
6635
+ return `${prefix}-surface--${this.surfaceName()}`;
6636
+ }
6637
+ return `${prefix}-surface--inherited`;
6638
+ }, ...(ngDevMode ? [{ debugName: "surfaceClass" }] : /* istanbul ignore next */ []));
6639
+ }
6640
+ syncWithProvider(provider) {
6641
+ this.currentProviderSync?.destroy();
6642
+ runInInjectionContext(this.injector, () => {
6643
+ this.currentProviderSync = effect(() => {
6644
+ const provideSurface = provider.effectiveSurface();
6645
+ untracked(() => {
6646
+ if (provideSurface === undefined) {
6647
+ this.clearForcedSurface();
6648
+ return;
6649
+ }
6650
+ this.forceSurface(provideSurface);
6651
+ });
6652
+ }, ...(ngDevMode ? [{ debugName: "currentProviderSync" }] : /* istanbul ignore next */ []));
6653
+ });
6654
+ }
6655
+ stopSyncWithProvider() {
6656
+ const hadProviderSync = !!this.currentProviderSync;
6657
+ this.currentProviderSync?.destroy();
6658
+ this.currentProviderSync = null;
6659
+ if (hadProviderSync) {
6660
+ this.clearForcedSurface();
6661
+ }
6662
+ }
6663
+ /** @internal */
6664
+ forceSurface(surface) {
6665
+ this.forcedSurface.set(surface);
6666
+ }
6667
+ /** @internal */
6668
+ clearForcedSurface() {
6669
+ if (this.forcedSurface() === FORCED_SURFACE_UNSET) {
6670
+ return;
6671
+ }
6672
+ this.forcedSurface.set(FORCED_SURFACE_UNSET);
6673
+ }
6674
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ProvideSurfaceDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6675
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: ProvideSurfaceDirective, isStandalone: true, selector: "[etProvideSurface]", inputs: { surface: { classPropertyName: "surface", publicName: "etProvideSurface", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "surfaceClass()" } }, providers: [{ provide: SURFACE_PROVIDER, useExisting: ProvideSurfaceDirective }], ngImport: i0 }); }
6676
+ }
6677
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ProvideSurfaceDirective, decorators: [{
6678
+ type: Directive,
6679
+ args: [{
6680
+ selector: '[etProvideSurface]',
6681
+ providers: [{ provide: SURFACE_PROVIDER, useExisting: ProvideSurfaceDirective }],
6682
+ host: {
6683
+ '[class]': 'surfaceClass()',
6684
+ },
6685
+ }]
6686
+ }], propDecorators: { surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "etProvideSurface", required: false }] }] } });
6687
+
6688
+ let uniqueId = 0;
6689
+ const [provideSurfaceContextTracker, injectSurfaceContextTracker] = createRootProvider(() => {
6690
+ const entries = signal([], ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
6691
+ const topEntry = computed(() => {
6692
+ const stack = entries();
6693
+ return stack.length > 0 ? (stack[stack.length - 1] ?? null) : null;
6694
+ }, ...(ngDevMode ? [{ debugName: "topEntry" }] : /* istanbul ignore next */ []));
6695
+ const topType = computed(() => topEntry()?.type ?? null, ...(ngDevMode ? [{ debugName: "topType" }] : /* istanbul ignore next */ []));
6696
+ const topElevation = computed(() => topEntry()?.elevation ?? 0, ...(ngDevMode ? [{ debugName: "topElevation" }] : /* istanbul ignore next */ []));
6697
+ const register = (type, elevation) => {
6698
+ const id = `surface-ctx-${uniqueId++}`;
6699
+ const entry = { id, type, elevation };
6700
+ entries.update((e) => [...e, entry]);
6701
+ return () => {
6702
+ entries.update((e) => e.filter((item) => item.id !== id));
6703
+ };
6704
+ };
6705
+ return { topType, topElevation, register };
6706
+ }, { name: 'SurfaceContextTracker' });
6707
+
6708
+ class SurfaceInteractiveStylesComponent {
6709
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SurfaceInteractiveStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6710
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: SurfaceInteractiveStylesComponent, isStandalone: true, selector: "et-surface-interactive-styles", ngImport: i0, template: '', isInline: true, styles: [":where(.et-surface-interactive){--et-surface-interaction-rgb: var(--et-surface-interaction);--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:hover){--et-surface-interaction-rgb: var(--et-surface-interaction-hover, var(--et-surface-interaction));--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:focus-visible){--et-surface-interaction-rgb: var( --et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction)) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:active){--et-surface-interaction-rgb: var( --et-surface-interaction-active, var(--et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction))) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive[disabled]),:where(.et-surface-interactive[aria-disabled=true]){--et-surface-interaction-rgb: var( --et-surface-interaction-disabled, var( --et-surface-interaction-active, var(--et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction))) ) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6711
+ }
6712
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SurfaceInteractiveStylesComponent, decorators: [{
6713
+ type: Component,
6714
+ args: [{ selector: 'et-surface-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":where(.et-surface-interactive){--et-surface-interaction-rgb: var(--et-surface-interaction);--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:hover){--et-surface-interaction-rgb: var(--et-surface-interaction-hover, var(--et-surface-interaction));--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:focus-visible){--et-surface-interaction-rgb: var( --et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction)) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive:active){--et-surface-interaction-rgb: var( --et-surface-interaction-active, var(--et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction))) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}:where(.et-surface-interactive[disabled]),:where(.et-surface-interactive[aria-disabled=true]){--et-surface-interaction-rgb: var( --et-surface-interaction-disabled, var( --et-surface-interaction-active, var(--et-surface-interaction-focus, var(--et-surface-interaction-hover, var(--et-surface-interaction))) ) );--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}\n"] }]
6715
+ }] });
6716
+
6717
+ class SurfaceInteractiveDirective {
6718
+ constructor() {
6719
+ this.styleManager = injectStyleManager();
6720
+ this.styleManager.mount(SurfaceInteractiveStylesComponent);
6721
+ }
6722
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SurfaceInteractiveDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6723
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: SurfaceInteractiveDirective, isStandalone: true, selector: "[etSurfaceInteractive]", host: { classAttribute: "et-surface-interactive" }, ngImport: i0 }); }
6724
+ }
6725
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: SurfaceInteractiveDirective, decorators: [{
6726
+ type: Directive,
6727
+ args: [{
6728
+ selector: '[etSurfaceInteractive]',
6729
+ host: {
6730
+ class: 'et-surface-interactive',
6731
+ },
6732
+ }]
6733
+ }], ctorParameters: () => [] });
5329
6734
 
5330
6735
  /**
5331
6736
  * Generated bundle index. Do not edit.
5332
6737
  */
5333
6738
 
5334
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, BOUNDARY_ELEMENT_TOKEN, ClickOutsideDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUS_VISIBLE_TRACKER_TOKEN, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideThemeDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, RuntimeError, SEO_DIRECTIVE_TOKEN, SeoDirective, StructuredDataComponent, THEME_PROVIDER, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyDescriptionBinding, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boundingClientRectToElementRect, buildElementSignal, buildSignalEffects, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, createArrayPropertyBinding, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssThemeName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRxHostListener, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, deferredSignal, deleteCookie, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, hasCookie, inferMimeType, injectAngularRootElement, injectBoundaryElement, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectPathParam, injectPathParamChanges, injectPathParams, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectTemplateRef, injectThemesPrefix, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, isArray, isElementSignal, isElementVisible, isGroupMatch, isKnockoutMatch, isObject, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, previousSignalValue, provideBoundaryElement, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideTitleConfig, provideTitleStore, provideViewportConfig, round, routerDisableScrollTop, scrollToElement, setCookie, setInputSignal, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideThemesPrefix };
6739
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PROVIDER, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RuntimeError, SEO_DIRECTIVE_TOKEN, SURFACE_PROVIDER, SURFACE_TYPE, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SeoDirective, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRxHostListener, createSessionMemory, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUserConsentProvider, deferredSignal, deleteCookie, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, inferMimeType, injectAngularRootElement, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideViewportConfig, resolveSurfaceByElevation, round, routerDisableScrollTop, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
5335
6740
  //# sourceMappingURL=ethlete-core.mjs.map