@ethlete/core 5.0.0-next.53 → 5.0.0-next.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, RendererFactory2, RendererStyleFlags2, isSignal, DOCUMENT, signal, linkedSignal, isDevMode, computed, afterNextRender, effect, NgZone, untracked, EnvironmentInjector, runInInjectionContext, Injector, booleanAttribute, numberAttribute, PLATFORM_ID, ApplicationRef, createComponent, model, ViewContainerRef, input, ViewEncapsulation, Component, provideEnvironmentInitializer, output, Pipe, afterEveryRender } from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, isDevMode, Directive, assertInInjectionContext, DestroyRef, TemplateRef, QueryList, RendererFactory2, RendererStyleFlags2, isSignal, DOCUMENT, signal, linkedSignal, computed, afterNextRender, effect, untracked, EnvironmentInjector, runInInjectionContext, NgZone, Injector, booleanAttribute, numberAttribute, PLATFORM_ID, ApplicationRef, createComponent, model, ViewContainerRef, input, ViewEncapsulation, Component, provideEnvironmentInitializer, output, createEnvironmentInjector, Pipe, afterEveryRender } from '@angular/core';
3
3
  import { takeUntilDestroyed, toSignal, toObservable, outputFromObservable } from '@angular/core/rxjs-interop';
4
4
  import { Subject, BehaviorSubject, debounceTime, combineLatest, map, merge, fromEvent, filter, tap, switchMap, startWith, of, defer, from, catchError, timer, takeUntil, pairwise, distinctUntilChanged, EMPTY, take, Observable, isObservable, firstValueFrom, defaultIfEmpty, concatMap, concat, finalize, exhaustMap, share, shareReplay } from 'rxjs';
5
5
  import { FormGroup, FormArray, FormControl } from '@angular/forms';
6
6
  import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
7
- import { DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
7
+ import { isPlatformBrowser, DOCUMENT as DOCUMENT$1 } from '@angular/common';
8
8
  import { Router, NavigationEnd, NavigationSkipped, NavigationStart, NavigationError, RouterLink } from '@angular/router';
9
9
  import { Title, Meta, DomSanitizer } from '@angular/platform-browser';
10
10
  import { offset, flip, shift, limitShift, computePosition, autoUpdate, hide, arrow, size } from '@floating-ui/dom';
@@ -83,7 +83,9 @@ class AnimatableDirective {
83
83
  }
84
84
  else {
85
85
  animationDebugLog(`animatable ${el.tagName.toLowerCase()}`, `${eventType} ignored - count already 0 (start ${didEmitStart ? '' : 'not '}emitted)`);
86
- console.warn(`${el.tagName} received animation end/cancel event but activeAnimationCount is already 0. Start was ${didEmitStart ? '' : 'not '}emitted.`);
86
+ if (isDevMode()) {
87
+ console.warn(`${el.tagName} received animation end/cancel event but activeAnimationCount is already 0. Start was ${didEmitStart ? '' : 'not '}emitted.`);
88
+ }
87
89
  }
88
90
  break;
89
91
  }
@@ -277,59 +279,40 @@ const maybeMergeValues = (defaultValue, valueOverride) => {
277
279
  };
278
280
 
