@ethlete/core 5.0.0-next.34 → 5.0.0-next.35

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @ethlete/core
2
2
 
3
+ ## 5.0.0-next.35
4
+
5
+ ### Minor Changes
6
+
7
+ - [`a20d0ce`](https://github.com/ethlete-io/ethdk/commit/a20d0cee2f9937ad45ac1fd5eaec3c1a6ac1d27c) Thanks [@TomTomB](https://github.com/TomTomB)! - Add `injectIsDocumentVisible()` — a signal for whether the page is the tab in front, which an
8
+ IntersectionObserver cannot tell you.
9
+
10
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`d787b1d`](https://github.com/ethlete-io/ethdk/commit/d787b1de041da31b6974a9f1b06ceb6ba6f5f6c5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Export `dragGestureFrom(event, element, { commitThreshold })` — the pointer-drag primitive that
11
+ `etDragHandle` is built on, now usable directly. It takes a `pointerdown` and returns an observable of
12
+ `start` / `move` / `end` (or a single `tapped` when the pointer never crossed the commit threshold),
13
+ completing with the gesture.
14
+
15
+ Prefer the directive. Reach for the primitive when the draggable element belongs to someone else's
16
+ template and you only have a delegated `pointerdown` — the case that motivated this: `et-table`'s
17
+ opt-in column-reorder feature attaches a drag to header cells the table itself renders, without the
18
+ table having to import any drag code.
19
+
20
+ `DragHandleDirective` is unchanged and now uses this primitive internally; `DragStartEvent` /
21
+ `DragMoveEvent` keep their import path.
22
+
23
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`929e355`](https://github.com/ethlete-io/ethdk/commit/929e3554770a132b4791edd2c063fa677f758762) Thanks [@github-actions](https://github.com/apps/github-actions)! - `setupScrollRestoration` can now restore the previous scroll offset on browser back/forward navigation instead of scrolling to top, via `restore: { enabled: true }`.
24
+
25
+ - The offset is applied only once the content is tall enough to reach it, so query-driven pages no longer land at the wrong place while their skeleton/loading state is on screen. Options: `timeout`, `maxTimeout`, `clampOnTimeout`.
26
+ - `holdScrollRestoration(() => query.isLoading())` suspends the wait from inside a route component when the data takes longer than `timeout` to arrive.
27
+ - `scrollElement` now also accepts a getter (`() => HTMLElement | null`), for scroll containers that only exist after the app shell rendered or are created per route.
28
+
29
+ ### Patch Changes
30
+
31
+ - [`4ffabfb`](https://github.com/ethlete-io/ethdk/commit/4ffabfbe1830d4560b98dcda7d262155273dd62e) Thanks [@TomTomB](https://github.com/TomTomB)! - `useCursorDragScroll` no longer starts a drag on a secondary click, and ends one when a context menu opens —
32
+ previously a right-click left it latched on, so every later mouse move scrolled the container.
33
+
3
34
  ## 5.0.0-next.34
4
35
 
5
36
  ### Patch Changes
@@ -7,7 +7,7 @@ import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
7
7
  import { coerceElement } from '@angular/cdk/coercion';
8
8
  import { DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
9
9
  import { BreakpointObserver } from '@angular/cdk/layout';
10
- import { Router, NavigationEnd, NavigationSkipped } from '@angular/router';
10
+ import { Router, NavigationEnd, NavigationSkipped, NavigationStart } from '@angular/router';
11
11
  import { Overlay } from '@angular/cdk/overlay';
12
12
  import { ComponentPortal } from '@angular/cdk/portal';
13
13
  import { autoUpdate, computePosition, offset, flip, size, shift, limitShift, arrow, hide } from '@floating-ui/dom';
@@ -2444,6 +2444,21 @@ const signalElementLastScrollDirection = (el) => {
2444
2444
  };
2445
2445
  const signalHostElementLastScrollDirection = () => signalElementLastScrollDirection(inject(ElementRef));
2446
2446
 
2447
+ /**
2448
+ * A signal for whether this page is the one the reader is actually looking at — `false` for a backgrounded
2449
+ * tab or a minimised window.
2450
+ *
2451
+ * Not the same question as whether an element is on screen: an IntersectionObserver reports a fully visible
2452
+ * element in a background tab, because the tab's own visibility is no part of what it measures. Anything
2453
+ * that moves on its own needs to ask both, and a timer is not a substitute — browsers throttle timers in a
2454
+ * hidden tab rather than stopping them, so work keeps piling up out of sight.
2455
+ */
2456
+ const injectIsDocumentVisible = memoizeSignal(() => {
2457
+ const document = inject(DOCUMENT);
2458
+ const isVisible = () => document.visibilityState === 'visible';
2459
+ return toSignal(fromEvent(document, 'visibilitychange').pipe(map(isVisible)), { initialValue: isVisible() });
2460
+ });
2461
+
2447
2462
  const areScrollStatesEqual = (a, b) => {
2448
2463
  return (a.canScroll === b.canScroll &&
2449
2464
  a.canScrollHorizontally === b.canScrollHorizontally &&
@@ -2557,6 +2572,8 @@ const writeViewportSizeToCssVariables = () => {
2557
2572
 
2558
2573
  /** The deadzone in pixels after which the cursor drag scroll will take effect. */
2559
2574
  const CURSOR_DRAG_SCROLL_DEADZONE = 5;
2575
+ /** `MouseEvent.button` for the primary button. A secondary click opens a menu; it does not drag. */
2576
+ const PRIMARY_MOUSE_BUTTON = 0;
2560
2577
  /** The class that is added to the element when the cursor is being dragged. */
2561
2578
  const CURSOR_DRAG_SCROLLING_CLASS = 'et-cursor-drag-scroll--scrolling';
2562
2579
  const CURSOR_DRAG_INIT_CLASS = 'et-cursor-drag-scroll--init';
@@ -2692,15 +2709,18 @@ const useCursorDragScroll = (el, options) => {
2692
2709
  dragAmount.set({ x: 0, y: 0 });
2693
2710
  };
2694
2711
  const setupDragging = (e) => {
2695
- const mouseUp = fromEvent(document, 'mouseup');
2712
+ // A context menu takes the pointer away without ever delivering a `mouseup` — so without it in here, a
2713
+ // right click (or a ctrl-click on a Mac, which is the primary button) leaves the drag latched on and
2714
+ // every later mouse move scrolls the container.
2715
+ const dragEnd = merge(fromEvent(document, 'mouseup'), fromEvent(document, 'contextmenu'));
2696
2716
  const mouseMove = fromEvent(document, 'mousemove');
2697
2717
  const el = element().currentElement;
2698
2718
  if (!el)
2699
2719
  return;
2700
2720
  mouseMove
2701
- .pipe(takeUntilDestroyed(destroyRef), takeUntil(mouseUp), tap((e) => updateDragging(e)))
2721
+ .pipe(takeUntilDestroyed(destroyRef), takeUntil(dragEnd), tap((e) => updateDragging(e)))
2702
2722
  .subscribe();
2703
- mouseUp
2723
+ dragEnd
2704
2724
  .pipe(take(1), takeUntilDestroyed(destroyRef), tap(() => updateDraggingEnd()))
2705
2725
  .subscribe();
2706
2726
  initialDragPosition.set({ x: e.clientX, y: e.clientY });
@@ -2708,7 +2728,7 @@ const useCursorDragScroll = (el, options) => {
2708
2728
  isInitDragging.set(true);
2709
2729
  };
2710
2730
  toObservable(element)
2711
- .pipe(map((e) => e?.currentElement), switchMap((el) => (el ? fromEvent(el, 'mousedown') : of(null))), filter((e) => !!e), filter(() => enabled()), tap((e) => setupDragging(e)), takeUntilDestroyed())
2731
+ .pipe(map((e) => e?.currentElement), switchMap((el) => (el ? fromEvent(el, 'mousedown') : of(null))), filter((e) => !!e), filter((e) => e.button === PRIMARY_MOUSE_BUTTON), filter(() => enabled()), tap((e) => setupDragging(e)), takeUntilDestroyed())
2712
2732
  .subscribe();
2713
2733
  return {
2714
2734
  isDragging: isDragging.asReadonly(),
@@ -2951,22 +2971,182 @@ const routerDisableScrollTop = (config = {}) => {
2951
2971
  ...(config.onPathParamChange ? { [ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE]: true } : {}),
2952
2972
  };
2953
2973
  };
2974
+ /**
2975
+ * Registry of "not settled yet" reporters. Lives in the root injector so a route component can
2976
+ * reach the registration created by the app level `setupScrollRestoration` call.
2977
+ * @internal
2978
+ */
2979
+ const [, injectScrollRestorationHolds] = createRootProvider(() => {
2980
+ const holds = new Set();
2981
+ return {
2982
+ add: (isPending) => {
2983
+ holds.add(isPending);
2984
+ return () => holds.delete(isPending);
2985
+ },
2986
+ isHeld: () => {
2987
+ for (const isPending of holds) {
2988
+ if (isPending())
2989
+ return true;
2990
+ }
2991
+ return false;
2992
+ },
2993
+ };
2994
+ }, { name: 'ScrollRestorationHolds' });
2995
+ /**
2996
+ * Suspend scroll restoration while `isPending` reads `true`.
2997
+ *
2998
+ * Restoration already waits for the scroll container to grow tall enough to reach the saved offset,
2999
+ * so this is only needed when the content may take longer than `restore.timeout` to get there —
3000
+ * a slow list request, for instance. Registers for the lifetime of the current injection context.
3001
+ *
3002
+ * @example
3003
+ * // inside a route component
3004
+ * holdScrollRestoration(() => query.isLoading());
3005
+ */
3006
+ const holdScrollRestoration = (isPending) => {
3007
+ const remove = injectScrollRestorationHolds().add(isPending);
3008
+ inject(DestroyRef).onDestroy(remove);
3009
+ };
3010
+ /** Upper bound on remembered history entries. Each entry is a single number, so this is generous. */
3011
+ const MAX_STORED_POSITIONS = 200;
3012
+ const DEFAULT_RESTORE_TIMEOUT = 1000;
3013
+ const DEFAULT_RESTORE_MAX_TIMEOUT = 10_000;
3014
+ /** Events that mean the user took over scrolling, so a pending restoration must be abandoned. */
3015
+ const INTERACTION_EVENTS = ['wheel', 'touchmove', 'keydown'];
2954
3016
  const setupScrollRestoration = (config = {}) => {
2955
3017
  if (!isPlatformBrowser(inject(PLATFORM_ID))) {
2956
3018
  return;
2957
3019
  }
2958
3020
  const router = inject(Router);
2959
3021
  const document = inject(DOCUMENT);
3022
+ const injector = inject(Injector);
3023
+ const holds = injectScrollRestorationHolds();
3024
+ const restoreEnabled = config.restore?.enabled === true;
3025
+ const restoreTimeout = config.restore?.timeout ?? DEFAULT_RESTORE_TIMEOUT;
3026
+ const restoreMaxTimeout = config.restore?.maxTimeout ?? DEFAULT_RESTORE_MAX_TIMEOUT;
3027
+ const clampOnTimeout = config.restore?.clampOnTimeout ?? true;
3028
+ const resolveScrollElement = () => {
3029
+ const el = typeof config.scrollElement === 'function' ? config.scrollElement() : config.scrollElement;
3030
+ return el ?? document.documentElement;
3031
+ };
3032
+ // The browser restores the offset against the still-loading (much shorter) document, which is the
3033
+ // exact problem we are solving — take it over completely.
3034
+ if (restoreEnabled && 'scrollRestoration' in history) {
3035
+ history.scrollRestoration = 'manual';
3036
+ }
3037
+ /** Saved offsets keyed by the router's per-history-entry `navigationId`. */
3038
+ const positions = new Map();
3039
+ // Mirrors Angular's own `RouterScroller`: the offset of the currently displayed page belongs to
3040
+ // the navigation that produced it, and a popstate reports the id of the entry it moves to.
3041
+ let lastNavigationId = 0;
3042
+ let restoredNavigationId = 0;
3043
+ let isPopstate = false;
2960
3044
  let prev = { state: createRouterState(router), route: createRoute(router) };
2961
- router.events
2962
- .pipe(filter((e) => e instanceof NavigationEnd || e instanceof NavigationSkipped), takeUntilDestroyed())
2963
- .subscribe(() => {
3045
+ let pendingRestore = null;
3046
+ const cancelPendingRestore = () => {
3047
+ pendingRestore?.();
3048
+ pendingRestore = null;
3049
+ };
3050
+ const scheduleRestore = (target) => {
3051
+ cancelPendingRestore();
3052
+ let frame = 0;
3053
+ let started = false;
3054
+ let cancelled = false;
3055
+ // The user scrolling always wins over a restoration we have not committed yet.
3056
+ const abortByUser = () => cancelPendingRestore();
3057
+ const hardDeadline = Date.now() + Math.max(restoreTimeout, restoreMaxTimeout);
3058
+ let deadline = Date.now() + restoreTimeout;
3059
+ const step = () => {
3060
+ frame = 0;
3061
+ if (cancelled)
3062
+ return;
3063
+ const el = resolveScrollElement();
3064
+ const maxOffset = Math.max(0, el.scrollHeight - el.clientHeight);
3065
+ if (maxOffset >= target) {
3066
+ el.scrollTop = target;
3067
+ cancelPendingRestore();
3068
+ return;
3069
+ }
3070
+ const now = Date.now();
3071
+ // A registered hold means the page knows more data is coming, so the content is expected to
3072
+ // grow — suspend the clock instead of giving up on a still loading page.
3073
+ if (holds.isHeld() && now < hardDeadline) {
3074
+ deadline = now + restoreTimeout;
3075
+ }
3076
+ if (now < deadline && now < hardDeadline) {
3077
+ frame = requestAnimationFrame(step);
3078
+ return;
3079
+ }
3080
+ if (clampOnTimeout && maxOffset > 0) {
3081
+ el.scrollTop = Math.min(target, maxOffset);
3082
+ }
3083
+ cancelPendingRestore();
3084
+ };
3085
+ // Wait for the new route to actually render before reading any geometry — on `NavigationEnd` the
3086
+ // components exist but the DOM still shows the previous page, whose height would be measured
3087
+ // instead. The timeout is a safety net in case no render pass follows.
3088
+ const start = () => {
3089
+ if (started || cancelled)
3090
+ return;
3091
+ started = true;
3092
+ frame = requestAnimationFrame(step);
3093
+ };
3094
+ const renderRef = afterNextRender({ read: start }, { injector });
3095
+ const fallback = setTimeout(start);
3096
+ for (const eventName of INTERACTION_EVENTS) {
3097
+ document.addEventListener(eventName, abortByUser, { capture: true, passive: true });
3098
+ }
3099
+ pendingRestore = () => {
3100
+ // `cancelled` is not redundant with destroying the render hook: a superseded restoration must
3101
+ // not apply its (now stale) offset even if its hook had already been queued to run.
3102
+ cancelled = true;
3103
+ renderRef.destroy();
3104
+ if (frame)
3105
+ cancelAnimationFrame(frame);
3106
+ clearTimeout(fallback);
3107
+ for (const eventName of INTERACTION_EVENTS) {
3108
+ document.removeEventListener(eventName, abortByUser, { capture: true });
3109
+ }
3110
+ };
3111
+ };
3112
+ const onNavigationStart = (event) => {
3113
+ // A new navigation supersedes a restoration that has not committed yet.
3114
+ cancelPendingRestore();
3115
+ if (!restoreEnabled)
3116
+ return;
3117
+ positions.set(lastNavigationId, resolveScrollElement().scrollTop);
3118
+ if (positions.size > MAX_STORED_POSITIONS) {
3119
+ const oldest = positions.keys().next();
3120
+ if (!oldest.done)
3121
+ positions.delete(oldest.value);
3122
+ }
3123
+ isPopstate = event.navigationTrigger === 'popstate';
3124
+ restoredNavigationId = event.restoredState?.navigationId ?? 0;
3125
+ };
3126
+ const onNavigationEnd = (event) => {
2964
3127
  const curr = { state: createRouterState(router), route: createRoute(router) };
2965
3128
  const prevState = prev.state;
2966
3129
  const currState = curr.state;
2967
3130
  const sameUrlNavigation = prev.route === curr.route;
2968
3131
  const didFragmentChange = prevState.fragment !== currState.fragment;
2969
3132
  prev = curr;
3133
+ if (event instanceof NavigationEnd) {
3134
+ lastNavigationId = event.id;
3135
+ }
3136
+ else {
3137
+ // A skipped same url navigation is not a history move, so there is nothing to restore.
3138
+ isPopstate = false;
3139
+ restoredNavigationId = 0;
3140
+ }
3141
+ if (restoreEnabled && isPopstate) {
3142
+ const target = positions.get(restoredNavigationId);
3143
+ // The saved offset wins over both scroll to top and fragment scrolling: the user may well have
3144
+ // scrolled away from the anchor before leaving the page.
3145
+ if (target !== undefined) {
3146
+ scheduleRestore(target);
3147
+ return;
3148
+ }
3149
+ }
2970
3150
  if (sameUrlNavigation) {
2971
3151
  const allQueryParams = [
2972
3152
  ...new Set(Object.keys(prevState.queryParams).concat(Object.keys(currState.queryParams))),
@@ -2978,7 +3158,7 @@ const setupScrollRestoration = (config = {}) => {
2978
3158
  const caseQueryParams = changedQueryParams.some((key) => config.queryParamTriggerList?.includes(key));
2979
3159
  const caseFragment = didFragmentChange && config.fragment?.enabled;
2980
3160
  if (caseQueryParams) {
2981
- (config.scrollElement ?? document.documentElement).scrollTop = 0;
3161
+ resolveScrollElement().scrollTop = 0;
2982
3162
  }
2983
3163
  else if (caseFragment) {
2984
3164
  const fragmentElement = document.getElementById(currState.fragment ?? '');
@@ -2994,9 +3174,17 @@ const setupScrollRestoration = (config = {}) => {
2994
3174
  if (viaReturnRoute || explicitly || pathParamsChange) {
2995
3175
  return;
2996
3176
  }
2997
- const el = config.scrollElement ?? document.documentElement;
2998
- el.scrollTop = 0;
3177
+ resolveScrollElement().scrollTop = 0;
2999
3178
  }
3179
+ };
3180
+ router.events
3181
+ .pipe(filter((e) => e instanceof NavigationStart || e instanceof NavigationEnd || e instanceof NavigationSkipped), takeUntilDestroyed())
3182
+ .subscribe((event) => {
3183
+ if (event instanceof NavigationStart) {
3184
+ onNavigationStart(event);
3185
+ return;
3186
+ }
3187
+ onNavigationEnd(event);
3000
3188
  });
3001
3189
  };
3002
3190
 
@@ -4776,6 +4964,20 @@ const setupDragObservable = (startEvent, el, commitThreshold) => {
4776
4964
  }), takeUntil(end$));
4777
4965
  return concat(moves$, defer(() => of(committed ? { type: 'end' } : { type: 'tapped' })));
4778
4966
  };
4967
+ /**
4968
+ * Observe one drag gesture, starting from a `pointerdown` on `element`.
4969
+ *
4970
+ * Emits `start` once the pointer has travelled `commitThreshold` px (so a click is not a drag),
4971
+ * immediately followed by a catch-up `move`, then a `move` per pointer move, and finally `end`. A
4972
+ * pointer released before crossing the threshold emits a single `tapped` instead. The stream
4973
+ * completes with the gesture, so there is nothing to unsubscribe on the happy path.
4974
+ *
4975
+ * This is the primitive behind {@link DragHandleDirective}. Prefer the directive; reach for this when
4976
+ * the draggable element belongs to someone else's template (e.g. a table feature attaching a drag to
4977
+ * header cells the table itself renders) and you can only work from a delegated `pointerdown`.
4978
+ */
4979
+ const dragGestureFrom = (event, element, options) => setupDragObservable(event, element, options?.commitThreshold ?? 8);
4980
+
4779
4981
  class DragHandleDirective {
4780
4982
  constructor() {
4781
4983
  this.el = inject(ElementRef);
@@ -4783,7 +4985,7 @@ class DragHandleDirective {
4783
4985
  ...(ngDevMode ? [{ debugName: "commitThreshold" }] : /* istanbul ignore next */ []));
4784
4986
  this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4785
4987
  this.gestureStart$ = new Subject();
4786
- this.gesture$ = this.gestureStart$.pipe(exhaustMap((event) => setupDragObservable(event, this.el.nativeElement, this.commitThreshold())), takeUntilDestroyed(), share());
4988
+ this.gesture$ = this.gestureStart$.pipe(exhaustMap((event) => dragGestureFrom(event, this.el.nativeElement, { commitThreshold: this.commitThreshold() })), takeUntilDestroyed(), share());
4787
4989
  this.dragTapped = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'tapped'), map(() => undefined)));
4788
4990
  this.dragStarted = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'start'), map((e) => e.data)));
4789
4991
  this.dragMoved = outputFromObservable(this.gesture$.pipe(filter((e) => e.type === 'move'), map((e) => e.data)));
@@ -8257,5 +8459,5 @@ const createUnsavedChangesGuard = (config) => {
8257
8459
  * Generated bundle index. Do not edit.
8258
8460
  */
8259
8461
 
8260
- export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PROVIDER, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RuntimeError, SEO_DIRECTIVE_TOKEN, SURFACE_PROVIDER, SURFACE_TYPE, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SeoDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, deleteCookie, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, markdownToHtml, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideViewportConfig, randomId, readFromClipboard, resetPositioningStyles, resolveAppRootColorProvider, resolveSurfaceByElevation, round, routerDisableScrollTop, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
8462
+ export { ANIMATABLE_TOKEN, ANIMATED_IF_TOKEN, ANIMATED_LIFECYCLE_TOKEN, ANIMATION_DEBUG_STORAGE_KEY, AT_LEAST_ONE_REQUIRED, AnimatableDirective, AnimatedIfDirective, AnimatedLifecycleDirective, AnimatedOverlayDirective, AutoSurfaceDirective, BOUNDARY_ELEMENT_TOKEN, BREAKPOINT_INSTANCE_TOKEN, BREAKPOINT_ORDER, COLOR_PROVIDER, ClickOutsideDirective, ColorInteractiveContainerDirective, ColorInteractiveDirective, ColorInteractiveExcludeDirective, ColorInteractiveHasFocusDirective, DEFAULT_MULTI_INSTANCE_RELS, DEFAULT_MULTI_INSTANCE_TAGS, DEFAULT_VIEWPORT_CONFIG, DISABLE_LOGGER_PARAM, DragHandleDirective, ET_DISABLE_SCROLL_TOP, ET_DISABLE_SCROLL_TOP_AS_RETURN_ROUTE, ET_DISABLE_SCROLL_TOP_ON_PATH_PARAM_CHANGE, ET_PROPERTY_REMOVED, FOCUSABLE_SELECTOR, FOCUS_VISIBLE_TRACKER_TOKEN, HtmlToMarkdownPipe, IS_ARRAY_NOT_EMPTY, IS_EMAIL, InferMimeTypePipe, InitialsPipe, IsArrayNotEmpty, IsEmail, jsonLd as JsonLD, KeyPressManager, MUST_MATCH, MarkdownToHtmlPipe, MustMatch, NormalizeGameResultTypePipe, NormalizeMatchParticipantsPipe, NormalizeMatchScorePipe, NormalizeMatchStatePipe, NormalizeMatchTypePipe, PropsDirective, ProvideColorDirective, ProvideSurfaceDirective, RUNTIME_ERROR_NO_DATA, RepeatDirective, ResizeHandlesComponent, RuntimeError, SEO_DIRECTIVE_TOKEN, SURFACE_PROVIDER, SURFACE_TYPE, ScrollObserverDirective, ScrollObserverEndDirective, ScrollObserverStartDirective, SeoDirective, SlugifyPipe, StructuredDataComponent, SurfaceInteractiveDirective, ToArrayPipe, TypedQueryList, ValidateAtLeastOneRequired, Validators, animationDebugLog, applyAlternateBinding, applyAlternateLanguagesBindings, applyArticleBindings, applyAuthorBinding, applyCanonicalBinding, applyCenteredPosition, applyDescriptionBinding, applyGlobalPosition, applyHeadBinding, applyHeadTitleBinding, applyHostListener, applyHostListeners, applyInitialFocus, applyKeywordsBinding, applyLinkBinding, applyMetaBinding, applyNextBinding, applyOgBinding, applyOpenGraphBindings, applyPrevBinding, applyResourceHintsBindings, applyRobotsBinding, applySocialMediaBindings, applyStructuredDataBinding, applyTwitterCardBindings, areScrollStatesEqual, bindProps, boolBreakpointTransform, booleanBreakpointAttribute, boundingClientRectToElementRect, breakpointTransformBase, buildElementSignal, buildSignalEffects, canUseSessionMemory, clamp, clone, cloneFormGroup, computedTillFalsy, computedTillTruthy, controlValueSignal, controlValueSignalWithPrevious, copyToClipboard, createAnchoredPositionCleanup, createArrayPropertyBinding, createAutoSessionMemoryKey, createBulkPropertyBinding, createCanAnimateSignal, createComponentId, createCssColorThemeName, createCssSurfaceName, createDependencyStash, createDestroy, createDocumentElementSignal, createElementDictionary, createElementDimensions, createEmptyElementSignal, createFlipAnimation, createFlipAnimationGroup, createHostProps, createIsRenderedSignal, createLogger, createOverlayRuntimeRef, createPropHandlers, createPropertyBinding, createProps, createProvider, createRootProvider, createRootThemeCss, createRoute, createRouterState, createRxHostListener, createSessionMemory, createSetup, createStaticProvider, createStaticRootProvider, createSwatchCss, createSwipeTracker, createTailwindColorThemes, createTailwindCssVar, createTailwindRgbVar, createThemeStyle, createUnsavedChangesGuard, createUnsavedChangesTracker, createUserConsentProvider, deferredSignal, deleteCookie, dragGestureFrom, easeElastic, easeIn, easeInOut, easeLinear, easeOut, easeOutBack, easeOutBackStrong, elementCanScroll, equal, firstElementSignal, focusElement, forceReflow, formatRuntimeError, fromNextFrame, getCookie, getDomain, getElementScrollCoordinates, getFocusableElements, getFormGroupValue, getGroupMatchPoints, getGroupMatchScore, getHeadingElement, getKnockoutMatchScore, getMatchScoreSubLine, getObjectProperty, getScrollContainerTarget, getScrollItemTarget, getScrollSnapTarget, hasCookie, holdScrollRestoration, htmlToMarkdown, inferMimeType, initials, injectAngularRootElement, injectAnimatedBlockSize, injectBoundaryElement, injectBreakpointInput, injectBreakpointIsMatched, injectBreakpointObserver, injectCanHover, injectColorThemes, injectColorThemesPrefix, injectCurrentBreakpoint, injectDeviceInputType, injectDisplayOrientation, injectErrorTheme, injectFocusVisibleTracker, injectFragment, injectHasPrecisionInput, injectHasTouchInput, injectHostElement, injectIs2Xl, injectIsDocumentVisible, injectIsLandscape, injectIsLg, injectIsMd, injectIsPortrait, injectIsRouterInitialized, injectIsSm, injectIsXl, injectIsXs, injectLinkStore, injectLinkStoreConfig, injectLocale, injectMediaQueryIsMatched, injectMetaConfig, injectMetaStore, injectObserveBreakpoint, injectObserveMediaQuery, injectOverlayRuntime, injectPathParam, injectPathParamChanges, injectPathParams, injectPrefersReducedMotion, injectQueryParam, injectQueryParamChanges, injectQueryParams, injectRenderer, injectRoute, injectRouteData, injectRouteDataItem, injectRouteTitle, injectRouterEvent, injectRouterState, injectScrollbarDimensions, injectStructuredDataConfig, injectStructuredDataStore, injectStyleManager, injectSuccessTheme, injectSurfaceContextTracker, injectSurfaceThemes, injectSurfaceThemesPrefix, injectTemplateRef, injectTitleConfig, injectTitleStore, injectUrl, injectViewportConfig, injectViewportDimensions, injectViewportSize, injectWarningTheme, isAnimationDebugEnabled, isArray, isElementSignal, isElementVisible, isFocusable, isGroupMatch, isHTMLElement, isKnockoutMatch, isObject, markdownToHtml, maybeSignalValue, memoizeSignal, nextFrame, normalizeGameResultType, normalizeMatchParticipant, normalizeMatchParticipants, normalizeMatchScore, normalizeMatchState, normalizeMatchType, normalizeUnsavedChangesSource, numberBreakpointAttribute, numberBreakpointTransform, previousSignalValue, provideBoundaryElement, provideBreakpointInstance, provideBreakpointObserver, provideColorThemes, provideColorThemesWithTailwind4, provideFocusVisibleTracker, provideLinkStore, provideLinkStoreConfig, provideLocale, provideMetaConfig, provideMetaStore, provideOverlayRuntime, provideRenderer, provideStructuredDataConfig, provideStructuredDataStore, provideStyleManager, provideSurfaceContextTracker, provideSurfaceThemesWithTailwind4, provideTitleConfig, provideTitleStore, provideViewportConfig, randomId, readFromClipboard, resetPositioningStyles, resolveAppRootColorProvider, resolveSurfaceByElevation, round, routerDisableScrollTop, scrollToElement, setBackdropStyles, setBaseElementStyles, setCookie, setInputSignal, setupFocusTrap, setupPositioning, setupScrollRestoration, signalAnimatedNumber, signalAttributes, signalClasses, signalElementChildren, signalElementDimensions, signalElementIntersection, signalElementLastScrollDirection, signalElementMutations, signalElementScrollState, signalHostAttributes, signalHostClasses, signalHostElementDimensions, signalHostElementIntersection, signalHostElementLastScrollDirection, signalHostElementMutations, signalHostElementScrollState, signalHostStyles, signalIsRendered, signalStyles, slugify, switchQueryListChanges, syncSignal, templateComputed, toArray, toArrayTrackByFn, toStringBinding, transformOrReturn, typedBreakpointTransform, unbindProps, useCursorDragScroll, writeScrollbarSizeToCssVariables, writeViewportSizeToCssVariables, ɵProvideColorThemes, ɵProvideColorThemesPrefix, ɵProvideSurfaceThemes, ɵProvideSurfaceThemesPrefix };
8261
8463
  //# sourceMappingURL=ethlete-core.mjs.map