@ethlete/core 4.13.0 → 4.15.0

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, HostBinding, InjectionToken, assertInInjectionContext, DestroyRef, ElementRef, TemplateRef, Injectable, isSignal, signal, QueryList, Injector, runInInjectionContext, effect, afterNextRender, untracked, NgZone, isDevMode, computed, Directive, model, EventEmitter, booleanAttribute, numberAttribute, Output, ViewContainerRef, Pipe, AfterRenderPhase, input } from '@angular/core';
2
+ import { inject, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, HostBinding, InjectionToken, assertInInjectionContext, DestroyRef, ElementRef, TemplateRef, Injectable, isSignal, signal, QueryList, Injector, effect, untracked, runInInjectionContext, afterNextRender, Renderer2, RendererStyleFlags2, NgZone, isDevMode, computed, Directive, model, EventEmitter, booleanAttribute, numberAttribute, Output, ViewContainerRef, Pipe, AfterRenderPhase, input } from '@angular/core';
3
3
  import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
4
4
  import { Subject, BehaviorSubject, takeUntil, switchMap, of, tap, map, startWith, Observable, combineLatest, timer, distinctUntilChanged, shareReplay, filter, take, fromEvent, pairwise, debounceTime, finalize, merge, skip, takeWhile } from 'rxjs';
5
5
  import { END, HOME, PAGE_DOWN, PAGE_UP, UP_ARROW, DOWN_ARROW } from '@angular/cdk/keycodes';
@@ -1031,16 +1031,24 @@ const isElementVisible = (options) => {
1031
1031
  element,
1032
1032
  };
1033
1033
  };
1034
- const scrollToElement = (options) => {
1034
+ const getElementScrollCoordinates = (options) => {
1035
1035
  let { container } = options;
1036
1036
  const { element, direction, behavior = 'smooth', origin = 'nearest', scrollBlockMargin = 0, scrollInlineMargin = 0, } = options;
1037
1037
  if (!element || container === null) {
1038
- return;
1038
+ return {
1039
+ behavior,
1040
+ left: undefined,
1041
+ top: undefined,
1042
+ };
1039
1043
  }
1040
1044
  container ||= document.documentElement;
1041
1045
  const canScroll = elementCanScroll(container);
1042
1046
  if (!canScroll) {
1043
- return;
1047
+ return {
1048
+ behavior,
1049
+ left: undefined,
1050
+ top: undefined,
1051
+ };
1044
1052
  }
1045
1053
  const elementRect = element.getBoundingClientRect();
1046
1054
  const containerRect = container.getBoundingClientRect();
@@ -1111,11 +1119,14 @@ const scrollToElement = (options) => {
1111
1119
  scrollToElementNearest();
1112
1120
  break;
1113
1121
  }
1114
- container.scrollTo({
1122
+ return {
1115
1123
  behavior,
1116
1124
  left: shouldScrollLeft ? scrollLeftTo : undefined,
1117
1125
  top: shouldScrollTop ? scrollTopTo : undefined,
1118
- });
1126
+ };
1127
+ };
1128
+ const scrollToElement = (options) => {
1129
+ options.container?.scrollTo(getElementScrollCoordinates(options));
1119
1130
  };
1120
1131
  const getElementVisibleStates = (options) => {
1121
1132
  let { container } = options;
@@ -2303,51 +2314,7 @@ const buildElementSignal = (el) => {
2303
2314
  previousElement: previousElements?.[0] ?? null,
2304
2315
  }))), { initialValue: { currentElement: null, previousElement: null, previousElements: [], currentElements: [] } });
2305
2316
  };