279
281
  const cloneFormGroup = (formGroup) => {
280
- const cloneLevel = (group, cloneGroup) => {
281
- Object.entries(group.controls).forEach(([key, control]) => {
282
- if (control instanceof FormGroup) {
283
- const cloneControl = new FormGroup({}, control.validator, control.asyncValidator);
284
- cloneGroup.addControl(key, cloneControl);
285
- cloneLevel(control, cloneControl);
286
- }
287
- else if (control instanceof FormArray) {
288
- const cloneArrayControl = new FormArray([], control.validator, control.asyncValidator);
289
- control.controls.forEach((control) => {
290
- if (control instanceof FormGroup) {
291
- const cloneControl = new FormGroup({}, control.validator, control.asyncValidator);
292
- const innerClone = cloneLevel(control, cloneControl);
293
- cloneArrayControl.push(innerClone);
294
- }
295
- else {
296
- const cloneControlItem = new FormControl({ value: control.value, disabled: control.disabled }, control.validator, control.asyncValidator);
297
- cloneArrayControl.push(cloneControlItem);
298
- }
299
- });
300
- cloneGroup.addControl(key, cloneArrayControl);
301
- }
302
- else {
303
- const cloneControl = new FormControl({ value: control.value, disabled: control.disabled }, control.validator, control.asyncValidator);
304
- cloneGroup.addControl(key, cloneControl);
305
- }
306
- });
307
- return cloneGroup;
282
+ const cloneControl = (control) => {
283
+ let clonedControl;
284
+ if (control instanceof FormGroup) {
285
+ const controls = Object.fromEntries(Object.entries(control.controls).map(([key, child]) => [key, cloneControl(child)]));
286
+ clonedControl = new FormGroup(controls, control.validator, control.asyncValidator);
287
+ }
288
+ else if (control instanceof FormArray) {
289
+ clonedControl = new FormArray(control.controls.map((child) => cloneControl(child)), control.validator, control.asyncValidator);
290
+ }
291
+ else {
292
+ clonedControl = new FormControl({ value: control.value, disabled: control.disabled }, control.validator, control.asyncValidator);
293
+ }
294
+ if (control.disabled && clonedControl.enabled) {
295
+ clonedControl.disable({ emitEvent: false });
296
+ }
297
+ return clonedControl;
308
298
  };
309
- const clonedForm = cloneLevel(formGroup, new FormGroup({}));
310
- clonedForm.setValue(formGroup.value);
299
+ const clonedForm = cloneControl(formGroup);
311
300
  clonedForm.updateValueAndValidity();
312
301
  return clonedForm;
313
302
  };
314
303
  const getFormGroupValue = (formGroup) => {
315
- const value = {};
316
- Object.entries(formGroup.controls).forEach(([key, control]) => {
304
+ const getControlValue = (control) => {
317
305
  if (control instanceof FormGroup) {
318
- value[key] = getFormGroupValue(control);
306
+ return getFormGroupValue(control);
319
307
  }
320
- else if (control instanceof FormArray) {
321
- value[key] = control.controls.map((control) => {
322
- if (control instanceof FormGroup) {
323
- return getFormGroupValue(control);
324
- }
325
- else {
326
- return control.value ?? null;
327
- }
328
- });
329
- }
330
- else {
331
- value[key] = control.value ?? null;
308
+ if (control instanceof FormArray) {
309
+ return control.controls.map(getControlValue);
332
310
  }
311
+ return control.value ?? null;
312
+ };
313
+ const value = {};
314
+ Object.entries(formGroup.controls).forEach(([key, control]) => {
315
+ value[key] = getControlValue(control);
333
316
  });
334
317
  return value;
335
318
  };
@@ -393,7 +376,7 @@ const ValidateAtLeastOneRequired = (config) => {
393
376
  const IS_ARRAY_NOT_EMPTY = 'isArrayNotEmpty';
394
377
  const IsArrayNotEmpty = (control) => {
395
378
  const value = control.value;
396
- if (!value) {
379
+ if (!Array.isArray(value)) {
397
380
  return null;
398
381
  }
399
382
  return value.length > 0 ? null : { [IS_ARRAY_NOT_EMPTY]: true };
@@ -404,7 +387,10 @@ const IsEmail = (control) => {
404
387
  if (!value) {
405
388
  return null;
406
389
  }
407
- const regex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/;
390
+ if (typeof value !== 'string') {
391
+ return null;
392
+ }
393
+ const regex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/i;
408
394
  return regex.test(value) ? null : { [IS_EMAIL]: true };
409
395
  };
410
396
  const MUST_MATCH = 'mustMatch';
@@ -412,20 +398,13 @@ const MustMatch = (controlName, matchingControlName) => {
412
398
  return (formGroup) => {
413
399
  const control = formGroup.get(controlName);
414
400
  const matchingControl = formGroup.get(matchingControlName);
415
- if (matchingControl?.errors && !matchingControl.errors[MUST_MATCH]) {
416
- return null;
417
- }
418
401
  if (control?.value !== matchingControl?.value) {
419
- matchingControl?.setErrors({ [MUST_MATCH]: true });
420
402
  return { [MUST_MATCH]: true };
421
403
  }
422
- else {
423
- matchingControl?.setErrors(null);
424
- return null;
425
- }
404
+ return null;
426
405
  };
427
406
  };
428
- const Validators = {
407
+ const EthleteValidators = {
429
408
  MustMatch,
430
409
  IsEmail,
431
410
  IsArrayNotEmpty,
@@ -490,18 +469,23 @@ const copyToClipboardViaExecCommand = (text) => {
490
469
  *
491
470
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
492
471
  */
493
- const set = (obj, key, val) => {
494
- if (typeof val.value === 'object')
495
- val.value = clone(val.value);
472
+ const set = (obj, key, val, seen) => {
473
+ if (typeof val.value === 'object' && val.value !== null)
474
+ val.value = cloneValue(val.value, seen);
496
475
  if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {
497
476
  Object.defineProperty(obj, key, val);
498
477
  }
499
478
  else
500
479
  obj[key] = val.value;
501
480
  };
502
- const clone = (original) => {
481
+ const cloneValue = (original, seen) => {
503
482
  if (typeof original !== 'object')
504
483
  return original;
484
+ if (original === null)
485
+ return original;
486
+ const existing = seen.get(original);
487
+ if (existing)
488
+ return existing;
505
489
  var _og = original;
506
490
  var i = 0;
507
491
  var k;
@@ -509,21 +493,23 @@ const clone = (original) => {
509
493
  var tmp;
510
494
  var str = Object.prototype.toString.call(_og);
511
495
  if (str === '[object Object]') {
512
- tmp = Object.create(_og.__proto__ || null);
496
+ tmp = Object.create(Object.getPrototypeOf(_og));
513
497
  }
514
498
  else if (str === '[object Array]') {
515
499
  tmp = Array(_og.length);
516
500
  }
517
501
  else if (str === '[object Set]') {
518
502
  tmp = new Set();
503
+ seen.set(_og, tmp);
519
504
  _og.forEach(function (val) {
520
- tmp.add(clone(val));
505
+ tmp.add(cloneValue(val, seen));
521
506
  });
522
507
  }
523
508
  else if (str === '[object Map]') {
524
509
  tmp = new Map();
510
+ seen.set(_og, tmp);
525
511
  _og.forEach(function (val, key) {
526
- tmp.set(clone(key), clone(val));
512
+ tmp.set(cloneValue(key, seen), cloneValue(val, seen));
527
513
  });
528
514
  }
529
515
  else if (str === '[object Date]') {
@@ -533,7 +519,7 @@ const clone = (original) => {
533
519
  tmp = new RegExp(_og.source, _og.flags);
534
520
  }
535
521
  else if (str === '[object DataView]') {
536
- tmp = new _og.constructor(clone(_og.buffer));
522
+ tmp = new _og.constructor(cloneValue(_og.buffer, seen));
537
523
  }
538
524
  else if (str === '[object ArrayBuffer]') {
539
525
  tmp = _og.slice(0);
@@ -542,17 +528,19 @@ const clone = (original) => {
542
528
  tmp = new _og.constructor(_og);
543
529
  }
544
530
  if (tmp) {
531
+ seen.set(_og, tmp);
545
532
  for (list = Object.getOwnPropertySymbols(_og); i < list.length; i++) {
546
- set(tmp, list[i], Object.getOwnPropertyDescriptor(_og, list[i]));
533
+ set(tmp, list[i], Object.getOwnPropertyDescriptor(_og, list[i]), seen);
547
534
  }
548
535
  for (i = 0, list = Object.getOwnPropertyNames(_og); i < list.length; i++) {
549
536
  if (Object.hasOwnProperty.call(tmp, (k = list[i])) && tmp[k] === _og[k])
550
537
  continue;
551
- set(tmp, k, Object.getOwnPropertyDescriptor(_og, k));
538
+ set(tmp, k, Object.getOwnPropertyDescriptor(_og, k), seen);
552
539
  }
553
540
  }
554
541
  return tmp || _og;
555
542
  };
543
+ const clone = (original) => cloneValue(original, new WeakMap());
556
544
  /**
557
545
  * Stolen from dequal to avoid adding a dependency
558
546
  * https://github.com/lukeed/dequal
@@ -592,7 +580,12 @@ const equal = (foo, bar) => {
592
580
  var tmp;
593
581
  if (foo === bar)
594
582
  return true;
595
- if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
583
+ if (foo &&
584
+ bar &&
585
+ ((ctor = foo.constructor) === bar.constructor ||
586
+ (!ctor && bar.constructor === Object) ||
587
+ (ctor === Object && !bar.constructor))) {
588
+ ctor ??= bar.constructor;
596
589
  if (ctor === Date)
597
590
  return foo.getTime() === bar.getTime();
598
591
  if (ctor === RegExp)
@@ -683,8 +676,8 @@ const getCookie = (name) => {
683
676
  if (typeof document === 'undefined') {
684
677
  return null;
685
678
  }
686
- // From https://stackoverflow.com/questions/10730362/get-cookie-by-name
687
- return ('; ' + document.cookie).split(`; ${name}=`).pop()?.split(';')[0];
679
+ const cookie = document.cookie.split(';').find((entry) => entry.trim().startsWith(`${name}=`));
680
+ return cookie?.trim().slice(name.length + 1) ?? null;
688
681
  };
689
682
  const setCookie = (name, data, expiresInDays, domain = getDomain(), path = '/', sameSite = 'lax') => {
690
683
  if (typeof document === 'undefined') {
@@ -698,7 +691,14 @@ const setCookie = (name, data, expiresInDays, domain = getDomain(), path = '/',
698
691
  date.setTime(date.getTime() + expires * 24 * 60 * 60 * 1000);
699
692
  cookieString += `; expires=${date.toUTCString()}`;
700
693
  }
701
- cookieString += `; domain=${domain}; SameSite=${sameSiteUpper};`;
694
+ if (domain) {
695
+ cookieString += `; domain=${domain}`;
696
+ }
697
+ cookieString += `; SameSite=${sameSiteUpper}`;
698
+ if (sameSite === 'none' || window.location.protocol === 'https:') {
699
+ cookieString += '; Secure';
700
+ }
701
+ cookieString += ';';
702
702
  document.cookie = cookieString;
703
703
  };
704
704
  const deleteCookie = (name, path = '/', domain = getDomain()) => {
@@ -733,15 +733,15 @@ const getDomain = () => {
733
733
  class KeyPressManager {
734
734
  constructor(key) {
735
735
  this.key = key;
736
- this._isKeyPressed$ = new BehaviorSubject(false);
737
- this._keyPressCount$ = new BehaviorSubject(0);
736
+ this.isKeyPressed = false;
737
+ this.keyPressCount = 0;
738
738
  this._stopTimeout$ = new Subject();
739
739
  }
740
740
  isPressed(event) {
741
741
  const key = event.keyCode;
742
742
  if (key === this.key) {
743
- this._isKeyPressed$.next(this._keyPressCount$.value > 1);
744
- this._keyPressCount$.next(this._keyPressCount$.value + 1);
743
+ this.isKeyPressed = this.keyPressCount >= 1;
744
+ this.keyPressCount++;
745
745
  this._stopTimeout$.next();
746
746
  timer(100)
747
747
  .pipe(takeUntil(this._stopTimeout$))
@@ -750,11 +750,11 @@ class KeyPressManager {
750
750
  else {
751
751
  this.clear();
752
752
  }
753
- return this._isKeyPressed$.value;
753
+ return this.isKeyPressed;
754
754
  }
755
755
  clear() {
756
- this._isKeyPressed$.next(false);
757
- this._keyPressCount$.next(0);
756
+ this.isKeyPressed = false;
757
+ this.keyPressCount = 0;
758
758
  this._stopTimeout$.next();
759
759
  }
760
760
  }
@@ -880,9 +880,6 @@ const RENDERER_DEF = /* @__PURE__ */ defineRootProvider(() => {
880
880
  const setTextContent = (element, text) => {
881
881
  renderer.setProperty(element, 'textContent', text);
882
882
  };
883
- const setInnerHTML = (element, html) => {
884
- renderer.setProperty(element, 'innerHTML', html);
885
- };
886
883
  const setAttributes = (element, attributes, namespace) => {
887
884
  Object.entries(attributes).forEach(([name, value]) => {
888
885
  setAttribute(element, name, value, namespace);
@@ -933,7 +930,6 @@ const RENDERER_DEF = /* @__PURE__ */ defineRootProvider(() => {
933
930
  replaceChild,
934
931
  empty,
935
932
  setTextContent,
936
- setInnerHTML,
937
933
  setAttributes,
938
934
  setDataAttributes,
939
935
  setCssProperty,
@@ -949,8 +945,13 @@ const coerceElement = (el) => (el instanceof ElementRef ? el.nativeElement : el)
949
945
  const isElementSignal = (el) => {
950
946
  if (!isSignal(el))
951
947
  return false;
952
- const val = el();
953
- return typeof val === 'object' && val !== null && 'currentElements' in val && 'previousElements' in val;
948
+ try {
949
+ const val = el();
950
+ return typeof val === 'object' && val !== null && 'currentElements' in val && 'previousElements' in val;
951
+ }
952
+ catch {
953
+ return false;
954
+ }
954
955
  };
955
956
  const createDocumentElementSignal = () => {
956
957
  const documentElement = inject(DOCUMENT).documentElement;
@@ -979,8 +980,6 @@ const areElementSignalValuesEqual = (a, b) => areElementArraysEqual(a.currentEle
979
980
  const buildElementSignal = (el) => {
980
981
  if (el === null || el === undefined)
981
982
  return createEmptyElementSignal();
982
- if (isElementSignal(el))
983
- return el;
984
983
  if (el instanceof HTMLElement || el instanceof ElementRef) {
985
984
  const element = coerceElement(el);
986
985
  if (!element)
@@ -998,6 +997,12 @@ const createElementSignalFromSignal = (input) => {
998
997
  return linkedSignal({
999
998
  source: input,
1000
999
  computation: (source, previous) => {
1000
+ if (typeof source === 'object' &&
1001
+ source !== null &&
1002
+ 'currentElements' in source &&
1003
+ 'previousElements' in source) {
1004
+ return source;
1005
+ }
1001
1006
  const currentElements = coerceValueToElementArray(source);
1002
1007
  const previousElements = previous?.value.currentElements ?? [];
1003
1008
  return {
@@ -1089,109 +1094,12 @@ const createCanAnimateSignal = () => {
1089
1094
  };
1090
1095
  };
1091
1096
 
1092
- const boundingClientRectToElementRect = (rect) => ({
1093
- bottom: rect.bottom,
1094
- height: rect.height,
1095
- left: rect.left,
1096
- right: rect.right,
1097
- top: rect.top,
1098
- width: rect.width,
1099
- x: rect.x,
1100
- y: rect.y,
1101
- });
1102
- const createElementDimensions = (el, rect) => {
1103
- if (!el) {
1104
- return {
1105
- rect: null,
1106
- client: null,
1107
- scroll: null,
1108
- offset: null,
1109
- };
1110
- }
1111
- const cachedNormalizedRect = rect ? boundingClientRectToElementRect(rect) : null;
1112
- const rectFn = () => cachedNormalizedRect ? cachedNormalizedRect : boundingClientRectToElementRect(el.getBoundingClientRect());
1113
- return {
1114
- rect: rectFn,
1115
- client: { width: el.clientWidth, height: el.clientHeight },
1116
- scroll: { width: el.scrollWidth, height: el.scrollHeight },
1117
- offset: { width: el.offsetWidth, height: el.offsetHeight },
1118
- };
1119
- };
1120
- const signalElementDimensions = (el) => {
1121
- const destroyRef = inject(DestroyRef);
1122
- const elements = buildElementSignal(el);
1123
- const firstEl = firstElementSignal(elements);
1124
- const zone = inject(NgZone);
1125
- const isRendered = signalIsRendered();
1126
- const initialValue = () => createElementDimensions(firstEl().currentElement);
1127
- const elementDimensionsSignal = signal(initialValue(), /* @ts-ignore */
1128
- ...(ngDevMode ? [{ debugName: "elementDimensionsSignal" }] : /* istanbul ignore next */ []));
1129
- const observer = new ResizeObserver((e) => {
1130
- if (!isRendered())
1131
- return;
1132
- const entry = e[0];
1133
- if (entry) {
1134
- const target = entry.target;
1135
- const newDimensions = createElementDimensions(target);
1136
- zone.run(() => elementDimensionsSignal.set(newDimensions));
1137
- }
1138
- });
1139
- effect(() => {
1140
- const els = firstEl();
1141
- untracked(() => {
1142
- elementDimensionsSignal.set(initialValue());
1143
- if (els.previousElement) {
1144
- observer.disconnect();
1145
- }
1146
- if (els.currentElement) {
1147
- const computedDisplay = getComputedStyle(els.currentElement).display;
1148
- const currentElIsAngularComponent = els.currentElement?.tagName.toLowerCase().includes('-');
1149
- if (computedDisplay === 'inline' && isDevMode() && currentElIsAngularComponent) {
1150
- 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.`);
1151
- }
1152
- observer.observe(els.currentElement);
1153
- }
1154
- });
1155
- });
1156
- destroyRef.onDestroy(() => observer.disconnect());
1157
- return computed(() => elementDimensionsSignal(), {
1158
- equal: (a, b) => equal(a, b),
1159
- });
1160
- };
1161
- const signalHostElementDimensions = () => signalElementDimensions(inject(ElementRef));
1162
- const injectViewportSize = () => {
1163
- const document = inject(DOCUMENT$1);
1164
- const zone = inject(NgZone);
1165
- const destroyRef = inject(DestroyRef);
1166
- const getSize = () => {
1167
- const vv = document.defaultView?.visualViewport;
1168
- if (vv)
1169
- return { width: vv.width, height: vv.height };
1170
- const win = document.defaultView;
1171
- return { width: win?.innerWidth ?? 0, height: win?.innerHeight ?? 0 };
1172
- };
1173
- const size = signal(getSize(), /* @ts-ignore */
1174
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1175
- const onResize = () => zone.run(() => size.set(getSize()));
1176
- const vv = document.defaultView?.visualViewport;
1177
- if (vv) {
1178
- vv.addEventListener('resize', onResize);
1179
- destroyRef.onDestroy(() => vv.removeEventListener('resize', onResize));
1180
- }
1181
- else {
1182
- const win = document.defaultView;
1183
- win?.addEventListener('resize', onResize);
1184
- destroyRef.onDestroy(() => win?.removeEventListener('resize', onResize));
1185
- }
1186
- return size;
1187
- };
1188
-
1189
1097
  const previousSignalValue = (signal) => {
1190
1098
  const obs = toObservable(signal).pipe(pairwise(), map(([prev]) => prev));
1191
1099
  return toSignal(obs);
1192
1100
  };
1193
1101
  const syncSignal = (from, to, options) => {
1194
- let isFirstRun = options?.skipSyncRead ? false : true;
1102
+ let isFirstRun = true;
1195
1103
  if (!options?.skipSyncRead) {
1196
1104
  try {
1197
1105
  // this might throw if the signal is not yet initialized (eg. a required signal input inside the constructor)
@@ -1283,6 +1191,104 @@ const memoizeSignal = (factory) => {
1283
1191
  };
1284
1192
  };
1285
1193
 
1194
+ const boundingClientRectToElementRect = (rect) => ({
1195
+ bottom: rect.bottom,
1196
+ height: rect.height,
1197
+ left: rect.left,
1198
+ right: rect.right,
1199
+ top: rect.top,
1200
+ width: rect.width,
1201
+ x: rect.x,
1202
+ y: rect.y,
1203
+ });
1204
+ const createElementDimensions = (el, rect) => {
1205
+ if (!el) {
1206
+ return {
1207
+ rect: null,
1208
+ client: null,
1209
+ scroll: null,
1210
+ offset: null,
1211
+ };
1212
+ }
1213
+ const cachedNormalizedRect = rect ? boundingClientRectToElementRect(rect) : null;
1214
+ const rectFn = () => cachedNormalizedRect ? cachedNormalizedRect : boundingClientRectToElementRect(el.getBoundingClientRect());
1215
+ return {
1216
+ rect: rectFn,
1217
+ client: { width: el.clientWidth, height: el.clientHeight },
1218
+ scroll: { width: el.scrollWidth, height: el.scrollHeight },
1219
+ offset: { width: el.offsetWidth, height: el.offsetHeight },
1220
+ };
1221
+ };
1222
+ const signalElementDimensions = (el) => {
1223
+ const destroyRef = inject(DestroyRef);
1224
+ const elements = buildElementSignal(el);
1225
+ const firstEl = firstElementSignal(elements);
1226
+ const zone = inject(NgZone);
1227
+ const isRendered = signalIsRendered();
1228
+ const initialValue = () => createElementDimensions(firstEl().currentElement);
1229
+ const elementDimensionsSignal = signal(initialValue(), /* @ts-ignore */
1230
+ ...(ngDevMode ? [{ debugName: "elementDimensionsSignal" }] : /* istanbul ignore next */ []));
1231
+ let observer = null;
1232
+ effect(() => {
1233
+ const els = firstEl();
1234
+ const rendered = isRendered();
1235
+ untracked(() => {
1236
+ elementDimensionsSignal.set(initialValue());
1237
+ if (!rendered || typeof ResizeObserver === 'undefined') {
1238
+ return;
1239
+ }
1240
+ observer ??= new ResizeObserver((entries) => {
1241
+ const entry = entries[0];
1242
+ if (entry) {
1243
+ const target = entry.target;
1244
+ const newDimensions = createElementDimensions(target);
1245
+ zone.run(() => elementDimensionsSignal.set(newDimensions));
1246
+ }
1247
+ });
1248
+ observer.disconnect();
1249
+ if (els.currentElement) {
1250
+ const computedDisplay = els.currentElement.ownerDocument.defaultView?.getComputedStyle(els.currentElement).display;
1251
+ const currentElIsAngularComponent = els.currentElement?.tagName.toLowerCase().includes('-');
1252
+ if (computedDisplay === 'inline' && isDevMode() && currentElIsAngularComponent) {
1253
+ 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.`);
1254
+ }
1255
+ observer.observe(els.currentElement);
1256
+ }
1257
+ });
1258
+ });
1259
+ destroyRef.onDestroy(() => observer?.disconnect());
1260
+ return computed(() => elementDimensionsSignal(), {
1261
+ equal: (a, b) => equal(a, b),
1262
+ });
1263
+ };
1264
+ const signalHostElementDimensions = () => signalElementDimensions(inject(ElementRef));
1265
+ const injectViewportSize = /* @__PURE__ */ memoizeSignal(() => {
1266
+ const document = inject(DOCUMENT);
1267
+ const zone = inject(NgZone);
1268
+ const destroyRef = inject(DestroyRef);
1269
+ const getSize = () => {
1270
+ const vv = document.defaultView?.visualViewport;
1271
+ if (vv)
1272
+ return { width: vv.width, height: vv.height };
1273
+ const win = document.defaultView;
1274
+ return { width: win?.innerWidth ?? 0, height: win?.innerHeight ?? 0 };
1275
+ };
1276
+ const size = signal(getSize(), /* @ts-ignore */
1277
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1278
+ const onResize = () => zone.run(() => size.set(getSize()));
1279
+ const vv = document.defaultView?.visualViewport;
1280
+ if (vv) {
1281
+ vv.addEventListener('resize', onResize);
1282
+ destroyRef.onDestroy(() => vv.removeEventListener('resize', onResize));
1283
+ }
1284
+ else {
1285
+ const win = document.defaultView;
1286
+ win?.addEventListener('resize', onResize);
1287
+ destroyRef.onDestroy(() => win?.removeEventListener('resize', onResize));
1288
+ }
1289
+ return size;
1290
+ });
1291
+
1286
1292
  /** Inject a signal containing a boolean value indicating if the viewport is xs */
1287
1293
  const injectIsXs = /* @__PURE__ */ memoizeSignal(() => injectObserveBreakpoint({ max: 'xs' }));
1288
1294
  /** Inject a signal containing a boolean value indicating if the viewport is sm */
@@ -1365,15 +1371,24 @@ const injectViewportDimensions = /* @__PURE__ */ memoizeSignal(() => signalEleme
1365
1371
  /** Inject a signal containing the scrollbar dimensions. Dimensions will be 0 if scrollbars overlap the page contents (like on mobile). */
1366
1372
  const injectScrollbarDimensions = /* @__PURE__ */ memoizeSignal(() => {
1367
1373
  const document = inject(DOCUMENT);
1374
+ const destroyRef = inject(DestroyRef);
1368
1375
  const renderer = injectRenderer();
1376
+ const view = document.defaultView;
1377
+ if (!view)
1378
+ return signal(null).asReadonly();
1369
1379
  const scrollbarRuler = renderer.createElement('div');
1370
1380
  scrollbarRuler.style.width = '100px';
1371
1381
  scrollbarRuler.style.height = '100px';
1372
1382
  scrollbarRuler.style.overflow = 'scroll';
1373
1383
  scrollbarRuler.style.position = 'absolute';
1374
1384
  scrollbarRuler.style.top = '-9999px';
1375
- scrollbarRuler.style.scrollbarWidth = getComputedStyle(document.documentElement).scrollbarWidth;
1385
+ scrollbarRuler.style.scrollbarWidth = view.getComputedStyle(document.documentElement).scrollbarWidth;
1376
1386
  renderer.appendChild(document.body, scrollbarRuler);
1387
+ destroyRef.onDestroy(() => {
1388
+ const parent = renderer.parentNode(scrollbarRuler);
1389
+ if (parent)
1390
+ renderer.removeChild(parent, scrollbarRuler);
1391
+ });
1377
1392
  const scrollContainerDimensions = signalElementDimensions(scrollbarRuler);
1378
1393
  return computed(() => {
1379
1394
  const client = scrollContainerDimensions().client;
@@ -1408,6 +1423,7 @@ const injectAnimatedBlockSize = (config) => {
1408
1423
  const renderer = injectRenderer();
1409
1424
  const prefersReducedMotion = injectPrefersReducedMotion();
1410
1425
  const destroyRef = inject(DestroyRef);
1426
+ const isRendered = signalIsRendered();
1411
1427
  const hostSignal = firstElementSignal(buildElementSignal(hostBinding));
1412
1428
  const observeTargets = Array.isArray(config.observe) ? config.observe : [config.observe];
1413
1429
  const observedElements = observeTargets.map((target) => firstElementSignal(buildElementSignal(target)));
@@ -1447,7 +1463,7 @@ const injectAnimatedBlockSize = (config) => {
1447
1463
  if (!animateBlock && !animateInline) {
1448
1464
  return;
1449
1465
  }
1450
- if (config.resizingClass && renderer) {
1466
+ if (config.resizingClass) {
1451
1467
  renderer.addClass(host, config.resizingClass);
1452
1468
  }
1453
1469
  const fromFrame = {};
@@ -1470,7 +1486,7 @@ const injectAnimatedBlockSize = (config) => {
1470
1486
  if (animation !== null && animation !== nextAnimation) {
1471
1487
  return;
1472
1488
  }
1473
- if (config.resizingClass && renderer) {
1489
+ if (config.resizingClass) {
1474
1490
  renderer.removeClass(host, config.resizingClass);
1475
1491
  }
1476
1492
  if (animation === nextAnimation) {
@@ -1480,15 +1496,18 @@ const injectAnimatedBlockSize = (config) => {
1480
1496
  nextAnimation.finished.then(cleanup).catch(cleanup);
1481
1497
  animation = nextAnimation;
1482
1498
  };
1483
- // no zone/signal indirection - see the pre-paint timing note in the doc comment above
1484
- const observer = new ResizeObserver(() => {
1485
- if (!ready)
1486
- return;
1487
- run();
1488
- });
1499
+ let observer = null;
1489
1500
  effect(() => {
1490
1501
  const elements = observedElements.map((element) => element().currentElement);
1502
+ const rendered = isRendered();
1491
1503
  untracked(() => {
1504
+ if (!rendered || typeof ResizeObserver === 'undefined') {
1505
+ return;
1506
+ }
1507
+ observer ??= new ResizeObserver(() => {
1508
+ if (ready)
1509
+ run();
1510
+ });
1492
1511
  observer.disconnect();
1493
1512
  for (const element of elements) {
1494
1513
  if (element) {
@@ -1497,7 +1516,6 @@ const injectAnimatedBlockSize = (config) => {
1497
1516
  }
1498
1517
  });
1499
1518
  });
1500
- // Capture the settled size of the first render as the baseline, then only animate later changes.
1501
1519
  afterNextRender(() => {
1502
1520
  const host = hostElement();
1503
1521
  const rect = host ? host.getBoundingClientRect() : null;
@@ -1506,7 +1524,7 @@ const injectAnimatedBlockSize = (config) => {
1506
1524
  ready = true;
1507
1525
  });
1508
1526
  destroyRef.onDestroy(() => {
1509
- observer.disconnect();
1527
+ observer?.disconnect();
1510
1528
  animation?.cancel();
1511
1529
  });
1512
1530
  };
@@ -1516,6 +1534,7 @@ const injectAnimatedBlockSize = (config) => {
1516
1534
  */
1517
1535
  const signalAnimatedNumber = (source, options = {}) => {
1518
1536
  const ngZone = inject(NgZone);
1537
+ const destroyRef = inject(DestroyRef);
1519
1538
  const duration = options.duration ?? 1000;
1520
1539
  const easing = options.easing ?? easeOut;
1521
1540
  const round = options.round ?? ((v) => Math.round(v));
@@ -1524,6 +1543,7 @@ const signalAnimatedNumber = (source, options = {}) => {
1524
1543
  ...(ngDevMode ? [{ debugName: "animatedValue" }] : /* istanbul ignore next */ []));
1525
1544
  let rafId = null;
1526
1545
  let currentAnimatedValue = initialValue;
1546
+ let destroyed = false;
1527
1547
  const cancelAnimation = () => {
1528
1548
  if (rafId !== null) {
1529
1549
  cancelAnimationFrame(rafId);
@@ -1537,14 +1557,21 @@ const signalAnimatedNumber = (source, options = {}) => {
1537
1557
  const startValue = currentAnimatedValue;
1538
1558
  const startTime = performance.now();
1539
1559
  const delta = targetValue - startValue;
1540
- // Skip animation if no change
1541
1560
  if (delta === 0) {
1542
1561
  options.onAnimationEnd?.();
1543
1562
  return readonlySignal;
1544
1563
  }
1545
1564
  options.onAnimationStart?.();
1565
+ if (typeof requestAnimationFrame === 'undefined') {
1566
+ currentAnimatedValue = targetValue;
1567
+ animatedValue.set(round(targetValue));
1568
+ options.onAnimationEnd?.();
1569
+ return readonlySignal;
1570
+ }
1546
1571
  ngZone.runOutsideAngular(() => {
1547
1572
  const animate = (timestamp) => {
1573
+ if (destroyed)
1574
+ return;
1548
1575
  const elapsed = timestamp - startTime;
1549
1576
  const progress = Math.min(elapsed / duration, 1);
1550
1577
  const easedProgress = easing(progress);
@@ -1580,6 +1607,10 @@ const signalAnimatedNumber = (source, options = {}) => {
1580
1607
  readonlySignal.play = play;
1581
1608
  readonlySignal.reset = reset;
1582
1609
  readonlySignal.stop = stop;
1610
+ destroyRef.onDestroy(() => {
1611
+ destroyed = true;
1612
+ cancelAnimation();
1613
+ });
1583
1614
  return readonlySignal;
1584
1615
  };
1585
1616
  /* Linear easing function */
@@ -1630,10 +1661,12 @@ const provideViewportConfig = /* @__PURE__ */ toProvideFn(VIEWPORT_CONFIG_DEF);
1630
1661
  const injectViewportConfig = /* @__PURE__ */ toInjectFn(VIEWPORT_CONFIG_DEF);
1631
1662
  const BREAKPOINT_OBSERVER_DEF = /* @__PURE__ */ defineRootProvider(() => {
1632
1663
  const viewportConfig = injectViewportConfig();
1664
+ const destroyRef = inject(DestroyRef);
1633
1665
  const defaultView = inject(DOCUMENT).defaultView;
1634
1666
  const matchMedia = defaultView?.matchMedia?.bind(defaultView) ?? null;
1635
1667
  const queryLists = new Map();
1636
1668
  const querySignals = new Map();
1669
+ const queryListenerCleanups = new Map();
1637
1670
  const getQueryList = (mediaQuery) => {
1638
1671
  if (!matchMedia)
1639
1672
  return null;
@@ -1652,9 +1685,11 @@ const BREAKPOINT_OBSERVER_DEF = /* @__PURE__ */ defineRootProvider(() => {
1652
1685
  const queryList = getQueryList(mediaQuery);
1653
1686
  const matches = signal(queryList?.matches ?? false, /* @ts-ignore */
1654
1687
  ...(ngDevMode ? [{ debugName: "matches" }] : /* istanbul ignore next */ []));
1655
- // the root provider outlives every consumer, so the listener is intentionally never removed -
1656
- // the same query list is shared by all of them
1657
- queryList?.addEventListener('change', (event) => matches.set(event.matches));
1688
+ if (queryList) {
1689
+ const onChange = (event) => matches.set(event.matches);
1690
+ queryList.addEventListener('change', onChange);
1691
+ queryListenerCleanups.set(mediaQuery, () => queryList.removeEventListener('change', onChange));
1692
+ }
1658
1693
  const result = matches.asReadonly();
1659
1694
  querySignals.set(mediaQuery, result);
1660
1695
  return result;
@@ -1676,11 +1711,11 @@ const BREAKPOINT_OBSERVER_DEF = /* @__PURE__ */ defineRootProvider(() => {
1676
1711
  return size + 0.9;
1677
1712
  };
1678
1713
  const buildMediaQueryString = (options) => {
1679
- if (!options.min && !options.max) {
1714
+ if (options.min === undefined && options.max === undefined) {
1680
1715
  throw new Error('At least one of min or max must be defined');
1681
1716
  }
1682
1717
  const mediaQueryParts = [];
1683
- if (options.min) {
1718
+ if (options.min !== undefined) {
1684
1719
  if (typeof options.min === 'number') {
1685
1720
  mediaQueryParts.push(`(min-width: ${options.min}px)`);
1686
1721
  }
@@ -1688,19 +1723,16 @@ const BREAKPOINT_OBSERVER_DEF = /* @__PURE__ */ defineRootProvider(() => {
1688
1723
  mediaQueryParts.push(`(min-width: ${getBreakpointSize(options.min, 'min')}px)`);
1689
1724
  }
1690
1725
  }
1691
- if (options.min && options.max) {
1692
- mediaQueryParts.push('and');
1726
+ if (options.max !== undefined) {
1727
+ const max = typeof options.max === 'number' ? options.max : getBreakpointSize(options.max, 'max');
1728
+ if (max !== Infinity)
1729
+ mediaQueryParts.push(`(max-width: ${max}px)`);
1693
1730
  }
1694
- if (options.max) {
1695
- if (typeof options.max === 'number') {
1696
- mediaQueryParts.push(`(max-width: ${options.max}px)`);
1697
- }
1698
- else {
1699
- mediaQueryParts.push(`(max-width: ${getBreakpointSize(options.max, 'max')}px)`);
1700
- }
1701
- }
1702
- return mediaQueryParts.join(' ');
1731
+ return mediaQueryParts.length > 0 ? mediaQueryParts.join(' and ') : '(min-width: 0px)';
1703
1732
  };
1733
+ destroyRef.onDestroy(() => {
1734
+ queryListenerCleanups.forEach((cleanup) => cleanup());
1735
+ });
1704
1736
  return {
1705
1737
  observeBreakpoint,
1706
1738
  isBreakpointMatched,
@@ -1741,31 +1773,24 @@ const resolveFromMap = (map, bp, defaultValue) => {
1741
1773
  }
1742
1774
  return defaultValue;
1743
1775
  };
1744
- const breakpointTransformBase = (coerce) => {
1776
+ const breakpointTransformBase = (coerce, defaultValue) => {
1745
1777
  const currentBp = injectCurrentBreakpoint();
1746
1778
  const injector = inject(Injector);
1747
1779
  const raw = signal(undefined, /* @ts-ignore */
1748
1780
  ...(ngDevMode ? [{ debugName: "raw" }] : /* istanbul ignore next */ []));
1749
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1750
- let capturedDefault = undefined;
1751
- let initialized = false;
1752
1781
  let cachedSig = null;
1753
1782
  const transformFn = (value) => {
1754
1783
  const coerced = isBreakpointMap(value) ? value : coerce(value);
1755
- if (!initialized) {
1756
- capturedDefault = coerced;
1757
- initialized = true;
1758
- }
1759
1784
  raw.set(coerced);
1760
- return isBreakpointMap(coerced)
1761
- ? resolveFromMap(coerced, currentBp(), capturedDefault)
1762
- : coerced;
1785
+ return isBreakpointMap(coerced) ? resolveFromMap(coerced, currentBp(), defaultValue) : coerced;
1763
1786
  };
1764
1787
  effect(() => {
1765
1788
  const bp = currentBp();
1766
1789
  const r = raw();
1767
1790
  if (!cachedSig) {
1768
- const instance = injector.get(BREAKPOINT_INSTANCE_TOKEN);
1791
+ const instance = injector.get(BREAKPOINT_INSTANCE_TOKEN, null);
1792
+ if (!instance)
1793
+ return;
1769
1794
  for (const key of Object.keys(instance)) {
1770
1795
  const val = instance[key];
1771
1796
  if (val && typeof val === 'function' && val[SIGNAL]?.transformFn === transformFn) {
@@ -1776,7 +1801,7 @@ const breakpointTransformBase = (coerce) => {
1776
1801
  }
1777
1802
  if (!cachedSig || r === undefined || !isBreakpointMap(r))
1778
1803
  return;
1779
- const resolved = resolveFromMap(r, bp, capturedDefault);
1804
+ const resolved = resolveFromMap(r, bp, defaultValue);
1780
1805
  untracked(() => setInputSignal(cachedSig, resolved));
1781
1806
  });
1782
1807
  return transformFn;
@@ -1786,30 +1811,30 @@ const breakpointTransformBase = (coerce) => {
1786
1811
  * Coerces plain values with `booleanAttribute`; resolves {@link BreakpointMap} mobile-first.
1787
1812
  *
1788
1813
  * @example
1789
- * snap = input(false, { transform: boolBreakpointTransform() });
1814
+ * snap = input(false, { transform: boolBreakpointTransform(false) });
1790
1815
  * // Template: `snap` | `[snap]="true"` | `[snap]="{ xs: false, md: true }"`
1791
1816
  */
1792
- const boolBreakpointTransform = () => breakpointTransformBase(booleanAttribute);
1817
+ const boolBreakpointTransform = (defaultValue = false) => breakpointTransformBase(booleanAttribute, defaultValue);
1793
1818
  /**
1794
1819
  * Transform factory for number inputs.
1795
1820
  * Coerces plain values with `numberAttribute`; resolves {@link BreakpointMap} mobile-first.
1796
1821
  *
1797
1822
  * @example
1798
- * scrollMargin = input(0, { transform: numberBreakpointTransform() });
1823
+ * scrollMargin = input(0, { transform: numberBreakpointTransform(0) });
1799
1824
  * // Template: `[scrollMargin]="16"` | `[scrollMargin]="{ xs: 0, md: 16 }"`
1800
1825
  */
1801
- const numberBreakpointTransform = () => breakpointTransformBase((v) => numberAttribute(v));
1826
+ const numberBreakpointTransform = (defaultValue = 0) => breakpointTransformBase((v) => numberAttribute(v), defaultValue);
1802
1827
  /**
1803
1828
  * Transform factory for any typed input (string unions, arrays, objects, etc.).
1804
1829
  * Passes plain values through as-is; resolves {@link BreakpointMap} mobile-first.
1805
1830
  * A value is treated as a {@link BreakpointMap} only when all its keys are valid breakpoint names.
1806
1831
  *
1807
1832
  * @example
1808
- * itemSize = input('auto', { transform: typedBreakpointTransform<ScrollableItemSize>() });
1809
- * tags = input([], { transform: typedBreakpointTransform<string[]>() });
1833
+ * itemSize = input('auto', { transform: typedBreakpointTransform<ScrollableItemSize>('auto') });
1834
+ * tags = input([], { transform: typedBreakpointTransform<string[]>([]) });
1810
1835
  * // Template: `[itemSize]="'third'"` | `[itemSize]="{ xs: 'full', md: 'third' }"`
1811
1836
  */
1812
- const typedBreakpointTransform = () => breakpointTransformBase((v) => v);
1837
+ const typedBreakpointTransform = (defaultValue) => breakpointTransformBase((v) => v, defaultValue);
1813
1838
  const injectBreakpointInput = (inputSignal, defaultValue) => {
1814
1839
  const currentBreakpoint = injectCurrentBreakpoint();
1815
1840
  return computed(() => {
@@ -1819,16 +1844,6 @@ const injectBreakpointInput = (inputSignal, defaultValue) => {
1819
1844
  return resolveFromMap(value, currentBreakpoint(), defaultValue);
1820
1845
  });
1821
1846
  };
1822
- const booleanBreakpointAttribute = (value) => {
1823
- if (isBreakpointMap(value))
1824
- return value;
1825
- return booleanAttribute(value);
1826
- };
1827
- const numberBreakpointAttribute = (value) => {
1828
- if (isBreakpointMap(value))
1829
- return value;
1830
- return numberAttribute(value);
1831
- };
1832
1847
  const BREAKPOINT_INSTANCE_TOKEN = new InjectionToken('BREAKPOINT_INSTANCE_TOKEN');
1833
1848
  const provideBreakpointInstance = (componentClass) => ({
1834
1849
  provide: BREAKPOINT_INSTANCE_TOKEN,
@@ -1852,14 +1867,17 @@ const controlValueSignal = (control, options) => {
1852
1867
  const controlObs = controlStream.pipe(switchMap((ctrl) => {
1853
1868
  if (!ctrl)
1854
1869
  return of(null);
1855
- const vcsObs = options?.debounceTime
1856
- ? ctrl.valueChanges.pipe(debounceTime(options.debounceTime))
1857
- : ctrl.valueChanges;
1858
- return vcsObs.pipe(startWith(ctrl.getRawValue()), map(() => ctrl.getRawValue()));
1870
+ const changes = ctrl.valueChanges.pipe(map(() => ctrl.getRawValue()));
1871
+ const debouncedChanges = options?.debounceTime ? changes.pipe(debounceTime(options.debounceTime)) : changes;
1872
+ if (!options?.debounceFirst) {
1873
+ return merge(of(ctrl.getRawValue()), debouncedChanges);
1874
+ }
1875
+ const values = merge(of(ctrl.getRawValue()), changes);
1876
+ return options.debounceTime ? values.pipe(debounceTime(options.debounceTime)) : values;
1859
1877
  }));
1860
- const obs = !options?.debounceFirst ? merge(of(initialValue), controlObs) : controlObs;
1878
+ const obs = controlObs;
1861
1879
  return toSignal(obs.pipe(distinctUntilChanged((a, b) => equal(a, b))), {
1862
- initialValue,
1880
+ initialValue: options?.debounceFirst ? null : initialValue,
1863
1881
  });
1864
1882
  };
1865
1883
  /**
@@ -1924,25 +1942,26 @@ const signalElementMutations = (el, options) => {
1924
1942
  const isRendered = signalIsRendered();
1925
1943
  const elementMutationsSignal = signal(null, /* @ts-ignore */
1926
1944
  ...(ngDevMode ? [{ debugName: "elementMutationsSignal" }] : /* istanbul ignore next */ []));
1927
- const observer = new MutationObserver((e) => {
1928
- if (!isRendered())
1929
- return;
1930
- const entry = e[0];
1931
- if (entry) {
1932
- zone.run(() => elementMutationsSignal.set(entry));
1933
- }
1934
- });
1945
+ let observer = null;
1935
1946
  effect(() => {
1936
1947
  const els = firstEl();
1948
+ const rendered = isRendered();
1937
1949
  elementMutationsSignal.set(null);
1938
- if (els.previousElement) {
1939
- observer.disconnect();
1950
+ if (!rendered || typeof MutationObserver === 'undefined') {
1951
+ return;
1940
1952
  }
1953
+ observer ??= new MutationObserver((entries) => {
1954
+ const entry = entries[0];
1955
+ if (entry) {
1956
+ zone.run(() => elementMutationsSignal.set(entry));
1957
+ }
1958
+ });
1959
+ observer.disconnect();
1941
1960
  if (els.currentElement) {
1942
1961
  observer.observe(els.currentElement, options);
1943
1962
  }
1944
1963
  });
1945
- destroyRef.onDestroy(() => observer.disconnect());
1964
+ destroyRef.onDestroy(() => observer?.disconnect());
1946
1965
  return elementMutationsSignal.asReadonly();
1947
1966
  };
1948
1967
  const signalHostElementMutations = (options) => signalElementMutations(inject(ElementRef), options);
@@ -2149,20 +2168,6 @@ const isElementVisible = (options) => {
2149
2168
  }
2150
2169
  const elementRect = options.elementRect || element.getBoundingClientRect();
2151
2170
  const containerRect = container ? options.containerRect || container.getBoundingClientRect() : createViewportRect();
2152
- const canScroll = elementCanScroll(container);
2153
- if (!canScroll) {
2154
- return {
2155
- inline: true,
2156
- block: true,
2157
- blockIntersection: 1,
2158
- inlineIntersection: 1,
2159
- intersectionRatio: 1,
2160
- isIntersecting: true,
2161
- element,
2162
- containerRect,
2163
- elementRect,
2164
- };
2165
- }
2166
2171
  const elLeft = elementRect.left;
2167
2172
  const elTop = elementRect.top;
2168
2173
  const elWidth = elementRect.width || 1;
@@ -2184,7 +2189,7 @@ const isElementVisible = (options) => {
2184
2189
  block: isElementBlockVisible,
2185
2190
  inlineIntersection: inlineIntersectionPercentage,
2186
2191
  blockIntersection: blockIntersectionPercentage,
2187
- isIntersecting: isElementInlineVisible && isElementBlockVisible,
2192
+ isIntersecting: inlineIntersectionPercentage > 0 && blockIntersectionPercentage > 0,
2188
2193
  element,
2189
2194
  containerRect,
2190
2195
  elementRect,
@@ -2432,12 +2437,13 @@ const createPositionObject = (entry) => {
2432
2437
  };
2433
2438
  };
2434
2439
  const signalElementIntersection = (el, options) => {
2440
+ const { root: rootBinding, enabled, ...observerOptions } = options ?? {};
2435
2441
  const destroyRef = inject(DestroyRef);
2436
2442
  const elements = buildElementSignal(el);
2437
- const root = firstElementSignal(options?.root ? buildElementSignal(options?.root) : createEmptyElementSignal());
2443
+ const root = firstElementSignal(rootBinding ? buildElementSignal(rootBinding) : createEmptyElementSignal());
2438
2444
  const zone = inject(NgZone);
2439
2445
  const isRendered = signalIsRendered();
2440
- const isEnabled = options?.enabled ?? signal(true);
2446
+ const isEnabled = enabled ?? signal(true);
2441
2447
  const elementIntersectionSignal = signal([], /* @ts-ignore */
2442
2448
  ...(ngDevMode ? [{ debugName: "elementIntersectionSignal" }] : /* istanbul ignore next */ []));
2443
2449
  const observer = signal(null, /* @ts-ignore */
@@ -2477,18 +2483,21 @@ const signalElementIntersection = (el, options) => {
2477
2483
  currentlyObservedElements.clear();
2478
2484
  if (!rendered || !enabled) {
2479
2485
  observer.set(null);
2486
+ elementIntersectionSignal.set([]);
2480
2487
  return;
2481
2488
  }
2482
2489
  const newObserver = new IntersectionObserver((entries) => updateIntersections(entries), {
2483
- ...options,
2490
+ ...observerOptions,
2484
2491
  root: rootEl,
2485
2492
  });
2486
2493
  observer.set(newObserver);
2487
2494
  };
2488
2495
  const updateObservedElements = (observer, elements) => {
2489
2496
  const rootEl = root().currentElement;
2490
- if (!observer)
2497
+ if (!observer) {
2498
+ elementIntersectionSignal.set([]);
2491
2499
  return;
2500
+ }
2492
2501
  const currIntersectionValue = elementIntersectionSignal();
2493
2502
  const newIntersectionValue = [];
2494
2503
  for (const el of elements.currentElements) {
@@ -2506,13 +2515,8 @@ const signalElementIntersection = (el, options) => {
2506
2515
  container: rootEl,
2507
2516
  element: el,
2508
2517
  });
2509
- if (!initialElementVisibility) {
2510
- console.error('No visibility data found for element.', {
2511
- element: el,
2512
- container: rootEl,
2513
- });
2518
+ if (!initialElementVisibility)
2514
2519
  continue;
2515
- }
2516
2520
  const intersectionEntry = {
2517
2521
  boundingClientRect: initialElementVisibility.elementRect,
2518
2522
  intersectionRatio: initialElementVisibility.intersectionRatio,
@@ -2665,7 +2669,7 @@ const signalElementScrollState = (el, options) => {
2665
2669
  };
2666
2670
  const signalHostElementScrollState = () => signalElementScrollState(inject(ElementRef));
2667
2671
 
2668
- let hasWrittenScrollbarSizes = false;
2672
+ const scrollbarSizeWriters = /* @__PURE__ */ new WeakSet();
2669
2673
  /**
2670
2674
  * Applies scrollbar size CSS variables to the documentElement (html tag) in pixels.
2671
2675
  * - `--et-sw`: scrollbar width
@@ -2675,10 +2679,11 @@ const writeScrollbarSizeToCssVariables = () => {
2675
2679
  if (!isPlatformBrowser(inject(PLATFORM_ID))) {
2676
2680
  return;
2677
2681
  }
2678
- if (hasWrittenScrollbarSizes) {
2682
+ const environmentInjector = inject(EnvironmentInjector);
2683
+ if (scrollbarSizeWriters.has(environmentInjector)) {
2679
2684
  return;
2680
2685
  }
2681
- hasWrittenScrollbarSizes = true;
2686
+ scrollbarSizeWriters.add(environmentInjector);
2682
2687
  const document = inject(DOCUMENT);
2683
2688
  const renderer = injectRenderer();
2684
2689
  const scrollbarDimensions = injectScrollbarDimensions();
@@ -2692,7 +2697,7 @@ const writeScrollbarSizeToCssVariables = () => {
2692
2697
  });
2693
2698
  });
2694
2699
  };
2695
- let hasWrittenViewportSizes = false;
2700
+ const viewportSizeWriters = /* @__PURE__ */ new WeakSet();
2696
2701
  /**
2697
2702
  * Applies viewport size CSS variables to the documentElement (html tag) in pixels.
2698
2703
  * - `--et-vw`: viewport width excluding scrollbar width
@@ -2702,10 +2707,11 @@ const writeViewportSizeToCssVariables = () => {
2702
2707
  if (!isPlatformBrowser(inject(PLATFORM_ID))) {
2703
2708
  return;
2704
2709
  }
2705
- if (hasWrittenViewportSizes) {
2710
+ const environmentInjector = inject(EnvironmentInjector);
2711
+ if (viewportSizeWriters.has(environmentInjector)) {
2706
2712
  return;
2707
2713
  }
2708
- hasWrittenViewportSizes = true;
2714
+ viewportSizeWriters.add(environmentInjector);
2709
2715
  const document = inject(DOCUMENT);
2710
2716
  const renderer = injectRenderer();
2711
2717
  const htmlElementDimensions = injectViewportDimensions();
@@ -2990,7 +2996,10 @@ const createRouterState = (router) => {
2990
2996
  * where `router.url` is already committed. Falls back to the browser location before the first navigation commits.
2991
2997
  */
2992
2998
  const createRoute = (router) => {
2993
- const url = router.navigated ? router.url : window.location.pathname + window.location.search + window.location.hash;
2999
+ const browserUrl = typeof window === 'undefined'
3000
+ ? router.url
3001
+ : window.location.pathname + window.location.search + window.location.hash;
3002
+ const url = router.navigated ? router.url : browserUrl;
2994
3003
  return url.split('?')[0]?.split('#')[0] ?? '';
2995
3004
  };
2996
3005
  /**
@@ -3006,7 +3015,9 @@ const injectRouterState = /* @__PURE__ */ memoizeSignal(() => {
3006
3015
  });
3007
3016
  /** Inject a signal containing the current route fragment (the part after the # inside the url if present) */
3008
3017
  const injectFragment = (config) => {
3009
- const routerState = injectRouterState();
3018
+ const routerState = config?.injector
3019
+ ? runInInjectionContext(config.injector, injectRouterState)
3020
+ : injectRouterState();
3010
3021
  const fragment = computed(() => routerState().fragment, /* @ts-ignore */
3011
3022
  ...(ngDevMode ? [{ debugName: "fragment" }] : /* istanbul ignore next */ []));
3012
3023
  return transformOrReturn(fragment, config);
@@ -3215,6 +3226,7 @@ const setupScrollRestoration = (config = {}) => {
3215
3226
  const router = inject(Router);
3216
3227
  const document = inject(DOCUMENT);
3217
3228
  const injector = inject(Injector);
3229
+ const destroyRef = inject(DestroyRef);
3218
3230
  const holds = injectScrollRestorationHolds();
3219
3231
  const restoreEnabled = config.restore?.enabled === true;
3220
3232
  const restoreTimeout = config.restore?.timeout ?? DEFAULT_RESTORE_TIMEOUT;
@@ -3226,15 +3238,16 @@ const setupScrollRestoration = (config = {}) => {
3226
3238
  };
3227
3239
  // The browser restores the offset against the still-loading (much shorter) document, which is the
3228
3240
  // exact problem we are solving - take it over completely.
3229
- if (restoreEnabled && 'scrollRestoration' in history) {
3241
+ const previousScrollRestoration = 'scrollRestoration' in history ? history.scrollRestoration : null;
3242
+ if (restoreEnabled && previousScrollRestoration !== null) {
3230
3243
  history.scrollRestoration = 'manual';
3231
3244
  }
3232
3245
  /** Saved offsets keyed by the router's per-history-entry `navigationId`, in least-recent-first order. */
3233
3246
  const positions = new Map();
3234
3247
  // Mirrors Angular's own `RouterScroller`: the offset of the currently displayed page belongs to
3235
3248
  // the navigation that produced it, and a popstate reports the id of the entry it moves to.
3236
- let lastNavigationId = 0;
3237
- let restoredNavigationId = 0;
3249
+ let lastNavigationId = null;
3250
+ let restoredNavigationId = null;
3238
3251
  let isPopstate = false;
3239
3252
  let wantsRestore = false;
3240
3253
  let prev = { state: createRouterState(router), route: createRoute(router) };
@@ -3250,7 +3263,7 @@ const setupScrollRestoration = (config = {}) => {
3250
3263
  let cancelled = false;
3251
3264
  // The user scrolling always wins over a restoration we have not committed yet.
3252
3265
  const abortByUser = () => cancelPendingRestore();
3253
- const hardDeadline = Date.now() + Math.max(restoreTimeout, restoreMaxTimeout);
3266
+ const hardDeadline = Date.now() + restoreMaxTimeout;
3254
3267
  let deadline = Date.now() + restoreTimeout;
3255
3268
  const step = () => {
3256
3269
  frame = 0;
@@ -3329,19 +3342,21 @@ const setupScrollRestoration = (config = {}) => {
3329
3342
  return;
3330
3343
  // Re-inserted rather than overwritten so map order stays least-recently-left first, which is both
3331
3344
  // what `findLastVisitedOffset` walks backwards and what the cap below evicts from.
3332
- positions.delete(lastNavigationId);
3333
- positions.set(lastNavigationId, {
3334
- top: resolveScrollElement().scrollTop,
3335
- route: prev.route,
3336
- search: serializeQueryParams(prev.state.queryParams),
3337
- });
3345
+ if (lastNavigationId !== null) {
3346
+ positions.delete(lastNavigationId);
3347
+ positions.set(lastNavigationId, {
3348
+ top: resolveScrollElement().scrollTop,
3349
+ route: prev.route,
3350
+ search: serializeQueryParams(prev.state.queryParams),
3351
+ });
3352
+ }
3338
3353
  if (positions.size > MAX_STORED_POSITIONS) {
3339
3354
  const oldest = positions.keys().next();
3340
3355
  if (!oldest.done)
3341
3356
  positions.delete(oldest.value);
3342
3357
  }
3343
3358
  isPopstate = event.navigationTrigger === 'popstate';
3344
- restoredNavigationId = event.restoredState?.navigationId ?? 0;
3359
+ restoredNavigationId = event.restoredState?.navigationId ?? null;
3345
3360
  // Read off the navigation rather than `history.state`: a symbol key does not survive being
3346
3361
  // structured-cloned into the history entry, which is what keeps the mark from outliving this
3347
3362
  // navigation and re-firing when the user later pops back to the entry it created.
@@ -3363,10 +3378,10 @@ const setupScrollRestoration = (config = {}) => {
3363
3378
  else {
3364
3379
  // A skipped same url navigation is not a history move, so there is nothing to restore.
3365
3380
  isPopstate = false;
3366
- restoredNavigationId = 0;
3381
+ restoredNavigationId = null;
3367
3382
  }
3368
3383
  if (restoreEnabled && isPopstate) {
3369
- const target = positions.get(restoredNavigationId);
3384
+ const target = restoredNavigationId === null ? undefined : positions.get(restoredNavigationId);
3370
3385
  // The saved offset wins over both scroll to top and fragment scrolling: the user may well have
3371
3386
  // scrolled away from the anchor before leaving the page.
3372
3387
  if (target !== undefined) {
@@ -3420,22 +3435,31 @@ const setupScrollRestoration = (config = {}) => {
3420
3435
  }
3421
3436
  onNavigationEnd(event);
3422
3437
  });
3438
+ destroyRef.onDestroy(() => {
3439
+ cancelPendingRestore();
3440
+ if (restoreEnabled && previousScrollRestoration !== null) {
3441
+ history.scrollRestoration = previousScrollRestoration;
3442
+ }
3443
+ });
3423
3444
  };
3424
3445
 
3425
3446
  const DISABLE_LOGGER_PARAM = 'et-logger-quiet';
3426
3447
  const createLogger = (config) => {
3427
3448
  const { scope, feature } = config;
3428
3449
  const disableLogging = injectQueryParam(DISABLE_LOGGER_PARAM);
3429
- const writeLog = (...args) => {
3430
- if (disableLogging()) {
3431
- return;
3432
- }
3433
- console.log(...args);
3434
- };
3435
3450
  return {
3436
- log: (...args) => writeLog(`\x1B[32;40;24m[${scope} ${feature}]\x1B[m`, ...args),
3437
- warn: (...args) => writeLog(`\x1B[93;40;24m[${scope} ${feature}]\x1B[m`, ...args),
3438
- error: (...args) => writeLog(`\x1B[31;40;24m[${scope} ${feature}]\x1B[m`, ...args),
3451
+ log: (...args) => {
3452
+ if (!disableLogging())
3453
+ console.log(`\x1B[32;40;24m[${scope} ${feature}]\x1B[m`, ...args);
3454
+ },
3455
+ warn: (...args) => {
3456
+ if (!disableLogging())
3457
+ console.warn(`\x1B[93;40;24m[${scope} ${feature}]\x1B[m`, ...args);
3458
+ },
3459
+ error: (...args) => {
3460
+ if (!disableLogging())
3461
+ console.error(`\x1B[31;40;24m[${scope} ${feature}]\x1B[m`, ...args);
3462
+ },
3439
3463
  };
3440
3464
  };
3441
3465
 
@@ -3448,12 +3472,15 @@ const escapeHtmlPreservingEntities = (str) => str
3448
3472
  .replace(/</g, '&lt;')
3449
3473
  .replace(/>/g, '&gt;')
3450
3474
  .replace(/"/g, '&quot;');
3451
- /** Rejects URL schemes that execute script when navigated. Whitespace/control characters are
3452
- * stripped before checking - browsers ignore them inside URLs, so `java\tscript:` would
3453
- * otherwise slip through. */
3454
- const isSafeUrl = (url) =>
3455
- // eslint-disable-next-line no-control-regex -- stripping control characters is the point: browsers ignore them inside URLs
3456
- !/^(javascript|data|vbscript):/i.test(url.replace(/[\s\u0000-\u001f]/g, ''));
3475
+ const decodeUrlCharacterReferences = (url) => url
3476
+ .replace(/&#(\d+);?/g, (_, value) => String.fromCodePoint(Number(value)))
3477
+ .replace(/&#x([0-9a-f]+);?/gi, (_, value) => String.fromCodePoint(Number.parseInt(value, 16)))
3478
+ .replace(/&(colon|tab|newline);/gi, (_, entity) => entity.toLowerCase() === 'colon' ? ':' : entity.toLowerCase() === 'tab' ? '\t' : '\n');
3479
+ const isSafeUrl = (url) => {
3480
+ // eslint-disable-next-line no-control-regex -- URL parsers ignore these characters inside schemes.
3481
+ const normalized = decodeUrlCharacterReferences(url).replace(/[\s\u0000-\u001f]/g, '');
3482
+ return (!/^(javascript|vbscript):/i.test(normalized) && !/^data:(?!image\/(?:avif|gif|jpeg|png|webp);)/i.test(normalized));
3483
+ };
3457
3484
  const unescapeHtml = (str) => str
3458
3485
  .replace(/&amp;/g, '&')
3459
3486
  .replace(/&lt;/g, '<')
@@ -3548,7 +3575,6 @@ const processInline = (text) => {
3548
3575
  .replace(placeholderRe('IC'), (_, i) => inlineCodes[+i] ?? '')
3549
3576
  .replace(placeholderRe('NTLINK'), (_, i) => newTabLinks[+i] ?? '');
3550
3577
  };
3551
- // --- Nested list helpers (regex can't match balanced nesting, so these scan by tag depth) ---
3552
3578
  /** The first top-level `<ul>`/`<ol>` in `html`, matched with balanced nesting. */
3553
3579
  const findList = (html) => {
3554
3580
  const open = /<(ul|ol)\b[^>]*>/i.exec(html);
@@ -3981,7 +4007,6 @@ class RuntimeError extends Error {
3981
4007
  }
3982
4008
  }
3983
4009
  function formatRuntimeError(code, message) {
3984
- // prefix code with zeros if it's less than 100
3985
4010
  const codeWithZeros = code < 10 ? `00${code}` : code < 100 ? `0${code}` : code;
3986
4011
  const fullCode = `ET${codeWithZeros}`;
3987
4012
  return `${fullCode}${message ? ': ' + message : ''}`;
@@ -4113,11 +4138,13 @@ const createSwipeTracker = (startEvent) => {
4113
4138
  const positiveMovementX = Math.abs(movementX);
4114
4139
  const positiveMovementY = Math.abs(movementY);
4115
4140
  if (!isSwiping && !isScrolling) {
4116
- if (positiveMovementY > positiveMovementX) {
4117
- isScrolling = true;
4118
- }
4119
- else {
4120
- isSwiping = true;
4141
+ if (positiveMovementY > 0 || positiveMovementX > 0) {
4142
+ if (positiveMovementY > positiveMovementX) {
4143
+ isScrolling = true;
4144
+ }
4145
+ else {
4146
+ isSwiping = true;
4147
+ }
4121
4148
  }
4122
4149
  }
4123
4150
  return {
@@ -4216,20 +4243,26 @@ const suppressTextSelection = (doc) => {
4216
4243
 
4217
4244
  const ANGULAR_ROOT_ELEMENT_DEF = /* @__PURE__ */ defineRootProvider(() => {
4218
4245
  const appRef = inject(ApplicationRef);
4246
+ const destroyRef = inject(DestroyRef);
4219
4247
  const rootElement = signal(null, /* @ts-ignore */
4220
4248
  ...(ngDevMode ? [{ debugName: "rootElement" }] : /* istanbul ignore next */ []));
4249
+ let pollId = null;
4221
4250
  const poll = () => {
4222
4251
  const appComponents = appRef.components;
4223
4252
  if (appComponents.length > 0) {
4224
4253
  rootElement.set(appComponents[0]?.location.nativeElement);
4225
4254
  }
4226
4255
  else {
4227
- setTimeout(poll, 25);
4256
+ pollId = setTimeout(poll, 25);
4228
4257
  }
4229
4258
  };
4230
- setTimeout(poll);
4259
+ pollId = setTimeout(poll);
4260
+ destroyRef.onDestroy(() => {
4261
+ if (pollId !== null)
4262
+ clearTimeout(pollId);
4263
+ });
4231
4264
  return rootElement;
4232
- });
4265
+ }, { name: 'Angular Root Element' });
4233
4266
  const injectAngularRootElement = /* @__PURE__ */ toInjectFn(ANGULAR_ROOT_ELEMENT_DEF);
4234
4267
 
4235
4268
  const BOUNDARY_ELEMENT_DEF = /* @__PURE__ */ defineProvider(() => {
@@ -4293,10 +4326,10 @@ const FOCUS_VISIBLE_TRACKER_DEF = /* @__PURE__ */ defineRootProvider(() => {
4293
4326
  ...(ngDevMode ? [{ debugName: "isFocusVisible" }] : /* istanbul ignore next */ []));
4294
4327
  let hadKeyboardEvent = false;
4295
4328
  const onKeyDown = (e) => {
4296
- if (e.key === 'Tab' || e.key === 'Shift' || e.key === 'Meta' || e.key === 'Alt' || e.key === 'Control') {
4297
- hadKeyboardEvent = true;
4298
- queueMicrotask(() => isFocusVisible.set(true));
4299
- }
4329
+ if (e.metaKey || e.altKey || e.ctrlKey || ['Shift', 'Meta', 'Alt', 'Control'].includes(e.key))
4330
+ return;
4331
+ hadKeyboardEvent = true;
4332
+ queueMicrotask(() => isFocusVisible.set(true));
4300
4333
  };
4301
4334
  const onPointerDown = () => {
4302
4335
  hadKeyboardEvent = false;
@@ -4471,6 +4504,9 @@ const createUserConsentProvider = (options) => ({
4471
4504
  });
4472
4505
 
4473
4506
  const nextFrame = (cb) => {
4507
+ if (typeof requestAnimationFrame === 'undefined') {
4508
+ return;
4509
+ }
4474
4510
  requestAnimationFrame(() => {
4475
4511
  requestAnimationFrame(cb);
4476
4512
  });
@@ -4526,8 +4562,8 @@ class AnimatedLifecycleDirective {
4526
4562
  this.element = this.elementRef.nativeElement;
4527
4563
  this.isConstructed = false;
4528
4564
  this.transitionIdCounter = 0;
4529
- this.forcedAtFrameId = null;
4530
- this.currentFrameId = 0;
4565
+ this.forcedThisFrame = false;
4566
+ this.forcedFrameResetId = null;
4531
4567
  this.state$ = new BehaviorSubject('init');
4532
4568
  this.stateChange = outputFromObservable(this.state$);
4533
4569
  this.skipNextEnter = model(false, /* @ts-ignore */
@@ -4542,15 +4578,9 @@ class AnimatedLifecycleDirective {
4542
4578
  }
4543
4579
  }), takeUntilDestroyed())
4544
4580
  .subscribe();
4545
- this.trackFrameId();
4546
- }
4547
- trackFrameId() {
4548
- const updateFrameId = () => {
4549
- this.currentFrameId = requestAnimationFrame(updateFrameId);
4550
- };
4551
- this.currentFrameId = requestAnimationFrame(updateFrameId);
4552
4581
  this.destroyRef.onDestroy(() => {
4553
- cancelAnimationFrame(this.currentFrameId);
4582
+ if (this.forcedFrameResetId !== null)
4583
+ cancelAnimationFrame(this.forcedFrameResetId);
4554
4584
  });
4555
4585
  }
4556
4586
  ngAfterViewInit() {
@@ -4565,7 +4595,7 @@ class AnimatedLifecycleDirective {
4565
4595
  this.updateState('entered');
4566
4596
  this.skipNextEnter.set(false);
4567
4597
  this.addClass(ANIMATION_CLASSES.enterDone);
4568
- this.forcedAtFrameId = null;
4598
+ this.forcedThisFrame = false;
4569
4599
  return;
4570
4600
  }
4571
4601
  const isInterrupting = currentState === 'leaving';
@@ -4575,8 +4605,8 @@ class AnimatedLifecycleDirective {
4575
4605
  this.cancelCurrentAnimation$ = new Subject();
4576
4606
  const transitionId = `enter-${++this.transitionIdCounter}`;
4577
4607
  this.animatable.setTransitionId(transitionId);
4578
- const skipAnimation = this.forcedAtFrameId !== null && this.forcedAtFrameId === this.currentFrameId;
4579
- this.forcedAtFrameId = null;
4608
+ const skipAnimation = this.forcedThisFrame;
4609
+ this.forcedThisFrame = false;
4580
4610
  this.debugLog(`enter: ${skipAnimation ? 'skip (forced this frame)' : isInterrupting ? 'interrupting leave' : 'normal'}`, {
4581
4611
  currentState,
4582
4612
  transitionId,
@@ -4634,7 +4664,7 @@ class AnimatedLifecycleDirective {
4634
4664
  this.debugLog('leave: instant (state is init, enter never ran)');
4635
4665
  this.updateState('left');
4636
4666
  this.addClass(ANIMATION_CLASSES.leaveDone);
4637
- this.forcedAtFrameId = null;
4667
+ this.forcedThisFrame = false;
4638
4668
  return;
4639
4669
  }
4640
4670
  const isInterrupting = currentState === 'entering';
@@ -4644,8 +4674,8 @@ class AnimatedLifecycleDirective {
4644
4674
  this.cancelCurrentAnimation$ = new Subject();
4645
4675
  const transitionId = `leave-${++this.transitionIdCounter}`;
4646
4676
  this.animatable.setTransitionId(transitionId);
4647
- const skipAnimation = this.forcedAtFrameId !== null && this.forcedAtFrameId === this.currentFrameId;
4648
- this.forcedAtFrameId = null;
4677
+ const skipAnimation = this.forcedThisFrame;
4678
+ this.forcedThisFrame = false;
4649
4679
  this.debugLog(`leave: ${skipAnimation ? 'skip (forced this frame)' : isInterrupting ? 'interrupting enter' : 'normal'}`, {
4650
4680
  currentState,
4651
4681
  transitionId,
@@ -4700,14 +4730,25 @@ class AnimatedLifecycleDirective {
4700
4730
  this.updateState('entered');
4701
4731
  this.removeClasses(ANIMATION_CLASSES.enterFrom, ANIMATION_CLASSES.enterActive, ANIMATION_CLASSES.enterTo, ANIMATION_CLASSES.leaveFrom, ANIMATION_CLASSES.leaveActive, ANIMATION_CLASSES.leaveTo);
4702
4732
  this.addClass(ANIMATION_CLASSES.enterDone);
4703
- this.forcedAtFrameId = this.currentFrameId;
4733
+ this.markForcedThisFrame();
4704
4734
  }
4705
4735
  forceLeftState() {
4706
4736
  this.cancelCurrentAnimation$.next();
4707
4737
  this.updateState('left');
4708
4738
  this.removeClasses(ANIMATION_CLASSES.enterFrom, ANIMATION_CLASSES.enterActive, ANIMATION_CLASSES.enterTo, ANIMATION_CLASSES.leaveFrom, ANIMATION_CLASSES.leaveActive, ANIMATION_CLASSES.leaveTo);
4709
4739
  this.addClass(ANIMATION_CLASSES.leaveDone);
4710
- this.forcedAtFrameId = this.currentFrameId;
4740
+ this.markForcedThisFrame();
4741
+ }
4742
+ markForcedThisFrame() {
4743
+ this.forcedThisFrame = true;
4744
+ if (typeof requestAnimationFrame === 'undefined')
4745
+ return;
4746
+ if (this.forcedFrameResetId !== null)
4747
+ cancelAnimationFrame(this.forcedFrameResetId);
4748
+ this.forcedFrameResetId = requestAnimationFrame(() => {
4749
+ this.forcedThisFrame = false;
4750
+ this.forcedFrameResetId = null;
4751
+ });
4711
4752
  }
4712
4753
  handleNormalTransition(config) {
4713
4754
  const { fromClass, activeClass, toClass, expectedState, transitionId, onComplete, cancelSignal } = config;
@@ -4825,7 +4866,7 @@ class AnimatedIfDirective {
4825
4866
  return of(null);
4826
4867
  }
4827
4868
  this.animatedLifecycle.leave();
4828
- return this.animatedLifecycle.state$.pipe(filter((state) => state === 'left'), tap(() => {
4869
+ return this.animatedLifecycle.state$.pipe(filter((state) => state === 'left'), take(1), tap(() => {
4829
4870
  this.viewContainerRef.clear();
4830
4871
  this.hasView = false;
4831
4872
  }));
@@ -4897,16 +4938,23 @@ const createFlipAnimation = (config) => {
4897
4938
  onCancel$.next();
4898
4939
  };
4899
4940
  const cleanup = () => {
4900
- if (!animation) {
4941
+ const currentAnimation = animation;
4942
+ if (!currentAnimation) {
4901
4943
  return;
4902
4944
  }
4903
- animation.removeEventListener('finish', onAnimationFinish);
4904
- animation.removeEventListener('cancel', onAnimationCancel);
4945
+ currentAnimation.removeEventListener('finish', onAnimationFinish);
4946
+ currentAnimation.removeEventListener('cancel', onAnimationCancel);
4947
+ animation = null;
4948
+ currentAnimation.cancel();
4905
4949
  };
4906
4950
  const updateInit = () => {
4907
4951
  initialRect = originElement.getBoundingClientRect();
4908
4952
  };
4909
4953
  const play = () => {
4954
+ if (animation) {
4955
+ cleanup();
4956
+ onCancel$.next();
4957
+ }
4910
4958
  const lastRect = el.getBoundingClientRect();
4911
4959
  const delta = {
4912
4960
  x: initialRect.left - lastRect.left,
@@ -4940,8 +4988,10 @@ const createFlipAnimation = (config) => {
4940
4988
  onStart$.next();
4941
4989
  };
4942
4990
  const cancel = () => {
4943
- animation?.cancel();
4991
+ if (!animation)
4992
+ return;
4944
4993
  cleanup();
4994
+ onCancel$.next();
4945
4995
  };
4946
4996
  return {
4947
4997
  updateInit,
@@ -5108,36 +5158,38 @@ const applyHeadBinding = (binding, applyFn, removeFn, isValid) => {
5108
5158
  const createPropertyBinding = (configBuilder, applyConfigFn) => {
5109
5159
  return (binding) => {
5110
5160
  applyConfigFn(computed(() => {
5111
- const value = untracked(() => (isSignal(binding) ? binding() : binding));
5161
+ const value = isSignal(binding) ? binding() : binding;
5112
5162
  return value ? configBuilder(value) : null;
5113
5163
  }));
5114
5164
  };
5115
5165
  };
5116
5166
  const createArrayPropertyBinding = (configBuilder, applyConfigFn) => {
5117
5167
  return (binding) => {
5168
+ const injector = inject(Injector);
5118
5169
  const valuesSignal = isSignal(binding) ? binding : signal(binding);
5119
- const valuesList = computed(() => untracked(() => valuesSignal()) ?? [], /* @ts-ignore */
5120
- ...(ngDevMode ? [{ debugName: "valuesList" }] : /* istanbul ignore next */ []));
5121
- valuesList().forEach((value, index) => {
5122
- applyConfigFn(computed(() => configBuilder(value, index)));
5170
+ let bindingCount = 0;
5171
+ effect(() => {
5172
+ const values = valuesSignal() ?? [];
5173
+ untracked(() => {
5174
+ while (bindingCount < values.length) {
5175
+ const index = bindingCount++;
5176
+ runInInjectionContext(injector, () => {
5177
+ applyConfigFn(computed(() => {
5178
+ const value = valuesSignal()?.[index];
5179
+ return value === undefined ? null : configBuilder(value, index);
5180
+ }));
5181
+ });
5182
+ }
5183
+ });
5123
5184
  });
5124
5185
  };
5125
5186
  };
5126
5187
  const toStringBinding = (binding) => {
5127
5188
  return computed(() => {
5128
- const value = untracked(() => (isSignal(binding) ? binding() : binding));
5189
+ const value = isSignal(binding) ? binding() : binding;
5129
5190
  return value !== null && value !== undefined ? String(value) : null;
5130
5191
  });
5131
5192
  };
5132
- const createBulkPropertyBinding = (_propertyPrefix, applyConfigFn) => {
5133
- return (config) => {
5134
- Object.entries(config).forEach(([key, value]) => {
5135
- if (value !== undefined) {
5136
- applyConfigFn(key, value);
5137
- }
5138
- });
5139
- };
5140
- };
5141
5193
 
5142
5194
  /** The rendered favicon is this many device-independent pixels square. */
5143
5195
  const FAVICON_SIZE = 64;
@@ -5486,7 +5538,7 @@ const applyLinkBinding = (binding) => {
5486
5538
  const applyCanonicalBinding = /* @__PURE__ */ createPropertyBinding((href) => ({ rel: 'canonical', href }), applyLinkBinding);
5487
5539
  const applyAlternateBinding = (hreflang, binding) => {
5488
5540
  applyLinkBinding(computed(() => {
5489
- const url = untracked(() => (isSignal(binding) ? binding() : binding));
5541
+ const url = isSignal(binding) ? binding() : binding;
5490
5542
  return url ? { rel: 'alternate', hreflang, href: url } : null;
5491
5543
  }));
5492
5544
  };
@@ -5705,6 +5757,8 @@ const META_STORE_DEF = /* @__PURE__ */ defineRootProvider(() => {
5705
5757
  return `http-equiv="${config.httpEquiv}"`;
5706
5758
  if (config.itemprop)
5707
5759
  return `itemprop="${config.itemprop}"`;
5760
+ if (config.charset)
5761
+ return `charset="${config.charset}"`;
5708
5762
  return config.key ?? '';
5709
5763
  };
5710
5764
  const isMultiInstanceTag = (selector) => {
@@ -5815,14 +5869,14 @@ const applyMetaBinding = (binding) => {
5815
5869
  const applyDescriptionBinding = /* @__PURE__ */ createPropertyBinding((content) => ({ name: 'description', content }), applyMetaBinding);
5816
5870
  const applyKeywordsBinding = (binding) => {
5817
5871
  applyMetaBinding(computed(() => {
5818
- const keywords = untracked(() => (isSignal(binding) ? binding() : binding));
5872
+ const keywords = isSignal(binding) ? binding() : binding;
5819
5873
  return keywords && keywords.length > 0 ? { name: 'keywords', content: keywords.join(', ') } : null;
5820
5874
  }));
5821
5875
  };
5822
5876
  const applyAuthorBinding = /* @__PURE__ */ createPropertyBinding((content) => ({ name: 'author', content }), applyMetaBinding);
5823
5877
  const applyRobotsBinding = (binding) => {
5824
5878
  applyMetaBinding(computed(() => {
5825
- const config = untracked(() => (isSignal(binding) ? binding() : binding));
5879
+ const config = isSignal(binding) ? binding() : binding;
5826
5880
  if (!config)
5827
5881
  return null;
5828
5882
  const directives = [];
@@ -5950,19 +6004,19 @@ const applySocialMediaBindings = (config) => {
5950
6004
  applyDescriptionBinding(config.description);
5951
6005
  if (config.openGraph || config.title || config.description || config.image || config.url) {
5952
6006
  applyOpenGraphBindings({
6007
+ ...config.openGraph,
5953
6008
  title: config.openGraph?.title ?? config.title,
5954
6009
  description: config.openGraph?.description ?? config.description,
5955
6010
  image: config.openGraph?.image ?? config.image,
5956
6011
  url: config.openGraph?.url ?? config.url,
5957
- ...config.openGraph,
5958
6012
  });
5959
6013
  }
5960
6014
  if (config.twitter || config.title || config.description || config.image) {
5961
6015
  applyTwitterCardBindings({
6016
+ ...config.twitter,
5962
6017
  title: config.twitter?.title ?? config.title,
5963
6018
  description: config.twitter?.description ?? config.description,
5964
6019
  image: config.twitter?.image ?? config.image,
5965
- ...config.twitter,
5966
6020
  });
5967
6021
  }
5968
6022
  if (config.article)
@@ -5992,9 +6046,6 @@ const STRUCTURED_DATA_STORE_DEF = /* @__PURE__ */ defineRootProvider(() => {
5992
6046
  }
5993
6047
  const script = renderer.createElement('script');
5994
6048
  renderer.setAttributes(script, { type: 'application/ld+json' });
5995
- // The JSON is the script's *content*, not an attribute. Written as text rather than markup so a
5996
- // `</script>` inside a string can't close the tag early - the escaping problem
5997
- // `StructuredDataComponent` has to solve by hand because it goes through `innerHTML`.
5998
6049
  renderer.setTextContent(script, JSON.stringify(data));
5999
6050
  const target = getTargetElement();
6000
6051
  renderer.appendChild(target, script);
@@ -6033,7 +6084,7 @@ class StructuredDataComponent {
6033
6084
  if (!data) {
6034
6085
  return null;
6035
6086
  }
6036
- const json = data ? JSON.stringify(data, null, 2).replace(/<\/script>/g, '<\\/script>') : '';
6087
+ const json = JSON.stringify(data, null, 2).replace(/</g, '\\u003C');
6037
6088
  const html = `<script type="application/ld+json">${json}</script>`;
6038
6089
  return this.sanitizer.bypassSecurityTrustHtml(html);
6039
6090
  }, /* @ts-ignore */
@@ -6060,19 +6111,18 @@ const UNSAVED_CHANGES_TITLE_MARKER = '●';
6060
6111
  // The badge is a single app-wide surface, so every lock that wants one registers here and the badge
6061
6112
  // is derived from all of them - otherwise the first tracker to go clean would clear a badge that
6062
6113
  // another one still needs.
6063
- const BADGE_HOLDERS = /* @__PURE__ */ new Map();
6064
- const syncAppBadge = () => {
6065
- const nav = typeof navigator === 'undefined' ? null : navigator;
6114
+ const BADGE_HOLDERS = /* @__PURE__ */ new WeakMap();
6115
+ const syncAppBadge = (nav, badgeHolders) => {
6066
6116
  if (!nav?.setAppBadge || !nav.clearAppBadge) {
6067
6117
  return;
6068
6118
  }
6069
6119
  // Unsupported, or not installed - the promise rejects instead of throwing synchronously.
6070
6120
  const ignore = () => undefined;
6071
- if (!BADGE_HOLDERS.size) {
6121
+ if (!badgeHolders.size) {
6072
6122
  nav.clearAppBadge().catch(ignore);
6073
6123
  return;
6074
6124
  }
6075
- const count = Array.from(BADGE_HOLDERS.values()).reduce((total, contents) => (typeof contents === 'number' ? total + contents : total), 0);
6125
+ const count = Array.from(badgeHolders.values()).reduce((total, contents) => (typeof contents === 'number' ? total + contents : total), 0);
6076
6126
  // `setAppBadge()` without a count renders a plain dot.
6077
6127
  nav.setAppBadge(count || undefined).catch(ignore);
6078
6128
  };
@@ -6104,9 +6154,10 @@ const createUnsavedChangesTabLock = (config) => {
6104
6154
  // Blinking needs something to blink, so it implies the default marker.
6105
6155
  const titleMarker = config.titleMarker === true
6106
6156
  ? UNSAVED_CHANGES_TITLE_MARKER
6107
- : (config.titleMarker ?? (flash && !favicon ? UNSAVED_CHANGES_TITLE_MARKER : null));
6157
+ : (config.titleMarker ?? (flash ? UNSAVED_CHANGES_TITLE_MARKER : null));
6108
6158
  const destroyRef = inject(DestroyRef);
6109
6159
  const isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
6160
+ const navigator = inject(DOCUMENT).defaultView?.navigator;
6110
6161
  const releaseFns = [];
6111
6162
  // The blink phase. Always `true` unless flashing is on, so the marker/favicon effects below can read
6112
6163
  // one signal either way.
@@ -6197,26 +6248,31 @@ const createUnsavedChangesTabLock = (config) => {
6197
6248
  detach();
6198
6249
  });
6199
6250
  }
6200
- if (isBrowser && badge !== false) {
6251
+ if (isBrowser && navigator && badge !== false) {
6201
6252
  const badgeId = Symbol('unsaved-changes-badge');
6202
6253
  const contents = badge === true ? true : badge;
6254
+ let badgeHolders = BADGE_HOLDERS.get(navigator);
6255
+ if (!badgeHolders) {
6256
+ badgeHolders = new Map();
6257
+ BADGE_HOLDERS.set(navigator, badgeHolders);
6258
+ }
6203
6259
  const badgeEffect = effect(() => {
6204
6260
  const dirty = hasChanges();
6205
6261
  untracked(() => {
6206
6262
  if (dirty) {
6207
- BADGE_HOLDERS.set(badgeId, contents);
6263
+ badgeHolders.set(badgeId, contents);
6208
6264
  }
6209
6265
  else {
6210
- BADGE_HOLDERS.delete(badgeId);
6266
+ badgeHolders.delete(badgeId);
6211
6267
  }
6212
- syncAppBadge();
6268
+ syncAppBadge(navigator, badgeHolders);
6213
6269
  });
6214
6270
  }, /* @ts-ignore */
6215
6271
  ...(ngDevMode ? [{ debugName: "badgeEffect" }] : /* istanbul ignore next */ []));
6216
6272
  releaseFns.push(() => {
6217
6273
  badgeEffect.destroy();
6218
- BADGE_HOLDERS.delete(badgeId);
6219
- syncAppBadge();
6274
+ badgeHolders.delete(badgeId);
6275
+ syncAppBadge(navigator, badgeHolders);
6220
6276
  });
6221
6277
  }
6222
6278
  const destroy = () => {
@@ -6282,6 +6338,9 @@ const createUnsavedChangesTracker = (config) => {
6282
6338
  return false;
6283
6339
  }
6284
6340
  const defaultValue = _defaultValue();
6341
+ if (defaultValue === null || defaultValue === undefined) {
6342
+ return false;
6343
+ }
6285
6344
  return !(compareFn ? compareFn(current, defaultValue) : equal(current, defaultValue));
6286
6345
  }, /* @ts-ignore */
6287
6346
  ...(ngDevMode ? [{ debugName: "hasChanges" }] : /* istanbul ignore next */ []));
@@ -6347,7 +6406,7 @@ const isCrossOrigin = (source) => /^(https?:)?\/\//.test(source);
6347
6406
  * Cross-origin scripts are left out: an analytics tag with a cache-busting query would otherwise read
6348
6407
  * as a new deploy on every check.
6349
6408
  */
6350
- const readBuildFingerprint = (document) => Array.from(document.querySelectorAll('script[src]'))
6409
+ const readBuildFingerprint = (document) => Array.from(document.head.querySelectorAll('script[src]'))
6351
6410
  .map((script) => script.getAttribute('src') ?? '')
6352
6411
  .filter((source) => !!source && !isCrossOrigin(source))
6353
6412
  .sort()
@@ -6420,7 +6479,7 @@ const isStaleBuildError = (error) => {
6420
6479
  };
6421
6480
 
6422
6481
  const RELOADED_AT_KEY = 'et-app-update-reloaded-at';
6423
- const APP_UPDATES_CONFIG_DEF = /* @__PURE__ */ defineStaticProvider({
6482
+ const APP_UPDATES_CONFIG_DEF = /* @__PURE__ */ defineStaticRootProvider({
6424
6483
  entryUrl: '/',
6425
6484
  pollInterval: 300_000,
6426
6485
  minCheckInterval: 30_000,
@@ -6634,30 +6693,15 @@ class RepeatDirective {
6634
6693
  this.mainTemplateRef = inject(TemplateRef);
6635
6694
  this.viewContainerRef = inject(ViewContainerRef);
6636
6695
  this.repeatCount = input(2, { ...(ngDevMode ? { debugName: "repeatCount" } : /* istanbul ignore next */ {}), alias: 'etRepeat', transform: numberAttribute });
6637
- this.views = linkedSignal({ ...(ngDevMode ? { debugName: "views" } : /* istanbul ignore next */ {}), source: this.repeatCount,
6638
- computation: (count, previous) => {
6639
- const prevCount = previous?.source ?? 0;
6640
- const views = previous?.value ?? [];
6641
- if (count === prevCount && previous?.value) {
6642
- return previous.value;
6643
- }
6644
- const viewsToCreate = count - prevCount;
6645
- if (viewsToCreate > 0) {
6646
- for (let i = 0; i < viewsToCreate; i++) {
6647
- views.push(this.viewContainerRef.createEmbeddedView(this.mainTemplateRef));
6648
- }
6649
- }
6650
- else if (viewsToCreate < 0) {
6651
- for (let i = 0; i < -viewsToCreate; i++) {
6652
- this.viewContainerRef.remove(this.viewContainerRef.length - 1);
6653
- }
6654
- views.splice(viewsToCreate);
6655
- }
6656
- return views;
6657
- } });
6658
- // Ugly but needed to trigger the linked signal.
6659
- // Otherwise it has no consumers and won't run.
6660
- effect(() => this.views());
6696
+ effect(() => {
6697
+ const count = Math.max(0, this.repeatCount());
6698
+ while (this.viewContainerRef.length < count) {
6699
+ this.viewContainerRef.createEmbeddedView(this.mainTemplateRef);
6700
+ }
6701
+ while (this.viewContainerRef.length > count) {
6702
+ this.viewContainerRef.remove(this.viewContainerRef.length - 1);
6703
+ }
6704
+ });
6661
6705
  }
6662
6706
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: RepeatDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6663
6707
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: RepeatDirective, isStandalone: true, selector: "[etRepeat]", inputs: { repeatCount: { classPropertyName: "repeatCount", publicName: "etRepeat", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
@@ -6727,11 +6771,15 @@ class ScrollObserverDirective {
6727
6771
  this.isAtEnd = computed(() => this._endIntersection()[0]?.isIntersecting ?? false, /* @ts-ignore */
6728
6772
  ...(ngDevMode ? [{ debugName: "isAtEnd" }] : /* istanbul ignore next */ []));
6729
6773
  }
6730
- _registerStart(el) {
6774
+ /** @internal */
6775
+ registerStart(el) {
6731
6776
  this._startEl.set(el);
6777
+ return () => this._startEl.update((current) => (current === el ? null : current));
6732
6778
  }
6733
- _registerEnd(el) {
6779
+ /** @internal */
6780
+ registerEnd(el) {
6734
6781
  this._endEl.set(el);
6782
+ return () => this._endEl.update((current) => (current === el ? null : current));
6735
6783
  }
6736
6784
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ScrollObserverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6737
6785
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", 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 }); }
@@ -6748,7 +6796,7 @@ class ScrollObserverEndDirective {
6748
6796
  constructor() {
6749
6797
  this.elementRef = inject(ElementRef);
6750
6798
  this.host = inject(ScrollObserverDirective);
6751
- this.host._registerEnd(this.elementRef);
6799
+ inject(DestroyRef).onDestroy(this.host.registerEnd(this.elementRef));
6752
6800
  }
6753
6801
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ScrollObserverEndDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6754
6802
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: ScrollObserverEndDirective, isStandalone: true, selector: "[etScrollObserverEnd]", ngImport: i0 }); }
@@ -6764,7 +6812,7 @@ class ScrollObserverStartDirective {
6764
6812
  constructor() {
6765
6813
  this.elementRef = inject(ElementRef);
6766
6814
  this.host = inject(ScrollObserverDirective);
6767
- this.host._registerStart(this.elementRef);
6815
+ inject(DestroyRef).onDestroy(this.host.registerStart(this.elementRef));
6768
6816
  }
6769
6817
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ScrollObserverStartDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6770
6818
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: ScrollObserverStartDirective, isStandalone: true, selector: "[etScrollObserverStart]", ngImport: i0 }); }
@@ -6788,6 +6836,7 @@ const capturePointer = (el, pointerId) => {
6788
6836
  };
6789
6837
  const setupDragObservable = (startEvent, el, commitThreshold) => {
6790
6838
  const { pointerId, clientX: startX, clientY: startY } = startEvent;
6839
+ const document = el.ownerDocument;
6791
6840
  let cancelled = false;
6792
6841
  let endX = startX;
6793
6842
  let endY = startY;
@@ -7198,7 +7247,12 @@ const applyInitialFocus = (paneElement, autoFocus, document) => {
7198
7247
  focusElement(getFocusableElements(paneElement, document)[0] ?? paneElement);
7199
7248
  return;
7200
7249
  }
7201
- focusElement(paneElement.querySelector(autoFocus) ?? paneElement);
7250
+ try {
7251
+ focusElement(paneElement.querySelector(autoFocus) ?? paneElement);
7252
+ }
7253
+ catch {
7254
+ focusElement(paneElement);
7255
+ }
7202
7256
  };
7203
7257
  const setupFocusTrap = (paneElement, overlayRef, enabled, isTopMost, document) => {
7204
7258
  if (!enabled) {
@@ -7217,6 +7271,11 @@ const setupFocusTrap = (paneElement, overlayRef, enabled, isTopMost, document) =
7217
7271
  const firstElement = focusableElements[0];
7218
7272
  const lastElement = focusableElements[focusableElements.length - 1];
7219
7273
  const activeElement = document.activeElement;
7274
+ if (!activeElement || !paneElement.contains(activeElement)) {
7275
+ event.preventDefault();
7276
+ focusElement(event.shiftKey ? (lastElement ?? null) : (firstElement ?? null));
7277
+ return;
7278
+ }
7220
7279
  if (event.shiftKey && activeElement === firstElement) {
7221
7280
  event.preventDefault();
7222
7281
  focusElement(lastElement ?? null);
@@ -7227,9 +7286,9 @@ const setupFocusTrap = (paneElement, overlayRef, enabled, isTopMost, document) =
7227
7286
  focusElement(firstElement ?? null);
7228
7287
  }
7229
7288
  };
7230
- paneElement.addEventListener('keydown', onKeyDown);
7289
+ document.addEventListener('keydown', onKeyDown, true);
7231
7290
  return () => {
7232
- paneElement.removeEventListener('keydown', onKeyDown);
7291
+ document.removeEventListener('keydown', onKeyDown, true);
7233
7292
  };
7234
7293
  };
7235
7294
 
@@ -7417,6 +7476,9 @@ const resetPositioningStyles = (config, hostElement, paneElement, renderer) => {
7417
7476
  '--et-overlay-anchored-y': null,
7418
7477
  });
7419
7478
  renderer.removeAttribute(paneElement, 'data-overlay-placement');
7479
+ const arrowElement = paneElement.querySelector('[et-floating-arrow]');
7480
+ if (arrowElement)
7481
+ renderer.setCssProperty(arrowElement, '--et-floating-arrow-translate', null);
7420
7482
  setBaseElementStyles(config, hostElement, paneElement, renderer);
7421
7483
  };
7422
7484
  let anchoredPositionSetup = null;
@@ -7570,7 +7632,10 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7570
7632
  renderer.setStyle(paneElement, { visibility: 'hidden' });
7571
7633
  }
7572
7634
  };
7635
+ let updateId = 0;
7636
+ let destroyed = false;
7573
7637
  const update = () => {
7638
+ const currentUpdateId = ++updateId;
7574
7639
  // Checked here rather than left to the `hide` middleware, which is only in the list when `autoHide`
7575
7640
  // or `autoCloseIfReferenceHidden` asked for it: a trigger destroyed while its overlay is open (a
7576
7641
  // menu item that removes the button it was opened from) would otherwise fly to the corner for the
@@ -7588,7 +7653,7 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7588
7653
  ? flip({
7589
7654
  fallbackPlacements: strategy.fallbackPlacements ?? undefined,
7590
7655
  fallbackAxisSideDirection: 'start',
7591
- padding: insets,
7656
+ padding: viewportPadding,
7592
7657
  boundary: strategy.boundary,
7593
7658
  })
7594
7659
  : preferredSide({
@@ -7651,6 +7716,8 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7651
7716
  strategy: 'absolute',
7652
7717
  middleware,
7653
7718
  }).then(({ x, y, placement, middlewareData }) => {
7719
+ if (destroyed || currentUpdateId !== updateId)
7720
+ return;
7654
7721
  if (middlewareData.hide?.referenceHidden) {
7655
7722
  handleUnusableReference();
7656
7723
  return;
@@ -7676,6 +7743,8 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
7676
7743
  // scrolling anything `autoUpdate` watches.
7677
7744
  const stopInsetUpdates = onOverlayViewportInsetsChange(update);
7678
7745
  return () => {
7746
+ destroyed = true;
7747
+ updateId++;
7679
7748
  cleanup();
7680
7749
  stopInsetUpdates();
7681
7750
  };
@@ -7723,7 +7792,7 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
7723
7792
  elements,
7724
7793
  state: _state.asReadonly(),
7725
7794
  componentInstance: _componentInstance.asReadonly(),
7726
- // Internal - driven by overlay-runtime.ts
7795
+ /** @internal */
7727
7796
  beforeOpenedSubject,
7728
7797
  close(result, source = 'api') {
7729
7798
  if (_state() === 'closing' || _state() === 'closed') {
@@ -7764,6 +7833,7 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
7764
7833
  afterClosed() {
7765
7834
  return afterClosedSubject.asObservable();
7766
7835
  },
7836
+ /** @internal */
7767
7837
  attachComponentRef(componentRef) {
7768
7838
  _componentInstance.set(componentRef.instance);
7769
7839
  },
@@ -7791,6 +7861,7 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
7791
7861
  }
7792
7862
  backdropUpdater?.(hasBackdrop);
7793
7863
  },
7864
+ /** @internal */
7794
7865
  markOpened() {
7795
7866
  if (_state() !== 'mounting') {
7796
7867
  return;
@@ -7799,6 +7870,7 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
7799
7870
  afterOpenedSubject.next();
7800
7871
  afterOpenedSubject.complete();
7801
7872
  },
7873
+ /** @internal */
7802
7874
  beginClose(closeEvent) {
7803
7875
  if (_state() === 'closing' || _state() === 'closed') {
7804
7876
  return false;
@@ -7808,6 +7880,7 @@ const createOverlayRuntimeRef = (id, config, elements, requestClose) => {
7808
7880
  beforeClosedSubject.complete();
7809
7881
  return true;
7810
7882
  },
7883
+ /** @internal */
7811
7884
  finishClose(closeEvent) {
7812
7885
  if (_state() === 'closed') {
7813
7886
  return;
@@ -7828,8 +7901,7 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
7828
7901
  const renderer = injectRenderer();
7829
7902
  const openEntriesState = signal([], /* @ts-ignore */
7830
7903
  ...(ngDevMode ? [{ debugName: "openEntriesState" }] : /* istanbul ignore next */ []));
7831
- const openEntries = computed(() => openEntriesState(), /* @ts-ignore */
7832
- ...(ngDevMode ? [{ debugName: "openEntries" }] : /* istanbul ignore next */ []));
7904
+ const openEntries = openEntriesState.asReadonly();
7833
7905
  // One runtime root per document and stacking level: overlays usually all mount into the app's
7834
7906
  // document at the default level, but an overlay anchored inside a same-origin pop-up window
7835
7907
  // (config.document) needs a root over there, and one opened from inside something that paints
@@ -7841,12 +7913,6 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
7841
7913
  const getRootElement = (targetDocument, zIndex) => {
7842
7914
  let documentRoots = rootElements.get(targetDocument);
7843
7915
  if (!documentRoots) {
7844
- // A previous Angular app (e.g. the one that existed before a Storybook HMR update or story
7845
- // switch) may have left its runtime root orphaned in <body> if it was torn down mid-animation.
7846
- // Such a node keeps a backdrop/pane on screen and blocks pointer events, so clear any stragglers
7847
- // before creating ours. Only on the document's first root - a second level must not remove the
7848
- // first one's still-mounted overlays.
7849
- targetDocument.querySelectorAll('.et-overlay-runtime-root').forEach((el) => el.remove());
7850
7916
  documentRoots = new Map();
7851
7917
  rootElements.set(targetDocument, documentRoots);
7852
7918
  }
@@ -7892,7 +7958,13 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
7892
7958
  }
7893
7959
  };
7894
7960
  const isTopMost = (overlayRef) => {
7895
- return openEntriesState().at(-1) === overlayRef;
7961
+ const entries = openEntriesState();
7962
+ for (let index = entries.length - 1; index >= 0; index--) {
7963
+ const entry = entries[index];
7964
+ if (entry && entry.state() !== 'closing' && entry.state() !== 'closed')
7965
+ return entry === overlayRef;
7966
+ }
7967
+ return false;
7896
7968
  };
7897
7969
  const getAnimatedLifecycle = (componentRef) => {
7898
7970
  const componentLifecycle = componentRef.instance.animatedLifecycle?.();
@@ -7957,12 +8029,18 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
7957
8029
  let interactiveCloseReady = false;
7958
8030
  const cleanupFns = [];
7959
8031
  const parentInjector = config.injector ?? config.viewContainerRef?.injector ?? environmentInjector;
8032
+ const parentEnvironmentInjector = parentInjector.get(EnvironmentInjector, environmentInjector);
8033
+ const overlayEnvironmentInjector = createEnvironmentInjector(config.providers ?? [], parentEnvironmentInjector);
7960
8034
  const elementInjector = Injector.create({
7961
8035
  parent: parentInjector,
7962
- providers: config.providers ?? [],
8036
+ // Element DI chains to the opener, so without this the opener's environment injector answers
8037
+ // `EnvironmentInjector` from inside the overlay - and a component created through a
8038
+ // ViewContainerRef down there (the container's own content component) never sees
8039
+ // `config.providers`.
8040
+ providers: [{ provide: EnvironmentInjector, useValue: overlayEnvironmentInjector }],
7963
8041
  });
7964
8042
  const componentRef = createComponent(config.component, {
7965
- environmentInjector,
8043
+ environmentInjector: overlayEnvironmentInjector,
7966
8044
  elementInjector,
7967
8045
  hostElement: paneElement,
7968
8046
  bindings: config.bindings ?? [],
@@ -8015,6 +8093,7 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
8015
8093
  if (!elementInjector.destroyed) {
8016
8094
  elementInjector.destroy();
8017
8095
  }
8096
+ overlayEnvironmentInjector.destroy();
8018
8097
  const parentNode = renderer.parentNode(hostElement);
8019
8098
  if (parentNode) {
8020
8099
  renderer.removeChild(parentNode, hostElement);
@@ -8028,7 +8107,11 @@ const OVERLAY_RUNTIME_DEF = /* @__PURE__ */ defineRootProvider(() => {
8028
8107
  };
8029
8108
  // Allows the runtime to synchronously destroy this overlay on app teardown, bypassing the
8030
8109
  // async leave animation (whose completion callback would never fire once the app is gone).
8031
- const forceTeardown = () => destroyMountedOverlay({ result: undefined, source: 'api' });
8110
+ const forceTeardown = () => {
8111
+ const closeEvent = { result: undefined, source: 'api' };
8112
+ overlayRef.beginClose(closeEvent);
8113
+ destroyMountedOverlay(closeEvent);
8114
+ };
8032
8115
  mountedTeardowns.add(forceTeardown);
8033
8116
  cleanupFns.push(() => mountedTeardowns.delete(forceTeardown));
8034
8117
  const beginClose = (closeEvent) => {
@@ -8163,7 +8246,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
8163
8246
  type: Pipe,
8164
8247
  args: [{ name: 'etNormalizeGameResultType' }]
8165
8248
  }] });
8166
- // TODO(TRB): Add correct type once provided by API
8167
8249
  const normalizeGameResultType = (type) => {
8168
8250
  if (!type) {
8169
8251
  return null;
@@ -8209,81 +8291,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
8209
8291
  args: [{ name: 'etNormalizeMatchState' }]
8210
8292
  }] });
8211
8293
  const normalizeMatchState = (match) => {
8294
+ if (!match) {
8295
+ return null;
8296
+ }
8212
8297
  if (match?.isCompletedByReferee) {
8213
- return "autoWin" /* MatchStateType.AUTO_WIN */;
8298
+ return MatchStateType.AUTO_WIN;
8214
8299
  }
8215
8300
  else if (match?.status === 'preparing') {
8216
- return "preMatch" /* MatchStateType.PRE_MATCH */;
8301
+ return MatchStateType.PRE_MATCH;
8217
8302
  }
8218
8303
  else if (match?.status === 'started') {
8219
- return "live" /* MatchStateType.LIVE */;
8304
+ return MatchStateType.LIVE;
8220
8305
  }
8221
8306
  else if (match?.status === 'published' || match?.status === 'finished') {
8222
- return "postMatch" /* MatchStateType.POST_MATCH */;
8307
+ return MatchStateType.POST_MATCH;
8223
8308
  }
8224
- else if (match?.round.state !== 'preparing') {
8225
- return "preparingRound" /* MatchStateType.PREPARING_ROUND */;
8309
+ else if (match.round.state === 'preparing') {
8310
+ return MatchStateType.PREPARING_ROUND;
8226
8311
  }
8227
8312
  return null;
8228
8313
  };
8229
8314
 
8230
- class NormalizeMatchParticipantsPipe {
8231
- constructor() {
8232
- this.transform = normalizeMatchParticipants;
8233
- }
8234
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
8235
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, isStandalone: true, name: "etNormalizeMatchParticipants" }); }
8236
- }
8237
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, decorators: [{
8238
- type: Pipe,
8239
- args: [{ name: 'etNormalizeMatchParticipants' }]
8240
- }] });
8241
- const normalizeMatchParticipants = (match) => {
8242
- const matchState = normalizeMatchState(match);
8243
- if (!match || !matchState) {
8244
- return null;
8245
- }
8246
- return {
8247
- home: normalizeMatchParticipant(match, 'home'),
8248
- away: normalizeMatchParticipant(match, 'away'),
8249
- };
8250
- };
8251
- const normalizeMatchParticipant = (match, side) => {
8252
- const matchState = normalizeMatchState(match);
8253
- if (!match || !matchState) {
8254
- return null;
8255
- }
8256
- const participant = match[side];
8257
- const participantType = match.home?.type ?? match.away?.type ?? 'unknown';
8258
- if (!participant) {
8259
- if (matchState === "postMatch" /* MatchStateType.POST_MATCH */ || matchState === "autoWin" /* MatchStateType.AUTO_WIN */) {
8260
- return {
8261
- participantType,
8262
- type: 'none',
8263
- i18n: 'match-participant.none',
8264
- text: 'No opponent',
8265
- data: participant,
8266
- };
8267
- }
8268
- else {
8269
- return {
8270
- participantType,
8271
- type: 'tbd',
8272
- i18n: 'match-participant.tbd',
8273
- text: 'TBD',
8274
- data: participant,
8275
- };
8276
- }
8277
- }
8278
- else {
8279
- return {
8280
- participantType,
8281
- type: 'participant',
8282
- data: participant,
8283
- };
8284
- }
8285
- };
8286
-
8287
8315
  class NormalizeMatchScorePipe {
8288
8316
  constructor() {
8289
8317
  this.transform = normalizeMatchScore;
@@ -8295,6 +8323,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
8295
8323
  type: Pipe,
8296
8324
  args: [{ name: 'etNormalizeMatchScore' }]
8297
8325
  }] });
8326
+ const MatchStateType = {
8327
+ PREPARING_ROUND: 'preparingRound',
8328
+ PRE_MATCH: 'preMatch',
8329
+ LIVE: 'live',
8330
+ POST_MATCH: 'postMatch',
8331
+ AUTO_WIN: 'autoWin',
8332
+ };
8298
8333
  const EMPTY_SCORE = {
8299
8334
  home: { score: 'match-score.placeholder', isWinner: false },
8300
8335
  away: { score: 'match-score.placeholder', isWinner: false },
@@ -8311,7 +8346,7 @@ const normalizeMatchScore = (match) => {
8311
8346
  return { ...EMPTY_SCORE, subLine, isNumeric: false };
8312
8347
  }
8313
8348
  if (isKnockoutMatch(match)) {
8314
- if (matchState === "preMatch" /* MatchStateType.PRE_MATCH */ || matchState === "live" /* MatchStateType.LIVE */) {
8349
+ if (matchState === MatchStateType.PRE_MATCH || matchState === MatchStateType.LIVE) {
8315
8350
  return { ...EMPTY_SCORE, subLine, isNumeric: false };
8316
8351
  }
8317
8352
  return {
@@ -8329,7 +8364,6 @@ const normalizeMatchScore = (match) => {
8329
8364
  }
8330
8365
  else if (isGroupMatch(match)) {
8331
8366
  if (match.games.length === 1) {
8332
- // Return the score if only one game has been played
8333
8367
  return {
8334
8368
  ...getGroupMatchScore(match),
8335
8369
  subLine,
@@ -8420,6 +8454,63 @@ const getGroupMatchPoints = (match) => {
8420
8454
  };
8421
8455
  };
8422
8456
 
8457
+ class NormalizeMatchParticipantsPipe {
8458
+ constructor() {
8459
+ this.transform = normalizeMatchParticipants;
8460
+ }
8461
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
8462
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, isStandalone: true, name: "etNormalizeMatchParticipants" }); }
8463
+ }
8464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: NormalizeMatchParticipantsPipe, decorators: [{
8465
+ type: Pipe,
8466
+ args: [{ name: 'etNormalizeMatchParticipants' }]
8467
+ }] });
8468
+ const normalizeMatchParticipants = (match) => {
8469
+ const matchState = normalizeMatchState(match);
8470
+ if (!match || !matchState) {
8471
+ return null;
8472
+ }
8473
+ return {
8474
+ home: normalizeMatchParticipant(match, 'home'),
8475
+ away: normalizeMatchParticipant(match, 'away'),
8476
+ };
8477
+ };
8478
+ const normalizeMatchParticipant = (match, side) => {
8479
+ const matchState = normalizeMatchState(match);
8480
+ if (!match || !matchState) {
8481
+ return null;
8482
+ }
8483
+ const participant = match[side];
8484
+ const participantType = match.home?.type ?? match.away?.type ?? 'unknown';
8485
+ if (!participant) {
8486
+ if (matchState === MatchStateType.POST_MATCH || matchState === MatchStateType.AUTO_WIN) {
8487
+ return {
8488
+ participantType,
8489
+ type: 'none',
8490
+ i18n: 'match-participant.none',
8491
+ text: 'No opponent',
8492
+ data: participant,
8493
+ };
8494
+ }
8495
+ else {
8496
+ return {
8497
+ participantType,
8498
+ type: 'tbd',
8499
+ i18n: 'match-participant.tbd',
8500
+ text: 'TBD',
8501
+ data: participant,
8502
+ };
8503
+ }
8504
+ }
8505
+ else {
8506
+ return {
8507
+ participantType,
8508
+ type: 'participant',
8509
+ data: participant,
8510
+ };
8511
+ }
8512
+ };
8513
+
8423
8514
  class NormalizeMatchTypePipe {
8424
8515
  constructor() {
8425
8516
  this.transform = normalizeMatchType;
@@ -8520,14 +8611,9 @@ const inferMimeType = (srcset) => {
8520
8611
  }
8521
8612
  const cleanedUrl = urlParts.join(' ');
8522
8613
  const queryPart = cleanedUrl.split('?')[1] ?? '';
8523
- const containsFm = queryPart.startsWith('fm=') || queryPart.includes('&fm=');
8524
8614
  let fileExtension = null;
8525
- if (containsFm) {
8526
- const fmIndex = queryPart.indexOf('fm=');
8527
- const fmValue = queryPart
8528
- .substring(fmIndex + 3)
8529
- .split('&')[0]
8530
- ?.toLowerCase();
8615
+ if (queryPart) {
8616
+ const fmValue = new URLSearchParams(queryPart).get('fm')?.toLowerCase();
8531
8617
  if (fmValue) {
8532
8618
  fileExtension = fmValue;
8533
8619
  }
@@ -8548,7 +8634,7 @@ const inferMimeType = (srcset) => {
8548
8634
  case 'gif':
8549
8635
  return 'image/gif';
8550
8636
  case 'ico':
8551
- return 'image/vdn.microsoft.icon';
8637
+ return 'image/vnd.microsoft.icon';
8552
8638
  case 'jpg':
8553
8639
  case 'jpeg':
8554
8640
  return 'image/jpeg';
@@ -8620,7 +8706,7 @@ const inferMimeType = (srcset) => {
8620
8706
  case 'mpeg':
8621
8707
  return 'video/mpeg';
8622
8708
  case 'mpkg':
8623
- return 'tapplication/vnd.apple.installer+xml';
8709
+ return 'application/vnd.apple.installer+xml';
8624
8710
  case 'odp':
8625
8711
  return 'application/vnd.oasis.opendocument.presentation';
8626
8712
  case 'ods':
@@ -8877,7 +8963,9 @@ const bindProps = (config) => {
8877
8963
  }
8878
8964
  else if (single) {
8879
8965
  const firstAttachedRefElement = attachedElements.first();
8880
- console.error(`[${name}] These props can only be attached to a single element at a time.\n\n Already attached to \n`, firstAttachedRefElement, '\n Trying to attach to \n', el);
8966
+ if (isDevMode()) {
8967
+ console.error(`[${name}] These props can only be attached to a single element at a time.\n\n Already attached to \n`, firstAttachedRefElement, '\n Trying to attach to \n', el);
8968
+ }
8881
8969
  return;
8882
8970
  }
8883
8971
  }
@@ -8972,13 +9060,15 @@ const createHostProps = (props) => {
8972
9060
  const createSetup = (config) => {
8973
9061
  let didCallSetup = false;
8974
9062
  afterNextRender(() => {
8975
- if (!didCallSetup) {
9063
+ if (!didCallSetup && isDevMode()) {
8976
9064
  console.error('The setup() function was not called. Please call it inside your constructor.', config.this);
8977
9065
  return;
8978
9066
  }
8979
9067
  });
8980
9068
  return (params) => {
8981
9069
  if (didCallSetup) {
9070
+ if (!isDevMode())
9071
+ return;
8982
9072
  console.error('The setup() function was already called. Please call it only once. \n\n', 'Instance containing the setup() call \n', config.this, '\n\n Setup was called with\n', params);
8983
9073
  return;
8984
9074
  }
@@ -9011,19 +9101,23 @@ class PropsDirective {
9011
9101
  this.destroyRef = inject(DestroyRef);
9012
9102
  this.props = input.required({ ...(ngDevMode ? { debugName: "props" } : /* istanbul ignore next */ {}), alias: 'etProps', transform: (d) => d });
9013
9103
  this.propHandlers = createPropHandlers();
9014
- afterNextRender({
9015
- write: () => {
9104
+ let boundProps = null;
9105
+ effect(() => {
9106
+ const props = this.props();
9107
+ untracked(() => {
9108
+ if (boundProps) {
9109
+ unbindProps({ handlers: this.propHandlers, props: boundProps });
9110
+ }
9016
9111
  bindProps({
9017
9112
  handlers: this.propHandlers,
9018
- props: this.props(),
9113
+ props,
9019
9114
  });
9020
- },
9115
+ boundProps = props;
9116
+ });
9021
9117
  });
9022
9118
  this.destroyRef.onDestroy(() => {
9023
- unbindProps({
9024
- handlers: this.propHandlers,
9025
- props: this.props(),
9026
- });
9119
+ if (boundProps)
9120
+ unbindProps({ handlers: this.propHandlers, props: boundProps });
9027
9121
  });
9028
9122
  }
9029
9123
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: PropsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -9038,7 +9132,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
9038
9132
 
9039
9133
  const templateComputed = (templateSignal) => computed(() => {
9040
9134
  const content = templateSignal();
9041
- if (!content)
9135
+ if (content === null)
9042
9136
  return null;
9043
9137
  if (typeof content === 'string') {
9044
9138
  return {
@@ -9091,12 +9185,12 @@ const setupResizeObservable = (startEvent, edge, doc) => {
9091
9185
  const startX = startEvent.clientX;
9092
9186
  const startY = startEvent.clientY;
9093
9187
  let cancelled = false;
9094
- const end$ = merge(fromEvent(document, 'pointerup'), fromEvent(document, 'pointercancel')).pipe(filter((e) => e.pointerId === pointerId), take(1),
9188
+ const end$ = merge(fromEvent(doc, 'pointerup'), fromEvent(doc, 'pointercancel')).pipe(filter((e) => e.pointerId === pointerId), take(1),
9095
9189
  // Read below by the terminating `defer`, which only runs once this has completed the moves.
9096
9190
  tap((e) => (cancelled = e.type === 'pointercancel')));
9097
9191
  return defer(() => {
9098
9192
  const releaseSelection = suppressTextSelection(doc);
9099
- return concat(of({ type: 'start', edge }), fromEvent(document, 'pointermove').pipe(filter((e) => e.pointerId === pointerId), map((e) => ({
9193
+ return concat(of({ type: 'start', edge }), fromEvent(doc, 'pointermove').pipe(filter((e) => e.pointerId === pointerId), map((e) => ({
9100
9194
  type: 'move',
9101
9195
  data: { edge, dx: e.clientX - startX, dy: e.clientY - startY, clientX: e.clientX, clientY: e.clientY },
9102
9196
  })), takeUntil(end$)), defer(() => of({ type: cancelled ? 'cancelled' : 'end' }))).pipe(finalize(releaseSelection));
@@ -9144,7 +9238,7 @@ class ResizeHandlesComponent {
9144
9238
  class="et-resize-handle et-resize-handle--{{ edge }}"
9145
9239
  ></div>
9146
9240
  }
9147
- `, 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-outset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@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:calc(-1 * var(--et-resize-handles-outset));pointer-events:none}.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-corner-size) + var(--et-resize-handles-outset));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-handle-thickness);top:0}.et-resize-handle--s{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness);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-handle-thickness)}.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-handle-corner);height:var(--et-resize-handle-corner)}.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-handle-corner);height:var(--et-resize-handle-corner)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(any-pointer:coarse){.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-touch-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-touch-corner-size) + var(--et-resize-handles-outset))}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
9241
+ `, isInline: true, styles: ["@layer components{@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-outset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@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:calc(-1 * var(--et-resize-handles-outset));pointer-events:none}.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-corner-size) + var(--et-resize-handles-outset));position:absolute;z-index:var(--et-resize-handles-z-index);touch-action:none;pointer-events:auto}.et-resize-handle--n{top:0;right:var(--et-resize-handles-edge-inset);left:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness)}.et-resize-handle--s{right:var(--et-resize-handles-edge-inset);bottom:0;left:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness)}.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-handle-thickness)}.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-handle-corner);height:var(--et-resize-handle-corner)}.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-handle-corner);height:var(--et-resize-handle-corner)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(any-pointer:coarse){.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-touch-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-touch-corner-size) + var(--et-resize-handles-outset))}}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
9148
9242
  }
9149
9243
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ResizeHandlesComponent, decorators: [{
9150
9244
  type: Component,
@@ -9160,16 +9254,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
9160
9254
  class: 'et-resize-handles',
9161
9255
  '[attr.inert]': 'disabled() ? "" : null',
9162
9256
  '[attr.data-active-edge]': 'activeEdge()',
9163
- }, 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-outset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@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:calc(-1 * var(--et-resize-handles-outset));pointer-events:none}.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-corner-size) + var(--et-resize-handles-outset));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-handle-thickness);top:0}.et-resize-handle--s{left:var(--et-resize-handles-edge-inset);right:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness);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-handle-thickness)}.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-handle-corner);height:var(--et-resize-handle-corner)}.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-handle-corner);height:var(--et-resize-handle-corner)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(any-pointer:coarse){.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-touch-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-touch-corner-size) + var(--et-resize-handles-outset))}}\n"] }]
9257
+ }, styles: ["@layer components{@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-outset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@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:calc(-1 * var(--et-resize-handles-outset));pointer-events:none}.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-corner-size) + var(--et-resize-handles-outset));position:absolute;z-index:var(--et-resize-handles-z-index);touch-action:none;pointer-events:auto}.et-resize-handle--n{top:0;right:var(--et-resize-handles-edge-inset);left:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness)}.et-resize-handle--s{right:var(--et-resize-handles-edge-inset);bottom:0;left:var(--et-resize-handles-edge-inset);height:var(--et-resize-handle-thickness)}.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-handle-thickness)}.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-handle-corner);height:var(--et-resize-handle-corner)}.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-handle-corner);height:var(--et-resize-handle-corner)}.et-resize-handle--se{right:0}.et-resize-handle--sw{left:0}@media(any-pointer:coarse){.et-resize-handle{--et-resize-handle-thickness: calc(var(--et-resize-handles-touch-edge-size) + var(--et-resize-handles-outset));--et-resize-handle-corner: calc(var(--et-resize-handles-touch-corner-size) + var(--et-resize-handles-outset))}}}\n"] }]
9164
9258
  }], 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"] }], resizeCancelled: [{ type: i0.Output, args: ["resizeCancelled"] }] } });
9165
9259
 
9166
9260
  class ColorInteractiveStylesComponent {
9167
9261
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ColorInteractiveStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9168
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: ColorInteractiveStylesComponent, isStandalone: true, selector: "et-color-interactive-styles", ngImport: i0, template: '', isInline: true, styles: [":where(.et-color-interactive){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}@media(hover:hover){: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);--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: 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, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[aria-readonly=true]){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, 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"], encapsulation: i0.ViewEncapsulation.None }); }
9262
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: ColorInteractiveStylesComponent, isStandalone: true, selector: "et-color-interactive-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{:where(.et-color-interactive){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}@media(hover:hover){: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);--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: 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, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[aria-readonly=true]){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, 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"], encapsulation: i0.ViewEncapsulation.None }); }
9169
9263
  }
9170
9264
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ColorInteractiveStylesComponent, decorators: [{
9171
9265
  type: Component,
9172
- args: [{ selector: 'et-color-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, styles: [":where(.et-color-interactive){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}@media(hover:hover){: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);--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: 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, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[aria-readonly=true]){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, 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"] }]
9266
+ args: [{ selector: 'et-color-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{:where(.et-color-interactive){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}@media(hover:hover){: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);--et-theme-color-primary-solid: rgb(var(--et-theme-color-primary-rgb));--et-theme-color-on-primary-rgb: 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, var(--et-color-primary));--et-theme-color-ink-solid: rgb(var(--et-theme-color-ink-rgb))}:where(.et-color-interactive[aria-readonly=true]){--et-theme-color-primary-rgb: 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);--et-theme-color-on-primary-solid: rgb(var(--et-theme-color-on-primary-rgb));--et-theme-color-ink-rgb: var(--et-color-primary-ink, 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"] }]
9173
9267
  }] });
9174
9268
 
9175
9269
  /**
@@ -9395,7 +9489,7 @@ class ProvideSurfaceDirective {
9395
9489
  this.currentProviderSync?.destroy();
9396
9490
  runInInjectionContext(this.injector, () => {
9397
9491
  this.currentProviderSync = effect(() => {
9398
- const provideSurface = provider.effectiveSurface();
9492
+ const provideSurface = provider.activeTheme()?.name;
9399
9493
  untracked(() => {
9400
9494
  if (provideSurface === undefined) {
9401
9495
  this.clearForcedSurface();
@@ -9445,7 +9539,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
9445
9539
  */
9446
9540
  const injectSurfaceType = () => {
9447
9541
  const provider = inject(SURFACE_PROVIDER, { optional: true, skipSelf: true });
9448
- const defaultType = injectDefaultSurfaceTheme()?.type ?? SURFACE_TYPE.DARK;
9542
+ const defaultType = injectDefaultSurfaceTheme()?.type ?? null;
9449
9543
  return computed(() => provider?.surfaceType() ?? defaultType);
9450
9544
  };
9451
9545
  /**
@@ -9671,7 +9765,7 @@ const provideColorThemesWithTailwind4 = (themes, prefix = 'et') => {
9671
9765
  return [ɵProvideColorThemes(themes), ɵProvideColorThemesPrefix(prefix)];
9672
9766
  };
9673
9767
  const injectColorThemeByType = (type) => {
9674
- const themes = injectColorThemes();
9768
+ const themes = injectColorThemes({ optional: true });
9675
9769
  if (!themes) {
9676
9770
  throw new Error(`[injectColorThemeByType] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
9677
9771
  }
@@ -9691,7 +9785,7 @@ const injectErrorTheme = () => injectColorThemeByType('error');
9691
9785
  const injectWarningTheme = () => injectColorThemeByType('warning');
9692
9786
  const injectSuccessTheme = () => injectColorThemeByType('success');
9693
9787
  const injectDefaultColorTheme = () => {
9694
- const themes = injectColorThemes();
9788
+ const themes = injectColorThemes({ optional: true });
9695
9789
  if (!themes) {
9696
9790
  throw new Error(`[injectDefaultColorTheme] No color themes provided. Call provideColorThemesWithTailwind4() in your app config.`);
9697
9791
  }
@@ -9743,6 +9837,8 @@ const createSwatchCss = (swatch, isAlt, data) => {
9743
9837
  * @deprecated Migrate to Tailwind v4. Intent to remove in v6.
9744
9838
  */
9745
9839
  const createRootThemeCss = (themes) => {
9840
+ if (typeof document === 'undefined')
9841
+ return;
9746
9842
  const createVars = (name, swatch) => {
9747
9843
  const inkDefault = swatch.inkColor?.default || swatch.color.default;
9748
9844
  const inkHover = swatch.inkColor?.hover || inkDefault;
@@ -9790,6 +9886,7 @@ const createRootThemeCss = (themes) => {
9790
9886
  ${vars.join('\n')}
9791
9887
  }
9792
9888
  `;
9889
+ document.getElementById('et-root-themes')?.remove();
9793
9890
  const style = document.createElement('style');
9794
9891
  style.id = `et-root-themes`;
9795
9892
  style.appendChild(document.createTextNode(css));
@@ -9799,6 +9896,8 @@ const createRootThemeCss = (themes) => {
9799
9896
  * @deprecated Migrate to Tailwind v4. Intent to remove in v6.
9800
9897
  */
9801
9898
  const createThemeStyle = (theme, isAlt) => {
9899
+ if (typeof document === 'undefined')
9900
+ return;
9802
9901
  const cssThemeName = createCssColorThemeName(theme.name);
9803
9902
  const classPrefix = isAlt ? 'et-color-alt' : 'et-color';
9804
9903
  const selectors = [
@@ -9814,6 +9913,7 @@ const createThemeStyle = (theme, isAlt) => {
9814
9913
  ${theme.tertiary ? createSwatchCss('tertiary', isAlt, theme.tertiary) : ''}
9815
9914
  }
9816
9915
  `;
9916
+ document.getElementById(`${classPrefix}--${cssThemeName}`)?.remove();
9817
9917
  const style = document.createElement('style');
9818
9918
  style.id = `${classPrefix}--${cssThemeName}`;
9819
9919
  style.appendChild(document.createTextNode(css));
@@ -10022,11 +10122,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
10022
10122
 
10023
10123
  class SurfaceInteractiveStylesComponent {
10024
10124
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SurfaceInteractiveStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10025
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", 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))}@media(hover:hover){: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"], encapsulation: i0.ViewEncapsulation.None }); }
10125
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: SurfaceInteractiveStylesComponent, isStandalone: true, selector: "et-surface-interactive-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{:where(.et-surface-interactive){--et-surface-interaction-rgb: var(--et-surface-interaction);--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}@media(hover:hover){: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"], encapsulation: i0.ViewEncapsulation.None }); }
10026
10126
  }
10027
10127
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SurfaceInteractiveStylesComponent, decorators: [{
10028
10128
  type: Component,
10029
- args: [{ selector: 'et-surface-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, styles: [":where(.et-surface-interactive){--et-surface-interaction-rgb: var(--et-surface-interaction);--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}@media(hover:hover){: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"] }]
10129
+ args: [{ selector: 'et-surface-interactive-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{:where(.et-surface-interactive){--et-surface-interaction-rgb: var(--et-surface-interaction);--et-surface-interaction-solid: rgb(var(--et-surface-interaction-rgb))}@media(hover:hover){: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"] }]
10030
10130
  }] });
10031
10131
 
10032
10132
  /**
@@ -10060,11 +10160,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
10060
10160
 
10061
10161
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
10062
10162
  /** The version of `@ethlete/core` this build was cut from. */
10063
- const CORE_VERSION = '5.0.0-next.53';
10163
+ const CORE_VERSION = '5.0.0-next.55';
10064
10164
 
10065
10165
  /**
10066
10166
  * Generated bundle index. Do not edit.
10067
10167
  */
10068
10168
 
10069
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PALETTE, COLOR_PROVIDER, CORE_VERSION, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_OVERLAY_LAYER, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, ET_RESTORE_SCROLL, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RestoreScrollDirective, RuntimeError, SURFACE_COLOR, SURFACE_PROVIDER, SURFACE_TYPE, SWIPE_VELOCITY_WINDOW_MS, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, Validators, anchoredOverlayPosition, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyFaviconOverlay, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHeadTitleMarker, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createObjectUrlHandle, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTabLock, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, defineLabels, defineProvider, defineRootProvider, defineStaticProvider, defineStaticRootProvider, deleteCookie, dragGestureFrom, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, enableAnchoredOverlayPositionExtras, equal, fetchDeployedBuildFingerprint, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectAppUpdates, injectAppUpdatesConfig, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorPalette, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDefaultColorTheme, injectDefaultSurfaceTheme, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFaviconStore, injectFileDownload, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsDocumentVisible, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectNotifications, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectParentSurface, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointAttribute, numberBreakpointTransform, onOverlayViewportInsetsChange, overlayViewportInsets, overlayViewportInsetsFor, previousSignalValue, provideAppUpdates, provideAppUpdatesConfig, provideAppUpdatesInstance, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorPalette, provideColorThemes, provideColorThemesWithTailwind4, provideFaviconStore, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideNotifications, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, registerAnchoredPositionMiddlewareExtras, registerAnchoredPositionSetup, reserveOverlayViewportSpace, resetPositioningStyles, resolveAppRootColorProvider, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
10169
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PALETTE, COLOR_PROVIDER, CORE_VERSION, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_OVERLAY_LAYER, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, ET_RESTORE_SCROLL, EthleteValidators, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MatchStateType, MustMatch, NOTIFICATION_CLICK_MESSAGE_TYPE, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OVERLAY_LAYER_ATTRIBUTE, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RestoreScrollDirective, RuntimeError, SURFACE_COLOR, SURFACE_PROVIDER, SURFACE_TYPE, SWIPE_VELOCITY_WINDOW_MS, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, UNSAVED_CHANGES_TITLE_MARKER, ValidateAtLeastOneRequired, anchoredOverlayPosition, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyFaviconOverlay, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHeadTitleMarker, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, bindProps, boolBreakpointTransform, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createObjectUrlHandle, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTabLock, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, defineLabels, defineProvider, defineRootProvider, defineStaticProvider, defineStaticRootProvider, deleteCookie, dragGestureFrom, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, enableAnchoredOverlayPositionExtras, equal, fetchDeployedBuildFingerprint, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectAppUpdates, injectAppUpdatesConfig, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorPalette, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDefaultColorTheme, injectDefaultSurfaceTheme, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFaviconStore, injectFileDownload, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsDocumentVisible, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectNotifications, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectParentSurface, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterNavigationState, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceType, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUnsavedChangesCoordinator, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, isOnHigherOverlayLayer, isStaleBuildError, markdownToHtml, matchesReducedMotion, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointTransform, onOverlayViewportInsetsChange, overlayViewportInsets, overlayViewportInsetsFor, previousSignalValue, provideAppUpdates, provideAppUpdatesConfig, provideAppUpdatesInstance, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorPalette, provideColorThemes, provideColorThemesWithTailwind4, provideFaviconStore, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideNotifications, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideUnsavedChangesCoordinator, provideViewportConfig, randomId, readBuildFingerprint, readFromClipboard, registerAnchoredPositionMiddlewareExtras, registerAnchoredPositionSetup, reserveOverlayViewportSpace, resetPositioningStyles, resolveAppRootColorProvider, resolveOverlayLayer, resolveSurfaceByElevation, round, routerDisableScrollTop, routerRestoreScroll, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalDeferredLoading, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, suppressTextSelection, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toInjectFn, toProvideFn, toStringBinding, toToken, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
10070
10170
  //# sourceMappingURL=ethlete-core.mjs.map