Revert "fix(animations): properly support boolean-based transitions and state changes (#19279)"
This reverts commit a8920eb774
.
This commit is contained in:
parent
a8920eb774
commit
6aa7cc1d96
|
@ -65,27 +65,16 @@ function parseAnimationAlias(alias: string, errors: string[]): string|Transition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TRUE_BOOLEAN_VALUES = new Set<string>();
|
|
||||||
TRUE_BOOLEAN_VALUES.add('true');
|
|
||||||
TRUE_BOOLEAN_VALUES.add('1');
|
|
||||||
|
|
||||||
const FALSE_BOOLEAN_VALUES = new Set<string>();
|
|
||||||
FALSE_BOOLEAN_VALUES.add('false');
|
|
||||||
FALSE_BOOLEAN_VALUES.add('0');
|
|
||||||
|
|
||||||
function makeLambdaFromStates(lhs: string, rhs: string): TransitionMatcherFn {
|
function makeLambdaFromStates(lhs: string, rhs: string): TransitionMatcherFn {
|
||||||
const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs);
|
|
||||||
const RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs);
|
|
||||||
|
|
||||||
return (fromState: any, toState: any): boolean => {
|
return (fromState: any, toState: any): boolean => {
|
||||||
let lhsMatch = lhs == ANY_STATE || lhs == fromState;
|
let lhsMatch = lhs == ANY_STATE || lhs == fromState;
|
||||||
let rhsMatch = rhs == ANY_STATE || rhs == toState;
|
let rhsMatch = rhs == ANY_STATE || rhs == toState;
|
||||||
|
|
||||||
if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') {
|
if (!lhsMatch && typeof fromState === 'boolean') {
|
||||||
lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs);
|
lhsMatch = fromState ? lhs === 'true' : lhs === 'false';
|
||||||
}
|
}
|
||||||
if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') {
|
if (!rhsMatch && typeof toState === 'boolean') {
|
||||||
rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs);
|
rhsMatch = toState ? rhs === 'true' : rhs === 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
return lhsMatch && rhsMatch;
|
return lhsMatch && rhsMatch;
|
||||||
|
|
|
@ -119,18 +119,18 @@ export class AnimationTransitionNamespace {
|
||||||
|
|
||||||
listen(element: any, name: string, phase: string, callback: (event: any) => boolean): () => any {
|
listen(element: any, name: string, phase: string, callback: (event: any) => boolean): () => any {
|
||||||
if (!this._triggers.hasOwnProperty(name)) {
|
if (!this._triggers.hasOwnProperty(name)) {
|
||||||
throw new Error(`Unable to listen on the animation trigger event "${
|
throw new Error(
|
||||||
phase}" because the animation trigger "${name}" doesn\'t exist!`);
|
`Unable to listen on the animation trigger event "${phase}" because the animation trigger "${name}" doesn\'t exist!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == null || phase.length == 0) {
|
if (phase == null || phase.length == 0) {
|
||||||
throw new Error(`Unable to listen on the animation trigger "${
|
throw new Error(
|
||||||
name}" because the provided event is undefined!`);
|
`Unable to listen on the animation trigger "${name}" because the provided event is undefined!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isTriggerEventValid(phase)) {
|
if (!isTriggerEventValid(phase)) {
|
||||||
throw new Error(`The provided animation trigger event "${phase}" for the animation trigger "${
|
throw new Error(
|
||||||
name}" is not supported!`);
|
`The provided animation trigger event "${phase}" for the animation trigger "${name}" is not supported!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const listeners = getOrSetAsInMap(this._elementListeners, element, []);
|
const listeners = getOrSetAsInMap(this._elementListeners, element, []);
|
||||||
|
@ -838,8 +838,7 @@ export class TransitionAnimationEngine {
|
||||||
|
|
||||||
reportError(errors: string[]) {
|
reportError(errors: string[]) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unable to process animations due to the following failed trigger transitions\n ${
|
`Unable to process animations due to the following failed trigger transitions\n ${errors.join("\n")}`);
|
||||||
errors.join('\n')}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _flushAnimations(cleanupFns: Function[], microtaskId: number):
|
private _flushAnimations(cleanupFns: Function[], microtaskId: number):
|
||||||
|
@ -1448,11 +1447,13 @@ function deleteOrUnsetInMap(map: Map<any, any[]>| {[key: string]: any}, key: any
|
||||||
return currentValues;
|
return currentValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeTriggerValue(value: any): any {
|
function normalizeTriggerValue(value: any): string {
|
||||||
// we use `!= null` here because it's the most simple
|
switch (typeof value) {
|
||||||
// way to test against a "falsy" value without mixing
|
case 'boolean':
|
||||||
// in empty strings or a zero value. DO NOT OPTIMIZE.
|
return value ? '1' : '0';
|
||||||
return value != null ? value : null;
|
default:
|
||||||
|
return value != null ? value.toString() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isElementNode(node: any) {
|
function isElementNode(node: any) {
|
||||||
|
|
|
@ -257,11 +257,6 @@ export interface AnimationStaggerMetadata extends AnimationMetadata {
|
||||||
the
|
the
|
||||||
* trigger is bound to (in the form of `[@triggerName]="expression"`.
|
* trigger is bound to (in the form of `[@triggerName]="expression"`.
|
||||||
*
|
*
|
||||||
* Animation trigger bindings strigify values and then match the previous and current values against
|
|
||||||
* any linked transitions. If a boolean value is provided into the trigger binding then it will both
|
|
||||||
* be represented as `1` or `true` and `0` or `false` for a true and false boolean values
|
|
||||||
* respectively.
|
|
||||||
*
|
|
||||||
* ### Usage
|
* ### Usage
|
||||||
*
|
*
|
||||||
* `trigger` will create an animation trigger reference based on the provided `name` value. The
|
* `trigger` will create an animation trigger reference based on the provided `name` value. The
|
||||||
|
@ -739,22 +734,6 @@ export function keyframes(steps: AnimationStyleMetadata[]): AnimationKeyframesSe
|
||||||
* ])
|
* ])
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* ### Boolean values
|
|
||||||
* if a trigger binding value is a boolean value then it can be matched using a transition
|
|
||||||
* expression that compares `true` and `false` or `1` and `0`.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* // in the template
|
|
||||||
* <div [@openClose]="open ? true : false">...</div>
|
|
||||||
*
|
|
||||||
* // in the component metadata
|
|
||||||
* trigger('openClose', [
|
|
||||||
* state('true', style({ height: '*' })),
|
|
||||||
* state('false', style({ height: '0px' })),
|
|
||||||
* transition('false <=> true', animate(500))
|
|
||||||
* ])
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ### Using :increment and :decrement
|
* ### Using :increment and :decrement
|
||||||
* In addition to the :enter and :leave transition aliases, the :increment and :decrement aliases
|
* In addition to the :enter and :leave transition aliases, the :increment and :decrement aliases
|
||||||
* can be used to kick off a transition when a numeric value has increased or decreased in value.
|
* can be used to kick off a transition when a numeric value has increased or decreased in value.
|
||||||
|
|
|
@ -475,103 +475,6 @@ export function main() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should understand boolean values as `true` and `false` for transition animations', () => {
|
|
||||||
@Component({
|
|
||||||
selector: 'if-cmp',
|
|
||||||
template: `
|
|
||||||
<div [@myAnimation]="exp"></div>
|
|
||||||
`,
|
|
||||||
animations: [
|
|
||||||
trigger(
|
|
||||||
'myAnimation',
|
|
||||||
[
|
|
||||||
transition(
|
|
||||||
'true => false',
|
|
||||||
[
|
|
||||||
style({opacity: 0}),
|
|
||||||
animate(1234, style({opacity: 1})),
|
|
||||||
]),
|
|
||||||
transition(
|
|
||||||
'false => true',
|
|
||||||
[
|
|
||||||
style({opacity: 1}),
|
|
||||||
animate(4567, style({opacity: 0})),
|
|
||||||
])
|
|
||||||
]),
|
|
||||||
]
|
|
||||||
})
|
|
||||||
class Cmp {
|
|
||||||
exp: any = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
|
||||||
|
|
||||||
const engine = TestBed.get(ɵAnimationEngine);
|
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
|
||||||
const cmp = fixture.componentInstance;
|
|
||||||
|
|
||||||
cmp.exp = true;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
cmp.exp = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
let players = getLog();
|
|
||||||
expect(players.length).toEqual(1);
|
|
||||||
let [player] = players;
|
|
||||||
|
|
||||||
expect(player.duration).toEqual(1234);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should understand boolean values as `true` and `false` for transition animations and apply the corresponding state() value',
|
|
||||||
() => {
|
|
||||||
@Component({
|
|
||||||
selector: 'if-cmp',
|
|
||||||
template: `
|
|
||||||
<div [@myAnimation]="exp"></div>
|
|
||||||
`,
|
|
||||||
animations: [
|
|
||||||
trigger(
|
|
||||||
'myAnimation',
|
|
||||||
[
|
|
||||||
state('true', style({color: 'red'})),
|
|
||||||
state('false', style({color: 'blue'})),
|
|
||||||
transition(
|
|
||||||
'true <=> false',
|
|
||||||
[
|
|
||||||
animate(1000, style({color: 'gold'})),
|
|
||||||
animate(1000),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
]
|
|
||||||
})
|
|
||||||
class Cmp {
|
|
||||||
exp: any = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
|
||||||
|
|
||||||
const engine = TestBed.get(ɵAnimationEngine);
|
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
|
||||||
const cmp = fixture.componentInstance;
|
|
||||||
|
|
||||||
cmp.exp = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
cmp.exp = true;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
let players = getLog();
|
|
||||||
expect(players.length).toEqual(1);
|
|
||||||
let [player] = players;
|
|
||||||
|
|
||||||
expect(player.keyframes).toEqual([
|
|
||||||
{color: 'blue', offset: 0},
|
|
||||||
{color: 'gold', offset: 0.5},
|
|
||||||
{color: 'red', offset: 1},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not throw an error if a trigger with the same name exists in separate components',
|
it('should not throw an error if a trigger with the same name exists in separate components',
|
||||||
() => {
|
() => {
|
||||||
@Component({selector: 'cmp1', template: '...', animations: [trigger('trig', [])]})
|
@Component({selector: 'cmp1', template: '...', animations: [trigger('trig', [])]})
|
||||||
|
|
Loading…
Reference in New Issue