@ethlete/core 4.12.1 → 4.13.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, NgZone, isDevMode, computed, untracked, 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, runInInjectionContext, effect, afterNextRender, untracked, 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';
@@ -1011,16 +1011,18 @@ const isElementVisible = (options) => {
1011
1011
  const elementBlockStart = elementRect.top;
1012
1012
  const containerInlineStart = containerRect.left;
1013
1013
  const containerBlockStart = containerRect.top;
1014
- const elementInlineEnd = elementInlineStart + elementRect.width;
1015
- const elementBlockEnd = elementBlockStart + elementRect.height;
1014
+ const elWith = elementRect.width || 1;
1015
+ const elHeight = elementRect.height || 1;
1016
+ const elementInlineEnd = elementInlineStart + elWith;
1017
+ const elementBlockEnd = elementBlockStart + elHeight;
1016
1018
  const containerInlineEnd = containerInlineStart + containerRect.width;
1017
1019
  const containerBlockEnd = containerBlockStart + containerRect.height;
1018
1020
  const isElementInlineVisible = elementInlineStart >= containerInlineStart && elementInlineEnd <= containerInlineEnd;
1019
1021
  const isElementBlockVisible = elementBlockStart >= containerBlockStart && elementBlockEnd <= containerBlockEnd;
1020
1022
  const inlineIntersection = Math.min(elementInlineEnd, containerInlineEnd) - Math.max(elementInlineStart, containerInlineStart);
1021
1023
  const blockIntersection = Math.min(elementBlockEnd, containerBlockEnd) - Math.max(elementBlockStart, containerBlockStart);
1022
- const inlineIntersectionPercentage = clamp((inlineIntersection / elementRect.width) * 100);
1023
- const blockIntersectionPercentage = clamp((blockIntersection / elementRect.height) * 100);
1024
+ const inlineIntersectionPercentage = clamp((inlineIntersection / elWith) * 100);
1025
+ const blockIntersectionPercentage = clamp((blockIntersection / elHeight) * 100);
1024
1026
  return {
1025
1027
  inline: isElementInlineVisible,
1026
1028
  block: isElementBlockVisible,
@@ -2347,18 +2349,78 @@ const signalIsRendered = () => {
2347
2349
  };
2348
2350
  const signalClasses = (el, classMap) => {
2349
2351
  const elements = buildElementSignal(el);
2350
- return buildSignalEffects({
2351
- map: classMap,
2352
- eachItemFn: ({ key, value }) => {
2353
- if (value) {
2354
- elements().currentElement?.classList.add(key);
2355
- }
2356
- else {
2357
- elements().currentElement?.classList.remove(key);
2352
+ const injector = inject(Injector);
2353
+ effect(() => {
2354
+ const { currentElements, previousElements } = elements();
2355
+ for (const previousEl of previousElements) {
2356
+ if (currentElements.includes(previousEl))
2357
+ continue;
2358
+ const tokens = Object.keys(classMap)
2359
+ .map((key) => key.split(' '))
2360
+ .flat();
2361
+ if (!tokens.length)
2362
+ continue;
2363
+ previousEl.classList.remove(...tokens);
2364
+ }
2365
+ for (const currentEl of currentElements) {
2366
+ if (previousElements.includes(currentEl))
2367
+ continue;
2368
+ for (const [tokens, condition] of Object.entries(classMap)) {
2369
+ untracked(() => {
2370
+ if (!condition())
2371
+ return;
2372
+ const tokenArray = tokens.split(' ');
2373
+ if (!tokenArray.length)
2374
+ return;
2375
+ currentEl.classList.add(...tokenArray);
2376
+ });
2358
2377
  }
2359
- },
2360
- cleanupFn: ({ key }) => elements().currentElement?.classList.remove(key),
2378
+ }
2361
2379
  });
2380
+ const effects = {};
2381
+ const has = (tokens) => tokens in effects;
2382
+ const push = (tokens, signal) => {
2383
+ if (has(tokens))
2384
+ return;
2385
+ runInInjectionContext(injector, () => {
2386
+ effects[tokens] = effect(() => {
2387
+ const { currentElements } = untracked(() => elements());
2388
+ for (const el of currentElements) {
2389
+ const tokenArray = tokens.split(' ');
2390
+ if (!tokenArray.length)
2391
+ continue;
2392
+ if (!signal()) {
2393
+ el.classList.remove(...tokenArray);
2394
+ }
2395
+ else {
2396
+ el.classList.add(...tokenArray);
2397
+ }
2398
+ }
2399
+ });
2400
+ });
2401
+ };
2402
+ const pushMany = (map) => {
2403
+ for (const [tokens, signal] of Object.entries(map)) {
2404
+ push(tokens, signal);
2405
+ }
2406
+ };
2407
+ const remove = (tokens) => {
2408
+ effects[tokens]?.destroy();
2409
+ delete effects[tokens];
2410
+ for (const el of elements().currentElements) {
2411
+ const tokenArray = tokens.split(' ');
2412
+ if (!tokenArray.length)
2413
+ continue;
2414
+ el.classList.remove(...tokenArray);
2415
+ }
2416
+ };
2417
+ const removeMany = (tokens) => {
2418
+ for (const token of tokens) {
2419
+ remove(token);
2420
+ }
2421
+ };
2422
+ pushMany(classMap);
2423
+ return { remove, removeMany, has, push, pushMany };
2362
2424
  };
2363
2425
  const signalHostClasses = (classMap) => signalClasses(inject(ElementRef), classMap);
2364
2426
  const ALWAYS_TRUE_ATTRIBUTE_KEYS = ['disabled', 'readonly', 'required', 'checked', 'selected', 'hidden', 'inert'];
@@ -2487,11 +2549,25 @@ const signalElementMutations = (el, options) => {
2487
2549
  return elementMutationsSignal.asReadonly();
2488
2550
  };
2489
2551
  const signalHostElementMutations = (options) => signalElementMutations(inject(ElementRef), options);
2490
- const signalElementScrollState = (el) => {
2552
+ const signalElementScrollState = (el, options) => {
2491
2553
  const elements = buildElementSignal(el);
2492
2554
  const elementDimensions = signalElementDimensions(elements);
2493
2555
  const elementMutations = signalElementMutations(elements, { childList: true, subtree: true });
2494
2556
  const isRendered = signalIsRendered();
2557
+ const initialScrollPosition = options?.initialScrollPosition;
2558
+ if (initialScrollPosition) {
2559
+ const ref = effect(() => {
2560
+ if (!isRendered())
2561
+ return;
2562
+ const scrollPosition = initialScrollPosition();
2563
+ const element = elements().currentElement;
2564
+ if (scrollPosition && element) {
2565
+ element.scrollLeft = scrollPosition.x;
2566
+ element.scrollTop = scrollPosition.y;
2567
+ ref.destroy();
2568
+ }
2569
+ });
2570
+ }
2495
2571
  return computed(() => {
2496
2572
  const element = elements().currentElement;
2497
2573
  const dimensions = elementDimensions();
@@ -2565,6 +2641,38 @@ const signalElementIntersection = (el, options) => {
2565
2641
  obs?.disconnect();
2566
2642
  }
2567
2643
  if (els.currentElements.length && !!enabled) {
2644
+ const rootEl = untracked(() => root().currentElement);
2645
+ // check sync for intersections since the intersection observer async and we probably want to know the initial state
2646
+ const entries = els.currentElements
2647
+ .map((el) => {
2648
+ const visibility = isElementVisible({
2649
+ container: rootEl,
2650
+ element: el,
2651
+ });
2652
+ if (!visibility) {
2653
+ console.error('No visibility data found for element.', {
2654
+ element: el,
2655
+ container: rootEl,
2656
+ });
2657
+ return null;
2658
+ }
2659
+ const inlineIntersectionRatio = visibility.inlineIntersection / 100;
2660
+ const blockIntersectionRatio = visibility.blockIntersection / 100;
2661
+ const isIntersecting = inlineIntersectionRatio > 0 && blockIntersectionRatio > 0;
2662
+ const intersectionRatio = Math.min(inlineIntersectionRatio, blockIntersectionRatio);
2663
+ const intersectionEntry = {
2664
+ boundingClientRect: el.getBoundingClientRect(),
2665
+ intersectionRatio,
2666
+ intersectionRect: el.getBoundingClientRect(),
2667
+ isIntersecting,
2668
+ rootBounds: root().currentElement?.getBoundingClientRect() ?? null,
2669
+ target: el,
2670
+ time: performance.now(),
2671
+ };
2672
+ return intersectionEntry;
2673
+ })
2674
+ .filter((e) => e !== null);
2675
+ elementIntersectionSignal.set(entries);
2568
2676
  for (const el of els.currentElements) {
2569
2677
  obs?.observe(el);
2570
2678
  }
@@ -2699,6 +2807,27 @@ const injectPathParam = (key, config) => {
2699
2807
  const src = computed(() => pathParams()[key] ?? null);
2700
2808
  return transformOrReturn(src, config);
2701
2809
  };
2810
+ const createIsRenderedSignal = () => {
2811
+ const value = signal(false);
2812
+ nextFrame(() => {
2813
+ if (!value()) {
2814
+ console.error('Render signal was not set to true. This can cause unexpected behavior. Make sure to .bind() the render signal at the end of the constructor.');
2815
+ }
2816
+ });
2817
+ return {
2818
+ state: value,
2819
+ bind: () => effect(() => value.set(true), { allowSignalWrites: true }),
2820
+ };
2821
+ };
2822
+ const createCanAnimateSignal = () => {
2823
+ const value = signal(false);
2824
+ nextFrame(() => {
2825
+ value.set(true);
2826
+ });
2827
+ return {
2828
+ state: value,
2829
+ };
2830
+ };
2702
2831
 
2703
2832
  const scrollBehaviorSupported = supportsScrollBehavior();
2704
2833
  let _uniqueIdCounter = 0;
@@ -5364,5 +5493,5 @@ const Validators = {
5364
5493
  * Generated bundle index. Do not edit.
5365
5494
  */
5366
5495
 
5367
- 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, createComponentId, createDependencyStash, createDestroy, createElementDictionary, createFlipAnimation, createFlipAnimationGroup, createHostProps, 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 };
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 };
5368
5497
  //# sourceMappingURL=ethlete-core.mjs.map