2306
- const buildSignalEffects = (config) => {
2307
- const injector = inject(Injector);
2308
- const { map, eachItemFn, cleanupFn } = config;
2309
- const effectRefMap = {};
2310
- const has = (token) => token in effectRefMap;
2311
- const push = (tokenString, signal) => {
2312
- if (has(tokenString))
2313
- return;
2314
- const tokenArray = tokenString.split(' ').filter((token) => !!token);
2315
- for (const token of tokenArray) {
2316
- runInInjectionContext(injector, () => {
2317
- const ref = effect(() => {
2318
- const value = signal();
2319
- eachItemFn({ key: token, value });
2320
- });
2321
- effectRefMap[token] = ref;
2322
- });
2323
- }
2324
- };
2325
- const pushMany = (map) => {
2326
- for (const [tokenString, signal] of Object.entries(map)) {
2327
- push(tokenString, signal);
2328
- }
2329
- };
2330
- const remove = (...tokens) => {
2331
- for (const tokenString of tokens) {
2332
- effectRefMap[tokenString]?.destroy();
2333
- cleanupFn({ key: tokenString, value: map[tokenString]?.() });
2334
- delete effectRefMap[tokenString];
2335
- }
2336
- };
2337
- const removeMany = (tokens) => {
2338
- for (const token of tokens) {
2339
- remove(token);
2340
- }
2341
- };
2342
- pushMany(map);
2343
- return { remove, removeMany, has, push, pushMany };
2344
- };
2345
- const signalIsRendered = () => {
2346
- const isRendered = signal(false);
2347
- afterNextRender(() => isRendered.set(true));
2348
- return isRendered.asReadonly();
2349
- };
2350
- const signalClasses = (el, classMap) => {
2317
+ const buildSignalEffects = (el, config) => {
2351
2318
  const elements = buildElementSignal(el);
2352
2319
  const injector = inject(Injector);
2353
2320
  effect(() => {
@@ -2355,24 +2322,22 @@ const signalClasses = (el, classMap) => {
2355
2322
  for (const previousEl of previousElements) {
2356
2323
  if (currentElements.includes(previousEl))
2357
2324
  continue;
2358
- const tokens = Object.keys(classMap)
2325
+ const tokens = Object.keys(config.tokenMap)
2359
2326
  .map((key) => key.split(' '))
2360
2327
  .flat();
2361
2328
  if (!tokens.length)
2362
2329
  continue;
2363
- previousEl.classList.remove(...tokens);
2330
+ config.cleanupFn(previousEl, tokens);
2364
2331
  }
2365
2332
  for (const currentEl of currentElements) {
2366
2333
  if (previousElements.includes(currentEl))
2367
2334
  continue;
2368
- for (const [tokens, condition] of Object.entries(classMap)) {
2335
+ for (const [tokens, condition] of Object.entries(config.tokenMap)) {
2369
2336
  untracked(() => {
2370
- if (!condition())
2371
- return;
2372
2337
  const tokenArray = tokens.split(' ');
2373
2338
  if (!tokenArray.length)
2374
2339
  return;
2375
- currentEl.classList.add(...tokenArray);
2340
+ config.updateFn(currentEl, tokenArray, condition());
2376
2341
  });
2377
2342
  }
2378
2343
  }
@@ -2389,12 +2354,7 @@ const signalClasses = (el, classMap) => {
2389
2354
  const tokenArray = tokens.split(' ');
2390
2355
  if (!tokenArray.length)
2391
2356
  continue;
2392
- if (!signal()) {
2393
- el.classList.remove(...tokenArray);
2394
- }
2395
- else {
2396
- el.classList.add(...tokenArray);
2397
- }
2357
+ config.updateFn(el, tokenArray, signal());
2398
2358
  }
2399
2359
  });
2400
2360
  });
@@ -2411,7 +2371,7 @@ const signalClasses = (el, classMap) => {
2411
2371
  const tokenArray = tokens.split(' ');
2412
2372
  if (!tokenArray.length)
2413
2373
  continue;
2414
- el.classList.remove(...tokenArray);
2374
+ config.cleanupFn(el, tokenArray);
2415
2375
  }
2416
2376
  };
2417
2377
  const removeMany = (tokens) => {
@@ -2419,52 +2379,73 @@ const signalClasses = (el, classMap) => {
2419
2379
  remove(token);
2420
2380
  }
2421
2381
  };
2422
- pushMany(classMap);
2382
+ pushMany(config.tokenMap);
2423
2383
  return { remove, removeMany, has, push, pushMany };
2424
2384
  };
2385
+ const signalIsRendered = () => {
2386
+ const isRendered = signal(false);
2387
+ afterNextRender(() => isRendered.set(true));
2388
+ return isRendered.asReadonly();
2389
+ };
2390
+ const signalClasses = (el, classMap) => {
2391
+ const renderer = inject(Renderer2);
2392
+ return buildSignalEffects(el, {
2393
+ tokenMap: classMap,
2394
+ cleanupFn: (el, tokens) => tokens.forEach((token) => renderer.removeClass(el, token)),
2395
+ updateFn: (el, tokens, condition) => {
2396
+ if (!condition) {
2397
+ tokens.forEach((token) => renderer.removeClass(el, token));
2398
+ }
2399
+ else {
2400
+ tokens.forEach((token) => renderer.addClass(el, token));
2401
+ }
2402
+ },
2403
+ });
2404
+ };
2425
2405
  const signalHostClasses = (classMap) => signalClasses(inject(ElementRef), classMap);
