@ethlete/core 5.0.0-next.23 → 5.0.0-next.24

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,31 @@
1
1
  # @ethlete/core
2
2
 
3
+ ## 5.0.0-next.24
4
+
5
+ ### Minor Changes
6
+
7
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`2f18e43`](https://github.com/ethlete-io/ethdk/commit/2f18e4344759dbbcd17ba0dbeca138f1f7043cdf) Thanks [@github-actions](https://github.com/apps/github-actions)! - Anchored overlays: the `shift` option now also accepts `{ crossAxis?: boolean }` in addition to a boolean. With `crossAxis: true`, an overlay that fits on neither side of its reference is shifted along the placement's cross axis to stay inside the viewport (it may then overlap the reference) instead of overflowing off-screen.
8
+
9
+ Menus enable this by default: a nested submenu near the viewport edge first flips to the other side and, when neither side fits, slides over its parent menu — matching native OS menu behavior — instead of being cut off by the viewport.
10
+
11
+ The `size` middleware (`autoResize`) now runs after `shift` instead of before it, so `--et-overlay-max-width` / `--et-overlay-max-height` are measured from the pane's shifted position. Previously a cross-axis-shifted pane had its max size capped to the unshifted leftover space, squeezing e.g. a submenu to a sliver instead of letting it keep its width while overlapping its parent.
12
+
13
+ ### Patch Changes
14
+
15
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`2f18e43`](https://github.com/ethlete-io/ethdk/commit/2f18e4344759dbbcd17ba0dbeca138f1f7043cdf) Thanks [@github-actions](https://github.com/apps/github-actions)! - Animations: fix overlays getting stuck in the DOM in an invisible but click-blocking state when their leave transition never reported completion.
16
+
17
+ When several anchored overlays close at once (e.g. clicking an item inside a nested menu closes the whole menu tree), destroying an ancestor pane shifts the anchored position of a still-leaving descendant. The browser then cancels and restarts the running transition, so its end event arrives either flagged as cancelled or under a stale transition id — and the animated lifecycle waited forever for an event that could no longer arrive, leaving the pane orphaned at `opacity: 0` while still intercepting pointer events. The lifecycle now treats the transition as settled once no animation is running anymore, matching the fallback the interrupted-transition path already had, so the overlay is torn down reliably.
18
+
19
+ - [#3016](https://github.com/ethlete-io/ethdk/pull/3016) [`3b359e5`](https://github.com/ethlete-io/ethdk/commit/3b359e52c5efa1cd9b0e79216fc578525aafa8e8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Tailwind surface & color theme generators: fix the dynamic `--color-*-surface-*` /
20
+ `--color-*-theme-*` variables not resolving per scope. They were emitted only inside
21
+ `@theme`, which lands on `:root`, so `rgb(var(--<runtime>-surface-background))` resolved
22
+ once against the root surface and inherited that concrete color into descendants. As a
23
+ result `bg-<prefix>-surface-*` / `bg-<prefix>-theme-*` utilities ignored nested
24
+ `.<runtime>-surface--*` / `.<runtime>-color--*` scopes (e.g. an elevated surface would
25
+ still paint the root background). The dynamic colors are now also re-declared on each
26
+ surface/color selector in the alias block, so the utilities resolve against the nearest
27
+ scope while still being generated from `@theme`.
28
+
3
29
  ## 5.0.0-next.23
4
30
 
5
31
  ### Major Changes
package/README.md CHANGED
@@ -1,7 +1,33 @@
1
- # core
1
+ # @ethlete/core
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ Angular framework primitives for the Ethlete SDK — signal-based DOM observation, the surface/color theming systems, the animation and overlay engines, and a toolbox of directives, pipes and utilities. Component-less; every other `@ethlete/*` UI library builds on it.
4
4
 
5
- ## Running unit tests
5
+ ## Installation
6
6
 
7
- Run `nx test core` to execute the unit tests.
7
+ ```bash
8
+ yarn add @ethlete/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { injectCurrentBreakpoint, signalHostElementDimensions } from '@ethlete/core';
15
+
16
+ @Component({
17
+ /* … */
18
+ })
19
+ export class ExampleComponent {
20
+ breakpoint = injectCurrentBreakpoint();
21
+ dimensions = signalHostElementDimensions();
22
+ }
23
+ ```
24
+
25
+ ## Documentation
26
+
27
+ Full guides on the docs site:
28
+
29
+ - [Overview](https://ethlete-sdk-docs.web.app/core/)
30
+ - [Element signals](https://ethlete-sdk-docs.web.app/core/element-signals) & [signal utilities](https://ethlete-sdk-docs.web.app/core/signal-utils)
31
+ - [Theming](https://ethlete-sdk-docs.web.app/core/theming)
32
+ - [Animations](https://ethlete-sdk-docs.web.app/core/animations) & [overlay runtime](https://ethlete-sdk-docs.web.app/core/overlay-runtime)
33
+ - [Providers](https://ethlete-sdk-docs.web.app/core/providers), [SEO](https://ethlete-sdk-docs.web.app/core/seo) & [utilities](https://ethlete-sdk-docs.web.app/core/utilities)
@@ -3634,7 +3634,21 @@ class AnimatedLifecycleDirective {
3634
3634
  this.removeClass(fromClass);
3635
3635
  this.addClass(toClass);
3636
3636
  }
3637
- }), switchMap(() => this.animatable.animationEnd$), filter((e) => this.state$.value === expectedState && !e.cancelled && e.transitionId === transitionId), tap(onComplete), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
3637
+ }), switchMap(() => this.animatable.animationEnd$), filter(() => this.state$.value === expectedState), switchMap((e) => {
3638
+ if (!e.cancelled && e.transitionId === transitionId) {
3639
+ return of(true);
3640
+ }
3641
+ // The batch ended cancelled or under a different id — e.g. the browser cancelled and
3642
+ // restarted a running transition mid-flight (an anchored overlay whose ancestor pane got
3643
+ // destroyed) or a foreign transition on the same element finished. If nothing is
3644
+ // animating anymore the expected end event can never arrive, so treat the transition as
3645
+ // settled instead of waiting forever (mirrors the fallback in handleInterruptedTransition).
3646
+ return this.animatable.isAnimating$.pipe(take(1), tap((stillAnimating) => {
3647
+ if (!stillAnimating) {
3648
+ this.debugLog(`${transitionId}: completes via fallback (batch id "${e.transitionId ?? 'none'}", cancelled ${e.cancelled})`);
3649
+ }
3650
+ }), map((stillAnimating) => !stillAnimating));
3651
+ }), filter((settled) => settled && this.state$.value === expectedState), tap(onComplete), take(1), takeUntil(cancelSignal), takeUntilDestroyed(this.destroyRef))
3638
3652
  .subscribe();
3639
3653
  }
3640
3654
  handleInterruptedTransition(config) {
@@ -4583,6 +4597,15 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
4583
4597
  fallbackPlacements: strategy.fallbackPlacements ?? undefined,
4584
4598
  fallbackAxisSideDirection: 'start',
4585
4599
  }));
4600
+ if (strategy.shift !== false) {
4601
+ middleware.push(shift({
4602
+ crossAxis: typeof strategy.shift === 'object' ? (strategy.shift.crossAxis ?? false) : false,
4603
+ limiter: limitShift(),
4604
+ padding: strategy.viewportPadding ?? 8,
4605
+ }));
4606
+ }
4607
+ // size must run AFTER shift so the available space is measured from the shifted position —
4608
+ // otherwise a cross-axis-shifted pane gets its max size capped to the unshifted leftover space
4586
4609
  if (strategy.autoResize) {
4587
4610
  middleware.push(size({
4588
4611
  padding: strategy.viewportPadding ?? 8,
@@ -4594,12 +4617,6 @@ const createAnchoredPositionCleanup = (strategy, paneElement, overlayRef, render
4594
4617
  },
4595
4618
  }));
4596
4619
  }
4597
- if (strategy.shift !== false) {
4598
- middleware.push(shift({
4599
- limiter: limitShift(),
4600
- padding: strategy.viewportPadding ?? 8,
4601
- }));
4602
- }
4603
4620
  if (arrowElement) {
4604
4621
  middleware.push(arrow({
4605
4622
  element: arrowElement,