Skip to content

Commit 10d337c

Browse files
authored
Merge branch 'master' into didimmova/update-textarea-theme
2 parents 3041f99 + a215567 commit 10d337c

31 files changed

+1055
-744
lines changed

ROADMAP.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,29 @@
22

33
# Current Milestone
44

5-
## Milestone 17 (Due Jun, 2025)
5+
## Milestone 20 (Due Nov, 2025)
66

7-
1. Date range picker [1596](https://github.com/IgniteUI/igniteui-webcomponents/issues/1596)
8-
2. Tooltip component [1615](https://github.com/IgniteUI/igniteui-webcomponents/issues/1615)
7+
1. Grids Cell Merging feature
8+
2. Grids Pining on both sides feature
99

1010
## Going down the road
1111

12-
1. Bottom navigation component [#169](https://github.com/IgniteUI/igniteui-webcomponents/issues/169)
13-
2. Splitter component [#184](https://github.com/IgniteUI/igniteui-webcomponents/issues/184)
14-
3. Chat UI component
12+
1. Grids localization
1513

1614
# Previous Milestone
1715

16+
## Milestone 19, version 6.3.0, Released Sep 18th, 2025
17+
18+
1. **[DONE]** Chat component
19+
20+
## Milestone 18, version 6.1.0, Released Jun 12th, 2025
21+
22+
1. **[DONE]** Date range picker [1596](https://github.com/IgniteUI/igniteui-webcomponents/issues/1596)
23+
24+
## Milestone 17, version 5.4.0, Released Apr 23rd, 2025
25+
26+
1. **[DONE]** Tooltip component [1615](https://github.com/IgniteUI/igniteui-webcomponents/issues/1615)
27+
1828
## Milestone 16, version 5.3.0, Released Mar 13th, 2025
1929

2030
1. **[DONE]** Tile manager component [#1402](https://github.com/IgniteUI/igniteui-webcomponents/pull/1402)

src/animations/player.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ describe('Animations Player', () => {
6363
it('should cancel running animations', async () => {
6464
const [playbackEvent] = (await Promise.all([
6565
el.player.play(fade),
66-
el.player.stopAll(),
66+
el.player.cancelAll(),
6767
])) as AnimationPlaybackEvent[];
6868

6969
expect(playbackEvent.type).to.equal('cancel');

src/animations/player.ts

Lines changed: 81 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,113 @@
11
import type { ReactiveController, ReactiveControllerHost } from 'lit';
22
import type { Ref } from 'lit/directives/ref.js';
3-
43
import { isElement } from '../components/common/util.js';
54
import type { AnimationReferenceMetadata } from './types.js';
65

7-
const listenerOptions = { once: true };
6+
/**
7+
* Defines the result of an optional View Transition start.
8+
*/
9+
type ViewTransitionResult = {
10+
transition?: ViewTransition;
11+
};
12+
13+
const LISTENER_OPTIONS = { once: true } as const;
814

9-
function getPrefersReducedMotion() {
15+
/**
16+
* Checks the user's preference for reduced motion.
17+
*/
18+
function getPrefersReducedMotion(): boolean {
1019
return globalThis?.matchMedia('(prefers-reduced-motion: reduce)').matches;
1120
}
1221

22+
/**
23+
* A ReactiveController for managing Web Animation API (WAAPI) playback
24+
* on a host element or a specified target element.
25+
*
26+
* It provides methods to play, stop, and coordinate animations, including
27+
* support for 'height: auto' transitions and reduced motion preference.
28+
*/
1329
class AnimationController implements ReactiveController {
14-
protected get target() {
15-
if (isElement(this._target)) {
16-
return this._target;
30+
private readonly _host: ReactiveControllerHost & HTMLElement;
31+
private readonly _ref?: Ref<HTMLElement> | HTMLElement;
32+
33+
/**
34+
* The actual HTMLElement target for the animations.
35+
* Prioritizes a passed-in Ref value, then a direct HTMLElement, falling back to the host.
36+
*/
37+
protected get _target(): HTMLElement {
38+
if (isElement(this._ref)) {
39+
return this._ref;
1740
}
18-
return this._target?.value ?? this.host;
41+
42+
return this._ref?.value ?? this._host;
1943
}
2044

2145
constructor(
22-
private readonly host: ReactiveControllerHost & HTMLElement,
23-
private _target?: Ref<HTMLElement> | HTMLElement
46+
host: ReactiveControllerHost & HTMLElement,
47+
ref?: Ref<HTMLElement> | HTMLElement
2448
) {
25-
this.host.addController(this);
49+
this._host = host;
50+
this._ref = ref;
51+
this._host.addController(this);
2652
}
2753

28-
private parseKeyframes(keyframes: Keyframe[]) {
29-
return keyframes.map((keyframe) => {
30-
if (!keyframe.height) return keyframe;
31-
32-
return {
33-
...keyframe,
34-
height:
35-
keyframe.height === 'auto'
36-
? `${this.target.scrollHeight}px`
37-
: keyframe.height,
38-
};
54+
/** Pre-processes keyframes, specifically resolving 'auto' height to the element's scrollHeight. */
55+
private _parseKeyframes(keyframes: Keyframe[]): Keyframe[] {
56+
const target = this._target;
57+
58+
return keyframes.map((frame) => {
59+
return frame.height === 'auto'
60+
? { ...frame, height: `${target.scrollHeight}px` }
61+
: frame;
3962
});
4063
}
4164

42-
public async play(animation: AnimationReferenceMetadata) {
65+
/** @internal */
66+
public hostConnected(): void {}
67+
68+
/** Plays a sequence of keyframes, first cancelling all existing animations on the target. */
69+
public async playExclusive(
70+
animation: AnimationReferenceMetadata
71+
): Promise<boolean> {
72+
await this.cancelAll();
73+
74+
const event = await this.play(animation);
75+
return event.type === 'finish';
76+
}
77+
78+
/**
79+
* Plays a sequence of keyframes using WAAPI.
80+
* Automatically sets duration to 0 if 'prefers-reduced-motion' is set.
81+
*/
82+
public async play(
83+
animation: AnimationReferenceMetadata
84+
): Promise<AnimationPlaybackEvent> {
4385
const { steps, options } = animation;
86+
const duration = getPrefersReducedMotion() ? 0 : (options?.duration ?? 0);
4487

45-
if (options?.duration === Number.POSITIVE_INFINITY) {
88+
if (!Number.isFinite(duration)) {
4689
throw new Error('Promise-based animations must be finite.');
4790
}
4891

4992
return new Promise<AnimationPlaybackEvent>((resolve) => {
50-
const animation = this.target.animate(this.parseKeyframes(steps), {
93+
const animation = this._target.animate(this._parseKeyframes(steps), {
5194
...options,
52-
duration: getPrefersReducedMotion() ? 0 : options!.duration,
95+
duration,
5396
});
5497

55-
animation.addEventListener('cancel', resolve, listenerOptions);
56-
animation.addEventListener('finish', resolve, listenerOptions);
98+
animation.addEventListener('cancel', resolve, LISTENER_OPTIONS);
99+
animation.addEventListener('finish', resolve, LISTENER_OPTIONS);
57100
});
58101
}
59102

60-
public stopAll() {
61-
return Promise.all(
62-
this.target.getAnimations().map((animation) => {
63-
return new Promise((resolve) => {
64-
const resolver = () => requestAnimationFrame(resolve);
65-
animation.addEventListener('cancel', resolver, listenerOptions);
66-
animation.addEventListener('finish', resolver, listenerOptions);
67-
68-
animation.cancel();
69-
});
70-
})
71-
);
72-
}
73-
74-
public async playExclusive(animation: AnimationReferenceMetadata) {
75-
const [_, event] = await Promise.all([
76-
this.stopAll(),
77-
this.play(animation),
78-
]);
103+
/** Cancels all active animations on the target element. */
104+
public cancelAll(): Promise<void> {
105+
for (const animation of this._target.getAnimations()) {
106+
animation.cancel();
107+
}
79108

80-
return event.type === 'finish';
109+
return Promise.resolve();
81110
}
82-
83-
public hostConnected() {}
84111
}
85112

86113
/**
@@ -91,14 +118,14 @@ class AnimationController implements ReactiveController {
91118
export function addAnimationController(
92119
host: ReactiveControllerHost & HTMLElement,
93120
target?: Ref<HTMLElement> | HTMLElement
94-
) {
121+
): AnimationController {
95122
return new AnimationController(host, target);
96123
}
97124

98-
type ViewTransitionResult = {
99-
transition?: ViewTransition;
100-
};
101-
125+
/**
126+
* Initiates a View Transition if supported by the browser and not suppressed by
127+
* the 'prefers-reduced-motion' setting.
128+
*/
102129
export function startViewTransition(
103130
callback?: ViewTransitionUpdateCallback
104131
): ViewTransitionResult {

0 commit comments

Comments
 (0)