2426
2406
  const ALWAYS_TRUE_ATTRIBUTE_KEYS = ['disabled', 'readonly', 'required', 'checked', 'selected', 'hidden', 'inert'];
2427
2407
  const signalAttributes = (el, attributeMap) => {
2428
- const elements = buildElementSignal(el);
2429
- return buildSignalEffects({
2430
- map: attributeMap,
2431
- eachItemFn: ({ key, value }) => {
2432
- const valueString = `${value}`;
2433
- if (ALWAYS_TRUE_ATTRIBUTE_KEYS.includes(key)) {
2434
- if (value) {
2435
- elements().currentElement?.setAttribute(key, '');
2436
- }
2437
- else {
2438
- elements().currentElement?.removeAttribute(key);
2408
+ const renderer = inject(Renderer2);
2409
+ return buildSignalEffects(el, {
2410
+ tokenMap: attributeMap,
2411
+ cleanupFn: (el, tokens) => tokens.forEach((token) => el.removeAttribute(token)),
2412
+ updateFn: (el, tokens, condition) => {
2413
+ for (const token of tokens) {
2414
+ if (ALWAYS_TRUE_ATTRIBUTE_KEYS.includes(token)) {
2415
+ if (condition) {
2416
+ renderer.setAttribute(el, token, '');
2417
+ }
2418
+ else {
2419
+ renderer.removeAttribute(el, token);
2420
+ }
2421
+ continue;
2439
2422
  }
2440
- }
2441
- else {
2442
- if (value === null || value === undefined) {
2443
- elements().currentElement?.removeAttribute(key);
2423
+ if (condition === null || condition === undefined) {
2424
+ renderer.removeAttribute(el, token);
2444
2425
  }
2445
2426
  else {
2446
- elements().currentElement?.setAttribute(key, valueString);
2427
+ renderer.setAttribute(el, token, `${condition}`);
2447
2428
  }
2448
2429
  }
2449
2430
  },
2450
- cleanupFn: ({ key }) => elements().currentElement?.removeAttribute(key),
2451
2431
  });
2452
2432
  };
2453
2433
  const signalHostAttributes = (attributeMap) => signalAttributes(inject(ElementRef), attributeMap);
2454
2434
  const signalStyles = (el, styleMap) => {
2455
- const elements = buildElementSignal(el);
2456
- return buildSignalEffects({
2457
- map: styleMap,
2458
- eachItemFn: ({ key, value }) => {
2459
- if (value === null || value === undefined) {
2460
- elements().currentElement?.style.removeProperty(key);
2461
- }
2462
- else {
2463
- const valueString = `${value}`;
2464
- elements().currentElement?.style.setProperty(key, valueString);
2435
+ const renderer = inject(Renderer2);
2436
+ return buildSignalEffects(el, {
2437
+ tokenMap: styleMap,
2438
+ cleanupFn: (el, tokens) => tokens.forEach((token) => renderer.removeStyle(el, token)),
2439
+ updateFn: (el, tokens, condition) => {
2440
+ for (const token of tokens) {
2441
+ if (condition === null || condition === undefined) {
2442
+ renderer.removeStyle(el, token);
2443
+ }
2444
+ else {
2445
+ renderer.setStyle(el, token, `${condition}`, RendererStyleFlags2.DashCase);
2446
+ }
2465
2447
  }
2466
2448
  },
2467
- cleanupFn: ({ key }) => elements().currentElement?.style.removeProperty(key),
2468
2449
  });
2469
2450
  };
2470
2451
  const signalHostStyles = (styleMap) => signalStyles(inject(ElementRef), styleMap);
@@ -2562,8 +2543,10 @@ const signalElementScrollState = (el, options) => {
2562
2543
  const scrollPosition = initialScrollPosition();
2563
2544
  const element = elements().currentElement;
2564
2545
  if (scrollPosition && element) {
2565
- element.scrollLeft = scrollPosition.x;
2566
- element.scrollTop = scrollPosition.y;
2546
+ if (scrollPosition.left !== undefined)
2547
+ element.scrollLeft = scrollPosition.left;
2548
+ if (scrollPosition.top !== undefined)
2549
+ element.scrollTop = scrollPosition.top;
2567
2550
  ref.destroy();
2568
2551
  }
2569
2552
  });
@@ -2642,6 +2625,7 @@ const signalElementIntersection = (el, options) => {
2642
2625
  }
2643
2626
  if (els.currentElements.length && !!enabled) {
2644
2627
  const rootEl = untracked(() => root().currentElement);
2628
+ const rootBounds = rootEl?.getBoundingClientRect();
2645
2629
  // check sync for intersections since the intersection observer async and we probably want to know the initial state
2646
2630
  const entries = els.currentElements
2647
2631
  .map((el) => {
@@ -2660,12 +2644,13 @@ const signalElementIntersection = (el, options) => {
2660
2644
  const blockIntersectionRatio = visibility.blockIntersection / 100;
2661
2645
  const isIntersecting = inlineIntersectionRatio > 0 && blockIntersectionRatio > 0;
2662
2646
  const intersectionRatio = Math.min(inlineIntersectionRatio, blockIntersectionRatio);
2647
+ const elBounds = el.getBoundingClientRect();
2663
2648
  const intersectionEntry = {
2664
- boundingClientRect: el.getBoundingClientRect(),
2649
+ boundingClientRect: elBounds,
2665
2650
  intersectionRatio,
2666
- intersectionRect: el.getBoundingClientRect(),
2651
+ intersectionRect: elBounds,
2667
2652
  isIntersecting,
2668
- rootBounds: root().currentElement?.getBoundingClientRect() ?? null,
2653
+ rootBounds: rootBounds ?? null,
2669
2654
  target: el,
2670
2655
  time: performance.now(),
2671
2656
  };
@@ -5493,5 +5478,5 @@ const Validators = {
5493
5478
  * Generated bundle index. Do not edit.
5494
5479
  */
5495
5480
 
5496
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, AT_LEAST_ONE_REQUIRED, ActiveSelectionModel, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, CURSOR_DRAG_SCROLLING_CLASS, CURSOR_DRAG_SCROLLING_PREPARED_CLASS, ClickObserverFactory, ClickObserverService, ClickOutsideDirective, ContentObserverService, CursorDragScrollDirective, DEBUG_TOKEN, DEFAULT_VIEWPORT_CONFIG, DELAYABLE_TOKEN, DebugDirective, DelayableDirective, ET_PROPERTY_REMOVED, FocusVisibleService, IS_ACTIVE_ELEMENT, IS_ARRAY_NOT_EMPTY, IS_ELEMENT, IS_EMAIL, InferMimeTypePipe, IntersectionObserverFactory, IntersectionObserverService, IsActiveElementDirective, IsArrayNotEmpty, IsElementDirective, IsEmail, KeyPressManager, LetContext, LetDirective, MUST_MATCH, Memo, MustMatch, MutationObserverFactory, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OBSERVE_SCROLL_STATE, OBSERVE_VISIBILITY_TOKEN, ObserveContentDirective, ObserveResizeDirective, ObserveScrollStateDirective, ObserveVisibilityDirective, PropsDirective, ROOT_BOUNDARY_TOKEN, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeObserverFactory, ResizeObserverService, RootBoundaryDirective, RouterStateService, RuntimeError, SCROLL_OBSERVER_FIRST_ELEMENT_CLASS, SCROLL_OBSERVER_IGNORE_TARGET_CLASS, SCROLL_OBSERVER_LAST_ELEMENT_CLASS, SCROLL_OBSERVER_OBSERVING_FIRST_ELEMENT_CLASS, SCROLL_OBSERVER_OBSERVING_LAST_ELEMENT_CLASS, SEO_DIRECTIVE_TOKEN, ScrollObserverFirstElementDirective, ScrollObserverIgnoreTargetDirective, ScrollObserverLastElementDirective, SelectionModel, SeoDirective, SmartBlockScrollStrategy, StructuredDataComponent, ToArrayPipe, TypedQueryList, VIEWPORT_CONFIG, ValidateAtLeastOneRequired, Validators, ViewportService, bindProps, buildSignalEffects, clamp, clone, cloneFormGroup, controlValueSignal, controlValueSignalWithPrevious, createCanAnimateSignal, createComponentId, createDependencyStash, createDestroy, createElementDictionary, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createMediaQueryObservable, createMutationObservable, createPropHandlers, createProps, createReactiveBindings, createResizeObservable, createSetup, debouncedControlValueSignal, deleteCookie, elementCanScroll, equal, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementVisibleStates, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getIntersectionInfo, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, hasCookie, inferMimeType, injectFragment, injectHostElement, injectOrRunInContext, injectPathParam, injectPathParams, injectQueryParam, injectQueryParams, injectRouteData, injectRouteDataItem, injectRouteTitle, injectTemplateRef, isArray, isElementVisible, isEmptyArray, isGroupMatch, isKnockoutMatch, isObject, isObjectArray, isPrimitiveArray, mergeSeoConfig, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, previousSignalValue, provideViewportConfig, round, routerDisableScrollTop, scrollToElement, setCookie, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, signalVisibilityChangeClasses, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, transformOrReturn, unbindProps };
5481
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, AT_LEAST_ONE_REQUIRED, ActiveSelectionModel, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, CURSOR_DRAG_SCROLLING_CLASS, CURSOR_DRAG_SCROLLING_PREPARED_CLASS, ClickObserverFactory, ClickObserverService, ClickOutsideDirective, ContentObserverService, CursorDragScrollDirective, DEBUG_TOKEN, DEFAULT_VIEWPORT_CONFIG, DELAYABLE_TOKEN, DebugDirective, DelayableDirective, ET_PROPERTY_REMOVED, FocusVisibleService, IS_ACTIVE_ELEMENT, IS_ARRAY_NOT_EMPTY, IS_ELEMENT, IS_EMAIL, InferMimeTypePipe, IntersectionObserverFactory, IntersectionObserverService, IsActiveElementDirective, IsArrayNotEmpty, IsElementDirective, IsEmail, KeyPressManager, LetContext, LetDirective, MUST_MATCH, Memo, MustMatch, MutationObserverFactory, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, OBSERVE_SCROLL_STATE, OBSERVE_VISIBILITY_TOKEN, ObserveContentDirective, ObserveResizeDirective, ObserveScrollStateDirective, ObserveVisibilityDirective, PropsDirective, ROOT_BOUNDARY_TOKEN, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeObserverFactory, ResizeObserverService, RootBoundaryDirective, RouterStateService, RuntimeError, SCROLL_OBSERVER_FIRST_ELEMENT_CLASS, SCROLL_OBSERVER_IGNORE_TARGET_CLASS, SCROLL_OBSERVER_LAST_ELEMENT_CLASS, SCROLL_OBSERVER_OBSERVING_FIRST_ELEMENT_CLASS, SCROLL_OBSERVER_OBSERVING_LAST_ELEMENT_CLASS, SEO_DIRECTIVE_TOKEN, ScrollObserverFirstElementDirective, ScrollObserverIgnoreTargetDirective, ScrollObserverLastElementDirective, SelectionModel, SeoDirective, SmartBlockScrollStrategy, StructuredDataComponent, ToArrayPipe, TypedQueryList, VIEWPORT_CONFIG, ValidateAtLeastOneRequired, Validators, ViewportService, bindProps, buildSignalEffects, clamp, clone, cloneFormGroup, controlValueSignal, controlValueSignalWithPrevious, createCanAnimateSignal, createComponentId, createDependencyStash, createDestroy, createElementDictionary, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createMediaQueryObservable, createMutationObservable, createPropHandlers, createProps, createReactiveBindings, createResizeObservable, createSetup, debouncedControlValueSignal, deleteCookie, elementCanScroll, equal, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getElementVisibleStates, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getIntersectionInfo, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, hasCookie, inferMimeType, injectFragment, injectHostElement, injectOrRunInContext, injectPathParam, injectPathParams, injectQueryParam, injectQueryParams, injectRouteData, injectRouteDataItem, injectRouteTitle, injectTemplateRef, isArray, isElementVisible, isEmptyArray, isGroupMatch, isKnockoutMatch, isObject, isObjectArray, isPrimitiveArray, mergeSeoConfig, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, previousSignalValue, provideViewportConfig, round, routerDisableScrollTop, scrollToElement, setCookie, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, signalVisibilityChangeClasses, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, transformOrReturn, unbindProps };
5497
5482
  //# sourceMappingURL=ethlete-core.mjs.map