diff --git a/docs/usage/features.md b/docs/usage/features.md
index 4b78a27..8bc0667 100644
--- a/docs/usage/features.md
+++ b/docs/usage/features.md
@@ -26,6 +26,8 @@ The following features are available as part of Font Awesome. Note that the synt
+
+
```
### Flip
diff --git a/projects/demo/e2e/src/app.e2e-spec.ts b/projects/demo/e2e/src/app.e2e-spec.ts
index e2bba31..bb5abca 100644
--- a/projects/demo/e2e/src/app.e2e-spec.ts
+++ b/projects/demo/e2e/src/app.e2e-spec.ts
@@ -10,7 +10,7 @@ describe('Angular FontAwesome demo', () => {
});
it('should render all icons', async () => {
- expect(await appPage.icons.count()).toBe(46);
+ expect(await appPage.icons.count()).toBe(47);
});
it('should only add styles once', async () => {
diff --git a/projects/demo/src/app/app.component.html b/projects/demo/src/app/app.component.html
index a087210..790337a 100644
--- a/projects/demo/src/app/app.component.html
+++ b/projects/demo/src/app/app.component.html
@@ -44,7 +44,9 @@
Change color
Rotate
-
+
+
+
Animations
diff --git a/src/lib/icon/icon.component.spec.ts b/src/lib/icon/icon.component.spec.ts
index c926f43..c86a1cf 100644
--- a/src/lib/icon/icon.component.spec.ts
+++ b/src/lib/icon/icon.component.spec.ts
@@ -378,4 +378,57 @@ describe('FaIconComponent', () => {
'fa-stack. Example: .',
);
});
+
+ it('should be able to set predefined rotate as a number', () => {
+ @Component({
+ selector: 'fa-host',
+ standalone: false,
+ template: '',
+ })
+ class HostComponent {
+ constructor(iconLibrary: FaIconLibrary) {
+ iconLibrary.addIcons(faUser, faUserRegular);
+ }
+ }
+
+ const fixture = initTest(HostComponent);
+ fixture.detectChanges();
+ expect(queryByCss(fixture, '.fa-rotate-90')).toBeTruthy();
+ });
+
+ it('should be able to set predefined rotate as a string', () => {
+ @Component({
+ selector: 'fa-host',
+ standalone: false,
+ template: '',
+ })
+ class HostComponent {
+ constructor(iconLibrary: FaIconLibrary) {
+ iconLibrary.addIcons(faUser, faUserRegular);
+ }
+ }
+
+ const fixture = initTest(HostComponent);
+ fixture.detectChanges();
+ expect(queryByCss(fixture, '.fa-rotate-90')).toBeTruthy();
+ });
+
+ it('should be able to set customer rotate', () => {
+ @Component({
+ selector: 'fa-host',
+ standalone: false,
+ template: '',
+ })
+ class HostComponent {
+ constructor(iconLibrary: FaIconLibrary) {
+ iconLibrary.addIcons(faUser, faUserRegular);
+ }
+ }
+
+ const fixture = initTest(HostComponent);
+ fixture.detectChanges();
+ const svg = queryByCss(fixture, '.fa-rotate-by');
+ expect(svg).toBeTruthy();
+ expect(getComputedStyle(svg).getPropertyValue('--fa-rotate-angle')).toBe('45deg');
+ });
});
diff --git a/src/lib/icon/icon.component.ts b/src/lib/icon/icon.component.ts
index 6f7045b..e44e124 100644
--- a/src/lib/icon/icon.component.ts
+++ b/src/lib/icon/icon.component.ts
@@ -11,6 +11,7 @@ import {
PullProp,
RotateProp,
SizeProp,
+ Styles,
Transform,
} from '@fortawesome/fontawesome-svg-core';
import { FaConfig } from '../config';
@@ -18,7 +19,7 @@ import { FaIconLibrary } from '../icon-library';
import { faWarnIfIconDefinitionMissing } from '../shared/errors/warn-if-icon-html-missing';
import { faWarnIfIconSpecMissing } from '../shared/errors/warn-if-icon-spec-missing';
import { AnimationProp, FaProps } from '../shared/models/props.model';
-import { faClassList } from '../shared/utils/classlist.util';
+import { faClassList, isKnownRotateValue } from '../shared/utils/classlist.util';
import { ensureCss } from '../shared/utils/css';
import { faNormalizeIconSpec } from '../shared/utils/normalize-icon-spec.util';
import { FaStackItemSizeDirective } from '../stack/stack-item-size.directive';
@@ -59,7 +60,7 @@ export class FaIconComponent implements OnChanges {
@Input() border?: boolean;
@Input() inverse?: boolean;
@Input() symbol?: FaSymbol;
- @Input() rotate?: RotateProp;
+ @Input() rotate?: RotateProp | string;
@Input() fixedWidth?: boolean;
@Input() transform?: string | Transform;
@@ -147,6 +148,11 @@ export class FaIconComponent implements OnChanges {
const parsedTransform = typeof this.transform === 'string' ? parse.transform(this.transform) : this.transform;
+ const styles: Styles = {};
+ if (classOpts.rotate != null && !isKnownRotateValue(classOpts.rotate)) {
+ styles['--fa-rotate-angle'] = `${classOpts.rotate}`;
+ }
+
return {
title: this.title,
transform: parsedTransform,
@@ -156,6 +162,7 @@ export class FaIconComponent implements OnChanges {
attributes: {
role: this.a11yRole,
},
+ styles,
};
}
}
diff --git a/src/lib/layers/layers-text.component.ts b/src/lib/layers/layers-text.component.ts
index 53c9af9..fd104f8 100644
--- a/src/lib/layers/layers-text.component.ts
+++ b/src/lib/layers/layers-text.component.ts
@@ -7,6 +7,7 @@ import {
PullProp,
RotateProp,
SizeProp,
+ Styles,
text,
TextParams,
Transform,
@@ -14,7 +15,7 @@ import {
import { FaConfig } from '../config';
import { faWarnIfParentNotExist } from '../shared/errors/warn-if-parent-not-exist';
import { FaProps } from '../shared/models/props.model';
-import { faClassList } from '../shared/utils/classlist.util';
+import { faClassList, isKnownRotateValue } from '../shared/utils/classlist.util';
import { ensureCss } from '../shared/utils/css';
import { FaLayersComponent } from './layers.component';
@@ -33,7 +34,7 @@ export class FaLayersTextComponent implements OnChanges {
@Input() pull?: PullProp;
@Input() border?: boolean;
@Input() inverse?: boolean;
- @Input() rotate?: RotateProp;
+ @Input() rotate?: RotateProp | string;
@Input() fixedWidth?: boolean;
@Input() transform?: string | Transform;
@@ -72,10 +73,16 @@ export class FaLayersTextComponent implements OnChanges {
const parsedTransform = typeof this.transform === 'string' ? parse.transform(this.transform) : this.transform;
+ const styles: Styles = {};
+ if (classOpts.rotate != null && !isKnownRotateValue(classOpts.rotate)) {
+ styles['--fa-rotate-angle'] = `${classOpts.rotate}`;
+ }
+
return {
transform: parsedTransform,
classes: faClassList(classOpts),
title: this.title,
+ styles,
};
}
diff --git a/src/lib/shared/models/props.model.ts b/src/lib/shared/models/props.model.ts
index 90e234b..9bf142e 100644
--- a/src/lib/shared/models/props.model.ts
+++ b/src/lib/shared/models/props.model.ts
@@ -13,7 +13,7 @@ export interface FaProps {
flip?: FlipProp;
size?: SizeProp;
pull?: PullProp;
- rotate?: RotateProp;
+ rotate?: RotateProp | string;
stackItemSize?: '1x' | '2x';
}
diff --git a/src/lib/shared/utils/classlist.util.ts b/src/lib/shared/utils/classlist.util.ts
index 36bcee3..e134c1c 100644
--- a/src/lib/shared/utils/classlist.util.ts
+++ b/src/lib/shared/utils/classlist.util.ts
@@ -1,10 +1,17 @@
+import { RotateProp } from '@fortawesome/fontawesome-svg-core';
import { FaProps } from '../models/props.model';
+export const isKnownRotateValue = (rotate: RotateProp | string | undefined) =>
+ rotate != null &&
+ (rotate === 90 || rotate === 180 || rotate === 270 || rotate === '90' || rotate === '180' || rotate === '270');
+
/**
* Fontawesome class list.
* Returns classes array by props.
*/
export const faClassList = (props: FaProps): string[] => {
+ const knownRotateValue = isKnownRotateValue(props.rotate);
+
const classes = {
[`fa-${props.animation}`]: props.animation != null && !props.animation.startsWith('spin'),
'fa-spin': props.animation === 'spin' || props.animation === 'spin-reverse',
@@ -21,7 +28,8 @@ export const faClassList = (props: FaProps): string[] => {
'fa-flip-horizontal': props.flip === 'horizontal' || props.flip === 'both',
'fa-flip-vertical': props.flip === 'vertical' || props.flip === 'both',
[`fa-${props.size}`]: props.size !== null,
- [`fa-rotate-${props.rotate}`]: props.rotate !== null,
+ [`fa-rotate-${props.rotate}`]: knownRotateValue,
+ 'fa-rotate-by': props.rotate != null && !knownRotateValue,
[`fa-pull-${props.pull}`]: props.pull !== null,
[`fa-stack-${props.stackItemSize}`]: props.stackItemSize != null,
};