@ethlete/components 1.0.0-next.28 → 1.0.0-next.29
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,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-next.29
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`90dad92`](https://github.com/ethlete-io/ethdk/commit/90dad922e8985b76e5f5ad67727333de6f5b9431) Thanks [@TomTomB](https://github.com/TomTomB)! - Overlays now elevate one level above the surface their **trigger** actually sits on, resolved from the trigger's nearest surface ancestor in the DOM rather than from dependency injection. The overlay container previously read its parent surface from the injector context (`SURFACE_PROVIDER`), which is wrong across the portal boundary: an overlay's trigger keeps the injector of where it was _declared_, and the anchored panel overlays (select, cascader, date-picker, menu) mount with no DI link to the trigger at all — so they always landed at elevation 1.
|
|
8
|
+
|
|
9
|
+
This fixes two cases:
|
|
10
|
+
|
|
11
|
+
- A `select` (or any anchored panel) opened from **inside a dialog** now mounts at elevation 2 instead of matching the dialog's elevation 1.
|
|
12
|
+
- A picker anchored to a field inside an **elevated card** (e.g. a date input in a card at elevation 1) now elevates above the card instead of staying at elevation 1.
|
|
13
|
+
|
|
14
|
+
Nested content (submenus elevating above their parent menu) and the plain non-nested case (an overlay opened from the base page mounts at elevation 1) are unchanged. Modal dialogs still always mount at elevation 1 — a backdrop resets the visual context.
|
|
15
|
+
|
|
3
16
|
## 1.0.0-next.28
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { ViewEncapsulation, Component, Directive, input, booleanAttribute, signal, effect, numberAttribute, computed, inject, ElementRef, afterNextRender, DestroyRef, InjectionToken, model, linkedSignal, output, Injector, runInInjectionContext, untracked, ApplicationRef, viewChild, ViewContainerRef, createEnvironmentInjector, DOCUMENT, EnvironmentInjector, inputBinding, createComponent, TemplateRef, afterRenderEffect, contentChild, viewChildren, outputBinding, afterEveryRender, isSignal, assertInInjectionContext, isDevMode, provideEnvironmentInitializer, PLATFORM_ID, contentChildren } from '@angular/core';
|
|
3
3
|
import * as i1 from '@ethlete/core';
|
|
4
|
-
import { injectStyleManager, SurfaceInteractiveDirective, RuntimeError, createCanAnimateSignal, ColorInteractiveDirective, ProvideColorDirective, injectErrorTheme, signalElementDimensions, createProvider, ProvideSurfaceDirective, COLOR_PROVIDER, SURFACE_PROVIDER, injectSurfaceThemes, injectSurfaceContextTracker, injectRenderer, injectBoundaryElement, ANIMATED_LIFECYCLE_TOKEN, resolveAppRootColorProvider, resolveSurfaceByElevation, provideBoundaryElement, AnimatedLifecycleDirective, injectBreakpointObserver, isHTMLElement, equal, animationDebugLog, createRootProvider, injectOverlayRuntime, injectAnimatedBlockSize, randomId, createStaticRootProvider, forceReflow, nextFrame, elementCanScroll, createSwipeTracker, createComponentId, injectObserveBreakpoint, AutoSurfaceDirective, AnimatableDirective, ColorInteractiveContainerDirective, ColorInteractiveExcludeDirective, createFlipAnimation, injectPrefersReducedMotion, createFlipAnimationGroup, ColorInteractiveHasFocusDirective, htmlToMarkdown, markdownToHtml, injectHasTouchInput, injectLocale, clamp, signalHostElementDimensions, DragHandleDirective, ResizeHandlesComponent, copyToClipboard, ScrollObserverDirective, signalElementScrollState, ScrollObserverStartDirective, ScrollObserverEndDirective, applyHostListener, injectQueryParam, createUnsavedChangesTracker, createDocumentElementSignal, fromNextFrame, injectRoute, AnimatedIfDirective, applyInitialFocus, syncSignal, typedBreakpointTransform, signalElementChildren, signalElementIntersection, signalHostAttributes, signalHostClasses, signalHostStyles, getScrollContainerTarget, getScrollItemTarget, getElementScrollCoordinates, provideBreakpointInstance, signalClasses, useCursorDragScroll, signalStyles, getScrollSnapTarget, injectViewportSize, signalHostElementIntersection, setInputSignal, injectHostElement, injectRouterEvent, canUseSessionMemory, createAutoSessionMemoryKey, createSessionMemory, injectFocusVisibleTracker } from '@ethlete/core';
|
|
4
|
+
import { injectStyleManager, SurfaceInteractiveDirective, RuntimeError, createCanAnimateSignal, ColorInteractiveDirective, ProvideColorDirective, injectErrorTheme, signalElementDimensions, createProvider, ProvideSurfaceDirective, COLOR_PROVIDER, SURFACE_PROVIDER, injectSurfaceThemes, injectSurfaceThemesPrefix, injectSurfaceContextTracker, injectRenderer, injectBoundaryElement, ANIMATED_LIFECYCLE_TOKEN, resolveAppRootColorProvider, resolveSurfaceByElevation, createCssSurfaceName, provideBoundaryElement, AnimatedLifecycleDirective, injectBreakpointObserver, isHTMLElement, equal, animationDebugLog, createRootProvider, injectOverlayRuntime, injectAnimatedBlockSize, randomId, createStaticRootProvider, forceReflow, nextFrame, elementCanScroll, createSwipeTracker, createComponentId, injectObserveBreakpoint, AutoSurfaceDirective, AnimatableDirective, ColorInteractiveContainerDirective, ColorInteractiveExcludeDirective, createFlipAnimation, injectPrefersReducedMotion, createFlipAnimationGroup, ColorInteractiveHasFocusDirective, htmlToMarkdown, markdownToHtml, injectHasTouchInput, injectLocale, clamp, signalHostElementDimensions, DragHandleDirective, ResizeHandlesComponent, copyToClipboard, ScrollObserverDirective, signalElementScrollState, ScrollObserverStartDirective, ScrollObserverEndDirective, applyHostListener, injectQueryParam, createUnsavedChangesTracker, createDocumentElementSignal, fromNextFrame, injectRoute, AnimatedIfDirective, applyInitialFocus, syncSignal, typedBreakpointTransform, signalElementChildren, signalElementIntersection, signalHostAttributes, signalHostClasses, signalHostStyles, getScrollContainerTarget, getScrollItemTarget, getElementScrollCoordinates, provideBreakpointInstance, signalClasses, useCursorDragScroll, signalStyles, getScrollSnapTarget, injectViewportSize, signalHostElementIntersection, setInputSignal, injectHostElement, injectRouterEvent, canUseSessionMemory, createAutoSessionMemoryKey, createSessionMemory, injectFocusVisibleTracker } from '@ethlete/core';
|
|
5
5
|
import { NgTemplateOutlet, DOCUMENT as DOCUMENT$1, NgComponentOutlet, Location, isPlatformBrowser } from '@angular/common';
|
|
6
6
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
7
7
|
import { endOfMonth, startOfWeek, startOfMonth, addDays, addYears, addMonths, startOfDay, isSameMonth, getDate, setDate, lastDayOfMonth, isBefore, format, isSameDay, isAfter, parse, isValid, setMilliseconds, setSeconds, setMinutes, setHours } from 'date-fns';
|
|
@@ -3110,6 +3110,7 @@ class OverlayContainerComponent {
|
|
|
3110
3110
|
this.appRef = inject(ApplicationRef);
|
|
3111
3111
|
this.overlayRef = inject(OVERLAY_REF);
|
|
3112
3112
|
this.surfaceThemes = injectSurfaceThemes({ optional: true });
|
|
3113
|
+
this.surfacePrefix = injectSurfaceThemesPrefix({ optional: true });
|
|
3113
3114
|
this.surfaceContextTracker = injectSurfaceContextTracker();
|
|
3114
3115
|
this.renderer = injectRenderer();
|
|
3115
3116
|
this.rootBoundary = injectBoundaryElement();
|
|
@@ -3133,9 +3134,18 @@ class OverlayContainerComponent {
|
|
|
3133
3134
|
this.ownColorProvider.syncWithProvider(contextColorProvider);
|
|
3134
3135
|
}
|
|
3135
3136
|
if (this.surfaceThemes) {
|
|
3136
|
-
|
|
3137
|
+
// Resolve the surface the overlay's trigger visually sits on, so the overlay elevates one
|
|
3138
|
+
// level above it. The trigger keeps its *declaration* injector even when projected/portaled
|
|
3139
|
+
// into another overlay, so DI (`parentSurfaceProvider`) reports the wrong surface for a
|
|
3140
|
+
// trigger rendered inside a dialog/menu pane, and reports nothing for the anchored panel
|
|
3141
|
+
// overlays (select/menu/date) which mount with no DI link to the trigger at all. The
|
|
3142
|
+
// trigger's nearest painted surface ancestor *in the DOM* is authoritative in every case —
|
|
3143
|
+
// an overlay pane and a plain elevated card both carry the surface class — so read that,
|
|
3144
|
+
// and fall back to DI (openers that pass a viewContainerRef but no origin).
|
|
3145
|
+
const parentSurface = this.resolveOriginSurface() ?? this.parentDiSurface();
|
|
3146
|
+
const parentType = parentSurface?.type ?? 'dark';
|
|
3137
3147
|
const hasBackdrop = this.overlayRef.config.hasBackdrop ?? this.overlayRef.config.mode !== 'non-modal';
|
|
3138
|
-
const elevation = hasBackdrop || !
|
|
3148
|
+
const elevation = hasBackdrop || !parentSurface ? 1 : parentSurface.elevation + 1;
|
|
3139
3149
|
const resolved = resolveSurfaceByElevation(this.surfaceThemes, parentType, elevation);
|
|
3140
3150
|
if (resolved) {
|
|
3141
3151
|
this.ownSurfaceProvider.forceSurface(resolved.name);
|
|
@@ -3216,6 +3226,49 @@ class OverlayContainerComponent {
|
|
|
3216
3226
|
* dialog), otherwise the first painted element in the rendered content (menu/tooltip/date-picker
|
|
3217
3227
|
* paint a nested element, potentially at a higher elevation than the host's forced surface).
|
|
3218
3228
|
*/
|
|
3229
|
+
parentDiSurface() {
|
|
3230
|
+
const provider = this.parentSurfaceProvider;
|
|
3231
|
+
if (!provider)
|
|
3232
|
+
return null;
|
|
3233
|
+
return { elevation: provider.elevation(), type: provider.surfaceType() ?? 'dark' };
|
|
3234
|
+
}
|
|
3235
|
+
/**
|
|
3236
|
+
* The surface of the nearest ancestor of the overlay's origin (trigger) that paints a resolved
|
|
3237
|
+
* surface — walking the real DOM so it sees *through* the portal/projection boundary that hides
|
|
3238
|
+
* the true parent surface from DI. Returns null when there is no origin element or no surfaced
|
|
3239
|
+
* ancestor (the overlay then falls back to DI, and ultimately to elevation 1).
|
|
3240
|
+
*/
|
|
3241
|
+
resolveOriginSurface() {
|
|
3242
|
+
const themes = this.surfaceThemes;
|
|
3243
|
+
if (!themes)
|
|
3244
|
+
return null;
|
|
3245
|
+
const origin = this.resolveOriginElement();
|
|
3246
|
+
if (!origin)
|
|
3247
|
+
return null;
|
|
3248
|
+
const prefix = this.surfacePrefix || 'et';
|
|
3249
|
+
const themeByClass = new Map();
|
|
3250
|
+
for (const theme of themes) {
|
|
3251
|
+
themeByClass.set(`${prefix}-surface--${createCssSurfaceName(theme.name)}`, theme);
|
|
3252
|
+
}
|
|
3253
|
+
for (let el = origin; el; el = el.parentElement) {
|
|
3254
|
+
for (const cls of Array.from(el.classList)) {
|
|
3255
|
+
const theme = themeByClass.get(cls);
|
|
3256
|
+
if (theme)
|
|
3257
|
+
return { elevation: theme.elevation, type: theme.type };
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
return null;
|
|
3261
|
+
}
|
|
3262
|
+
resolveOriginElement() {
|
|
3263
|
+
const origin = this.overlayRef.config.origin;
|
|
3264
|
+
if (origin instanceof HTMLElement)
|
|
3265
|
+
return origin;
|
|
3266
|
+
if (origin instanceof Event) {
|
|
3267
|
+
const target = origin.target ?? origin.currentTarget;
|
|
3268
|
+
return target instanceof HTMLElement ? target : null;
|
|
3269
|
+
}
|
|
3270
|
+
return null;
|
|
3271
|
+
}
|
|
3219
3272
|
isSheetHost(host) {
|
|
3220
3273
|
return (host.classList.contains('et-overlay--bottom-sheet') ||
|
|
3221
3274
|
host.classList.contains('et-overlay--top-sheet') ||
|