From 5de193183c48eb0198f6eb22da482caa6810808a Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Wed, 20 Nov 2024 23:39:32 +0100 Subject: [PATCH] Add support for "fa-rotate-by" Fixes #454 --- docs/usage/features.md | 2 + projects/demo/e2e/src/app.e2e-spec.ts | 2 +- projects/demo/src/app/app.component.html | 4 +- src/lib/icon/icon.component.spec.ts | 53 ++++++++++++++++++++++++ src/lib/icon/icon.component.ts | 11 ++++- src/lib/layers/layers-text.component.ts | 11 ++++- src/lib/shared/models/props.model.ts | 2 +- src/lib/shared/utils/classlist.util.ts | 10 ++++- 8 files changed, 87 insertions(+), 8 deletions(-) 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, };