@@ -21,7 +22,7 @@ describe('BusyIndicatorExtendedDirective', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
- imports: [BusyIndicatorModule]
+ imports: [BusyIndicatorExtendedDirective, BusyIndicatorComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/busy-indicator/busy-indicator-extended/busy-indicator-extended.directive.ts b/libs/core/src/lib/busy-indicator/busy-indicator-extended/busy-indicator-extended.directive.ts
index 6bbd1493dab..8e1d8696c8e 100644
--- a/libs/core/src/lib/busy-indicator/busy-indicator-extended/busy-indicator-extended.directive.ts
+++ b/libs/core/src/lib/busy-indicator/busy-indicator-extended/busy-indicator-extended.directive.ts
@@ -6,7 +6,8 @@ const messageToastClass = 'fd-message-toast';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
- selector: '[fd-busy-indicator-extended]'
+ selector: '[fd-busy-indicator-extended]',
+ standalone: true
})
export class BusyIndicatorExtendedDirective implements AfterContentInit {
/** @hidden */
diff --git a/libs/core/src/lib/busy-indicator/busy-indicator.component.spec.ts b/libs/core/src/lib/busy-indicator/busy-indicator.component.spec.ts
index fa0161dc5de..55910294f61 100644
--- a/libs/core/src/lib/busy-indicator/busy-indicator.component.spec.ts
+++ b/libs/core/src/lib/busy-indicator/busy-indicator.component.spec.ts
@@ -1,13 +1,16 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { NgIf } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BusyIndicatorComponent } from './busy-indicator.component';
-import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
template: `
Button
- `
+ `,
+ standalone: true,
+ imports: [NgIf, BusyIndicatorComponent]
})
class TestWrapperComponent {
block = true;
@@ -22,7 +25,7 @@ describe('BusyIndicatorComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [TestWrapperComponent, BusyIndicatorComponent]
+ imports: [TestWrapperComponent]
})
.overrideComponent(BusyIndicatorComponent, {
set: { changeDetection: ChangeDetectionStrategy.Default }
diff --git a/libs/core/src/lib/busy-indicator/busy-indicator.component.ts b/libs/core/src/lib/busy-indicator/busy-indicator.component.ts
index f294049d07a..adc7e864860 100644
--- a/libs/core/src/lib/busy-indicator/busy-indicator.component.ts
+++ b/libs/core/src/lib/busy-indicator/busy-indicator.component.ts
@@ -11,6 +11,7 @@ import { KeyUtil } from '@fundamental-ngx/cdk/utils';
import { Nullable } from '@fundamental-ngx/cdk/utils';
import { TAB } from '@angular/cdk/keycodes';
import { FD_BUSY_INDICATOR_COMPONENT } from './tokens';
+import { NgIf } from '@angular/common';
export type BusyIndicatorSize = 's' | 'm' | 'l';
@@ -35,7 +36,9 @@ export type BusyIndicatorSize = 's' | 'm' | 'l';
'[attr.title]': 'title',
'[class.fd-busy-indicator__container]': 'true',
'[class.fd-busy-indicator__container--inline]': '!block'
- }
+ },
+ standalone: true,
+ imports: [NgIf]
})
export class BusyIndicatorComponent {
/** Whether to display the loading indicator animation. */
@@ -60,7 +63,7 @@ export class BusyIndicatorComponent {
/** add loading label value */
@Input()
- label: string;
+ label?: string;
/** Aria live attribute value. */
@Input()
diff --git a/libs/core/src/lib/busy-indicator/busy-indicator.module.ts b/libs/core/src/lib/busy-indicator/busy-indicator.module.ts
index 42e2d04851d..a881aca3e2d 100644
--- a/libs/core/src/lib/busy-indicator/busy-indicator.module.ts
+++ b/libs/core/src/lib/busy-indicator/busy-indicator.module.ts
@@ -4,8 +4,7 @@ import { BusyIndicatorComponent } from './busy-indicator.component';
import { BusyIndicatorExtendedDirective } from './busy-indicator-extended/busy-indicator-extended.directive';
@NgModule({
- declarations: [BusyIndicatorComponent, BusyIndicatorExtendedDirective],
exports: [BusyIndicatorComponent, BusyIndicatorExtendedDirective],
- imports: [CommonModule]
+ imports: [CommonModule, BusyIndicatorComponent, BusyIndicatorExtendedDirective]
})
export class BusyIndicatorModule {}
diff --git a/libs/core/src/lib/card/card-footer.component.html b/libs/core/src/lib/card/card-footer.component.html
index 8f14f982a3f..675d6faaee5 100644
--- a/libs/core/src/lib/card/card-footer.component.html
+++ b/libs/core/src/lib/card/card-footer.component.html
@@ -1,6 +1,6 @@
diff --git a/libs/core/src/lib/carousel/carousel-item.directive.ts b/libs/core/src/lib/carousel/carousel-item.directive.ts
index d395a5ebcff..862078f6a63 100644
--- a/libs/core/src/lib/carousel/carousel-item.directive.ts
+++ b/libs/core/src/lib/carousel/carousel-item.directive.ts
@@ -4,7 +4,8 @@ let carouselItemCounter = 0;
@Directive({
selector: '[fd-carousel-item], [fdCarouselItem]',
- exportAs: 'fdCarouselItem'
+ exportAs: 'fdCarouselItem',
+ standalone: true
})
export class CarouselItemDirective {
/** Value of the item , to keep some information inside */
diff --git a/libs/core/src/lib/carousel/carousel-item/carousel-item.component.ts b/libs/core/src/lib/carousel/carousel-item/carousel-item.component.ts
index 66e49860f85..9bb90170f2b 100644
--- a/libs/core/src/lib/carousel/carousel-item/carousel-item.component.ts
+++ b/libs/core/src/lib/carousel/carousel-item/carousel-item.component.ts
@@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, ElementRef, HostBinding, Input, ViewEncapsulation } from '@angular/core';
import { CarouselItemInterface } from '../carousel.service';
import { Nullable } from '@fundamental-ngx/cdk/utils';
+import { BusyIndicatorComponent } from '@fundamental-ngx/core/busy-indicator';
export type Visibility = 'visible' | 'hidden';
@@ -10,7 +11,9 @@ let carouselItemCounter = 0;
selector: 'fd-carousel-item',
templateUrl: './carousel-item.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
- encapsulation: ViewEncapsulation.None
+ encapsulation: ViewEncapsulation.None,
+ standalone: true,
+ imports: [BusyIndicatorComponent]
})
export class CarouselItemComponent implements CarouselItemInterface {
/** Id of the Carousel items. */
diff --git a/libs/core/src/lib/carousel/carousel.component.html b/libs/core/src/lib/carousel/carousel.component.html
index 795bbdbcc60..6bf9995e501 100644
--- a/libs/core/src/lib/carousel/carousel.component.html
+++ b/libs/core/src/lib/carousel/carousel.component.html
@@ -17,6 +17,7 @@
@@ -42,7 +43,11 @@
-
+
@@ -83,27 +88,31 @@
diff --git a/libs/core/src/lib/carousel/carousel.component.spec.ts b/libs/core/src/lib/carousel/carousel.component.spec.ts
index ab5a57638ce..a66f2ea835b 100644
--- a/libs/core/src/lib/carousel/carousel.component.spec.ts
+++ b/libs/core/src/lib/carousel/carousel.component.spec.ts
@@ -2,7 +2,7 @@ import { Component, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { whenStable } from '@fundamental-ngx/core/tests';
-import { CarouselComponent, PageIndicatorsOrientation } from './carousel.component';
+import { CarouselBackgroundOptions, CarouselComponent, PageIndicatorsOrientation } from './carousel.component';
import { CarouselModule } from './carousel.module';
const carouselItems = `
@@ -18,8 +18,11 @@ const carouselItems = `
@Component({
selector: 'fd-test-carousel',
+ standalone: true,
+ imports: [CarouselModule],
template: `
[navigatorInPageIndicator]="navigatorInPageIndicator"
[pageIndicatorsOrientation]="pageIndicatorContainerPlacement"
[loop]="isCircular"
+ [noPaginationContainerBorder]="noPaginationContainerBorder"
+ [contentBackground]="contentBackground"
+ [pageIndicatorBackground]="pageIndicatorBackground"
>${carouselItems}
`
@@ -35,6 +41,7 @@ class TestCarouselComponent {
@ViewChild(CarouselComponent)
carousel: CarouselComponent;
+ vertical = false;
visibleItemsCount = 1;
showPageIndicatorContainer = true;
showPageIndicator = true;
@@ -42,6 +49,9 @@ class TestCarouselComponent {
navigatorInPageIndicator = true;
pageIndicatorContainerPlacement: PageIndicatorsOrientation = 'top';
isCircular = false;
+ noPaginationContainerBorder = false;
+ contentBackground: CarouselBackgroundOptions;
+ pageIndicatorBackground: CarouselBackgroundOptions;
}
describe('CarouselComponent', () => {
@@ -50,8 +60,7 @@ describe('CarouselComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [TestCarouselComponent],
- imports: [CarouselModule]
+ imports: [TestCarouselComponent]
}).compileComponents();
}));
@@ -65,6 +74,69 @@ describe('CarouselComponent', () => {
expect(component).toBeTruthy();
});
+ it('should apply background config', async () => {
+ const backgroundOptions: CarouselBackgroundOptions[] = ['solid', 'translucent', 'transparent'];
+
+ // Apply properties in a separate loop to exclude possibility of incorrect property binding.
+ backgroundOptions.forEach((option) => {
+ component.contentBackground = option;
+ fixture.detectChanges();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__content').classList).toContain(
+ `fd-carousel__content--${option}`
+ );
+ });
+
+ backgroundOptions.forEach((option) => {
+ component.pageIndicatorBackground = option;
+ fixture.detectChanges();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__page-indicator-container').classList).toContain(
+ `fd-carousel__page-indicator-container--${option}`
+ );
+ });
+ });
+
+ it('should change icons for vertical carousel', async () => {
+ component.vertical = false;
+ fixture.detectChanges();
+
+ expect(fixture.nativeElement.querySelector('.fd-carousel__content').classList).toContain(
+ 'fd-carousel__content--horizontal'
+ );
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--left')).toBeTruthy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--up')).toBeFalsy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--right')).toBeTruthy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--down')).toBeFalsy();
+ expect(
+ fixture.nativeElement.querySelector('.fd-carousel__button--left .sap-icon--slim-arrow-left')
+ ).toBeTruthy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--left .sap-icon--slim-arrow-up')).toBeFalsy();
+ expect(
+ fixture.nativeElement.querySelector('.fd-carousel__button--right .sap-icon--slim-arrow-right')
+ ).toBeTruthy();
+ expect(
+ fixture.nativeElement.querySelector('.fd-carousel__button--right .sap-icon--slim-arrow-down')
+ ).toBeFalsy();
+
+ component.vertical = true;
+ fixture.detectChanges();
+
+ expect(fixture.nativeElement.querySelector('.fd-carousel__content').classList).not.toContain(
+ 'fd-carousel__content--horizontal'
+ );
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--left')).toBeFalsy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--up')).toBeTruthy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--right')).toBeFalsy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--down')).toBeTruthy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--up .sap-icon--slim-arrow-left')).toBeFalsy();
+ expect(fixture.nativeElement.querySelector('.fd-carousel__button--up .sap-icon--slim-arrow-up')).toBeTruthy();
+ expect(
+ fixture.nativeElement.querySelector('.fd-carousel__button--down .sap-icon--slim-arrow-right')
+ ).toBeFalsy();
+ expect(
+ fixture.nativeElement.querySelector('.fd-carousel__button--down .sap-icon--slim-arrow-down')
+ ).toBeTruthy();
+ });
+
it('should have 8 carousel items', async () => {
await whenStable(fixture);
expect(component.carousel.slides.length).toEqual(8);
@@ -107,6 +179,8 @@ describe('CarouselComponent', () => {
@Component({
selector: 'fd-test-multiple-active-item-carousel',
+ standalone: true,
+ imports: [CarouselModule],
template: `
{
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [TestCarouselMultipleActiveItemComponent],
- imports: [CarouselModule]
+ imports: [TestCarouselMultipleActiveItemComponent]
}).compileComponents();
}));
@@ -232,6 +305,8 @@ describe('CarouselComponent Multiple Active Item', () => {
@Component({
selector: 'fd-test-looping-navigation-carousel',
+ imports: [CarouselModule],
+ standalone: true,
template: `
{
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [TestCarouselLoopingNavigationComponent],
- imports: [CarouselModule]
+ imports: [TestCarouselLoopingNavigationComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/carousel/carousel.component.ts b/libs/core/src/lib/carousel/carousel.component.ts
index e2cb51e9c14..2516aad253f 100644
--- a/libs/core/src/lib/carousel/carousel.component.ts
+++ b/libs/core/src/lib/carousel/carousel.component.ts
@@ -30,11 +30,16 @@ import { resizeObservable, RtlService } from '@fundamental-ngx/cdk/utils';
import { CarouselItemComponent } from './carousel-item/carousel-item.component';
import { CarouselResourceStringsEN, FdCarouselResourceStrings } from './i18n/carousel-resources';
import { CarouselConfig, CarouselItemInterface, CarouselService, PanEndOutput } from './carousel.service';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { NgIf, NgTemplateOutlet, NgClass, NgFor } from '@angular/common';
/** Page limit to switch to numerical indicator */
const ICON_PAGE_INDICATOR_LIMIT = 8;
export type PageIndicatorsOrientation = 'bottom' | 'top';
+export type CarouselBackgroundOptions = 'translucent' | 'transparent' | 'solid';
+
export enum SlideDirection {
None,
NEXT,
@@ -59,7 +64,9 @@ class CarouselActiveSlides {
providers: [CarouselService],
host: {
'[style.width]': 'width'
- }
+ },
+ standalone: true,
+ imports: [NgIf, NgTemplateOutlet, NgClass, NgFor, ButtonModule, FdTranslatePipe]
})
export class CarouselComponent
implements OnInit, AfterContentInit, AfterViewInit, AfterViewChecked, OnChanges, OnDestroy
@@ -145,6 +152,18 @@ export class CarouselComponent
@Input()
vertical = false;
+ /** Whether to hide top border of the Pagination Container. */
+ @Input()
+ noPaginationContainerBorder = false;
+
+ /** Background configuration for the Content container. */
+ @Input()
+ contentBackground: CarouselBackgroundOptions = 'translucent';
+
+ /** Background configuration for the Pagination container */
+ @Input()
+ pageIndicatorBackground: CarouselBackgroundOptions = 'solid';
+
/** Number of items to be visible at a time */
@Input()
set visibleSlidesCount(value: number | 'auto') {
diff --git a/libs/core/src/lib/carousel/carousel.directive.spec.ts b/libs/core/src/lib/carousel/carousel.directive.spec.ts
index d6f603343fe..5fcb7c1d542 100644
--- a/libs/core/src/lib/carousel/carousel.directive.spec.ts
+++ b/libs/core/src/lib/carousel/carousel.directive.spec.ts
@@ -55,13 +55,8 @@ describe('CarouselDirective', () => {
beforeEach(() => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
- imports: [CommonModule],
- declarations: [
- HorizontalCarouselComponent,
- VerticalCarouselComponent,
- CarouselItemDirective,
- CarouselDirective
- ],
+ imports: [CommonModule, CarouselItemDirective, CarouselDirective],
+ declarations: [HorizontalCarouselComponent, VerticalCarouselComponent],
providers: [CarouselService]
}).compileComponents();
});
diff --git a/libs/core/src/lib/carousel/carousel.directive.ts b/libs/core/src/lib/carousel/carousel.directive.ts
index 3099547955d..2132914f798 100644
--- a/libs/core/src/lib/carousel/carousel.directive.ts
+++ b/libs/core/src/lib/carousel/carousel.directive.ts
@@ -17,7 +17,8 @@ import { CarouselItemDirective } from './carousel-item.directive';
host: {
class: 'fd-carousel_'
},
- providers: [CarouselService]
+ providers: [CarouselService],
+ standalone: true
})
export class CarouselDirective implements AfterContentInit {
/** Configuration for carousel */
diff --git a/libs/core/src/lib/carousel/carousel.module.ts b/libs/core/src/lib/carousel/carousel.module.ts
index f2c971accc0..9c861c8148f 100644
--- a/libs/core/src/lib/carousel/carousel.module.ts
+++ b/libs/core/src/lib/carousel/carousel.module.ts
@@ -1,18 +1,13 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
import { CarouselItemDirective } from './carousel-item.directive';
import { CarouselDirective } from './carousel.directive';
import { CarouselComponent } from './carousel.component';
import { CarouselItemComponent } from './carousel-item/carousel-item.component';
-import { BusyIndicatorModule } from '@fundamental-ngx/core/busy-indicator';
-import { I18nModule } from '@fundamental-ngx/i18n';
-import { ButtonModule } from '@fundamental-ngx/core/button';
import { CarouselService } from './carousel.service';
@NgModule({
- imports: [CommonModule, BusyIndicatorModule, ButtonModule, I18nModule],
+ imports: [CarouselItemDirective, CarouselDirective, CarouselComponent, CarouselItemComponent],
exports: [CarouselItemDirective, CarouselDirective, CarouselComponent, CarouselItemComponent],
- declarations: [CarouselItemDirective, CarouselDirective, CarouselComponent, CarouselItemComponent],
providers: [CarouselService]
})
export class CarouselModule {}
diff --git a/libs/core/src/lib/checkbox/checkbox.module.ts b/libs/core/src/lib/checkbox/checkbox.module.ts
index 4c22c67b1ca..4f6e49fe494 100644
--- a/libs/core/src/lib/checkbox/checkbox.module.ts
+++ b/libs/core/src/lib/checkbox/checkbox.module.ts
@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
import { CheckboxComponent } from './checkbox/checkbox.component';
-import { FormsModule } from '@angular/forms';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
@NgModule({
- declarations: [CheckboxComponent],
- imports: [CommonModule, FormsModule, ContentDensityModule],
+ imports: [ContentDensityModule, CheckboxComponent],
exports: [CheckboxComponent, ContentDensityModule]
})
export class CheckboxModule {}
diff --git a/libs/core/src/lib/checkbox/checkbox/checkbox.component.html b/libs/core/src/lib/checkbox/checkbox/checkbox.component.html
index b042cea0b85..6aca17ceeaf 100644
--- a/libs/core/src/lib/checkbox/checkbox/checkbox.component.html
+++ b/libs/core/src/lib/checkbox/checkbox/checkbox.component.html
@@ -13,10 +13,12 @@
[attr.aria-describedby]="ariaDescribedBy"
[attr.aria-disabled]="disabled"
[attr.aria-required]="required"
- [class]="state ? 'is-' + state : ''"
+ [ngClass]="[displayOnly ? 'is-display' : '', state ? 'is-' + state : '']"
(click)="_onInputClick($event)"
(blur)="_onBlur()"
(focus)="_onFocus()"
+ (keyup.enter)="_onLabelKeydown($event)"
+ (keyup.space)="_onLabelKeydown($event)"
/>
diff --git a/libs/core/src/lib/checkbox/checkbox/checkbox.component.spec.ts b/libs/core/src/lib/checkbox/checkbox/checkbox.component.spec.ts
index 143afb12a46..b5e5a11d5cc 100644
--- a/libs/core/src/lib/checkbox/checkbox/checkbox.component.spec.ts
+++ b/libs/core/src/lib/checkbox/checkbox/checkbox.component.spec.ts
@@ -19,11 +19,14 @@ function checkboxDetectChanges(checkbox: CheckboxComponent): void {
}
@Component({
- template: ` `
+ template: ` `,
+ standalone: true,
+ imports: [FormsModule, CheckboxComponent]
})
class TestCheckboxWrapperComponent {
@ViewChild(CheckboxComponent) checkboxRef: CheckboxComponent;
value: any = false;
+ displayOnly = false;
}
describe('CheckboxComponent', () => {
@@ -33,8 +36,7 @@ describe('CheckboxComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [FormsModule, CheckboxModule],
- declarations: [TestCheckboxWrapperComponent]
+ imports: [TestCheckboxWrapperComponent]
}).compileComponents();
}));
@@ -186,7 +188,7 @@ describe('CheckboxComponent', () => {
it('should use custom values for third state', async () => {
checkbox.tristate = true;
checkbox.tristateSelectable = true;
- checkbox.values = { trueValue: 'Yes', falseValue: 'No', thirdStateValue: 'Maby' };
+ checkbox.values = { trueValue: 'Yes', falseValue: 'No', thirdStateValue: 'Maybe' };
hostComponent.value = 'Yes';
fixture.detectChanges();
@@ -195,10 +197,41 @@ describe('CheckboxComponent', () => {
checkbox.nextValue();
expect(hostComponent.value).toBe('No');
checkbox.nextValue();
- expect(hostComponent.value).toBe('Maby');
+ expect(hostComponent.value).toBe('Maybe');
checkbox.nextValue();
expect(hostComponent.value).toBe('Yes');
});
+
+ it('should render display-only mode', async () => {
+ hostComponent.displayOnly = true;
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(getCheckboxInput(fixture).classList).toContain('is-display');
+ });
+
+ it('should ignore user interactions when rendered in display-only mode', async () => {
+ // Check usual interaction
+ const oldValue = hostComponent.value;
+ const checkboxInput = getCheckboxInput(fixture);
+ checkboxInput.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ // Toggle happened
+ expect(hostComponent.value).not.toEqual(oldValue);
+
+ checkbox.displayOnly = true;
+ fixture.detectChanges();
+ await fixture.whenStable();
+ checkboxInput.dispatchEvent(new Event('click'));
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ // Toggle didn't happen
+ expect(hostComponent.value).not.toEqual(oldValue);
+ });
});
@Component({
diff --git a/libs/core/src/lib/checkbox/checkbox/checkbox.component.ts b/libs/core/src/lib/checkbox/checkbox/checkbox.component.ts
index 2470a8b46ba..36d4d11eb30 100644
--- a/libs/core/src/lib/checkbox/checkbox/checkbox.component.ts
+++ b/libs/core/src/lib/checkbox/checkbox/checkbox.component.ts
@@ -8,24 +8,23 @@ import {
EventEmitter,
forwardRef,
HostBinding,
- Inject,
Input,
OnDestroy,
- Optional,
Output,
Renderer2,
ViewChild,
ViewEncapsulation
} from '@angular/core';
-import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { FD_CHECKBOX_VALUES_DEFAULT, FdCheckboxValues } from './fd-checkbox-values.interface';
-import { LIST_ITEM_COMPONENT, ListItemInterface, Nullable } from '@fundamental-ngx/cdk/utils';
+import { Nullable } from '@fundamental-ngx/cdk/utils';
import equal from 'fast-deep-equal';
import { Subscription } from 'rxjs';
import { FormStates } from '@fundamental-ngx/cdk/forms';
import { FormItemControl, registerFormItemControl } from '@fundamental-ngx/core/form';
import { ContentDensityObserver, contentDensityObserverProviders } from '@fundamental-ngx/core/content-density';
import { FD_CHECKBOX_COMPONENT } from '../tokens';
+import { NgClass, NgIf } from '@angular/common';
let checkboxUniqueId = 0;
@@ -50,7 +49,9 @@ export type FdCheckboxTypes = 'checked' | 'unchecked' | 'indeterminate' | 'force
registerFormItemControl(CheckboxComponent),
contentDensityObserverProviders()
],
- host: { '[attr.tabindex]': '-1' }
+ host: { '[attr.tabindex]': '-1' },
+ standalone: true,
+ imports: [NgIf, FormsModule, NgClass]
})
export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, OnDestroy, FormItemControl {
/** @hidden */
@@ -61,6 +62,12 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
@ViewChild('labelElement')
labelElement: ElementRef;
+ /** Whether input label should be wrapped */
+ @Input() wrapLabel: boolean;
+
+ /** Vertical position of the label compared to the checkbox box */
+ @Input() valignLabel: 'top' | 'middle' = 'middle';
+
/** Sets the `aria-label` attribute to the element. */
@Input()
ariaLabel: Nullable;
@@ -123,6 +130,10 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
@Input()
required = false;
+ /** Whether the checkbox should be rendered in display-only mode. */
+ @Input()
+ displayOnly = false;
+
/** @hidden */
private _subscriptions = new Subscription();
@@ -131,6 +142,7 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
set values(checkboxValues: FdCheckboxValues) {
this._values = { ...FD_CHECKBOX_VALUES_DEFAULT, ...(checkboxValues ?? {}) };
}
+
get values(): FdCheckboxValues {
return this._values;
}
@@ -179,8 +191,7 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
@Attribute('tabIndexValue') public tabIndexValue: number = 0,
private _changeDetectorRef: ChangeDetectorRef,
private renderer: Renderer2,
- readonly _contentDensityObserver: ContentDensityObserver,
- @Optional() @Inject(LIST_ITEM_COMPONENT) private _listItemComponent: ListItemInterface
+ readonly _contentDensityObserver: ContentDensityObserver
) {
this.tabIndexValue = tabIndexValue;
}
@@ -274,11 +285,24 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
}
/** @hidden handles click on the label associated with native checkbox input */
- _onLabelClick(event: Event): void {
+ _onLabelClick(event: MouseEvent): void {
// We have to stop propagation for click events on the input label.
// By default, when a user clicks on a label element, a generated click event will be
// dispatched on the associated input element. This will lead to duplicated "click" event dispatched from the component
event.stopPropagation();
+
+ // If we have display-only mode, stop any possible actions by label click event.
+ this._handleDisplayOnlyMode(event);
+ }
+
+ /**
+ * @hidden
+ * Event handler for cases when checkbox was toggled with the help of keyboard.
+ * @param event
+ */
+ _onLabelKeydown(event: Event): void {
+ // If we have display-only mode, stop any possible actions by label click event.
+ this._handleDisplayOnlyMode(event);
}
/** @hidden handles click on the native checkbox input */
@@ -287,10 +311,22 @@ export class CheckboxComponent implements ControlValueAccessor, AfterViewInit, O
// This is needed in order to set the value to the component before any external listeners will receive it.
// Otherwise checkbox might be out of sync.
event.stopPropagation();
+ if (this.displayOnly) {
+ return;
+ }
this.nextValue();
this.elementRef.nativeElement.dispatchEvent(new MouseEvent(event.type, event));
}
+ /** @hidden */
+ private _handleDisplayOnlyMode(event: Event): void {
+ if (!this.displayOnly) {
+ return;
+ }
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
/** @hidden Based on current control value sets new control state. */
private _setState(): void {
if (equal(this.checkboxValue, this.values.trueValue)) {
diff --git a/libs/core/src/lib/dialog/dialog-body/dialog-body.component.html b/libs/core/src/lib/dialog/dialog-body/dialog-body.component.html
index 3daa40cc97f..ad6677503f8 100644
--- a/libs/core/src/lib/dialog/dialog-body/dialog-body.component.html
+++ b/libs/core/src/lib/dialog/dialog-body/dialog-body.component.html
@@ -1,4 +1,9 @@
-
-
+
+
+
diff --git a/libs/core/src/lib/dialog/dialog.module.ts b/libs/core/src/lib/dialog/dialog.module.ts
index b084473533c..fd4d6f84a3e 100644
--- a/libs/core/src/lib/dialog/dialog.module.ts
+++ b/libs/core/src/lib/dialog/dialog.module.ts
@@ -8,7 +8,13 @@ import { IconModule } from '@fundamental-ngx/core/icon';
import { TitleModule } from '@fundamental-ngx/core/title';
import { BarModule } from '@fundamental-ngx/core/bar';
import { BusyIndicatorModule } from '@fundamental-ngx/core/busy-indicator';
-import { DynamicComponentService, InitialFocusModule, ResizeModule, TemplateModule } from '@fundamental-ngx/cdk/utils';
+import {
+ DynamicComponentService,
+ DynamicPortalComponent,
+ InitialFocusModule,
+ ResizeModule,
+ TemplateModule
+} from '@fundamental-ngx/cdk/utils';
import { DialogComponent } from './dialog.component';
import { DialogHeaderComponent } from './dialog-header/dialog-header.component';
@@ -50,7 +56,8 @@ const declarations = [
A11yModule,
ScrollbarModule,
PortalModule,
- OverlayModule
+ OverlayModule,
+ DynamicPortalComponent
],
exports: [declarations, BarModule, TitleModule, TemplateModule, InitialFocusModule],
providers: [DialogService, DynamicComponentService]
diff --git a/libs/core/src/lib/dialog/utils/dialog-ref.class.ts b/libs/core/src/lib/dialog/utils/dialog-ref.class.ts
index c4a9f1a0a07..f290d384019 100644
--- a/libs/core/src/lib/dialog/utils/dialog-ref.class.ts
+++ b/libs/core/src/lib/dialog/utils/dialog-ref.class.ts
@@ -1,15 +1,20 @@
import { BehaviorSubject, Observable } from 'rxjs';
-import { Injectable } from '@angular/core';
+import { Injectable, TemplateRef, Type } from '@angular/core';
import { DialogRefBase } from '../base/dialog-ref-base.class';
+export interface DialogRefLoadingConfiguration {
+ isLoading: boolean;
+ loadingLabel?: string;
+ loadingContent?: string | TemplateRef
| Type;
+}
+
/**
* Reference to a dialog component
* It can be injected into the content component through the constructor.
* For a template, it is declared as part of the implicit context, see examples.
*/
-
@Injectable()
-export class DialogRef extends DialogRefBase {
+export class DialogRef extends DialogRefBase implements DialogRefLoadingConfiguration {
/** @hidden */
private readonly _onHide = new BehaviorSubject(false);
@@ -17,15 +22,19 @@ export class DialogRef extends DialogRefBase {
private readonly _onLoading = new BehaviorSubject(false);
/** Observable that is triggered whenever the dialog should be visually hidden or visible.*/
- public onHide: Observable = this._onHide.asObservable();
+ onHide: Observable = this._onHide.asObservable();
/** Observable that is triggered whenever the dialog should be displayed in loading state.*/
- public onLoading: Observable = this._onLoading.asObservable();
+ onLoading: Observable = this._onLoading.asObservable();
- /** @hidden */
- constructor() {
- super();
- }
+ /** Value used to determine if dialog window should be hidden or visible. */
+ isLoading: boolean;
+
+ /** Text, that is rendered in loading state */
+ loadingLabel?: string;
+
+ /** Content, that is rendered in loading state before busy indicator */
+ loadingContent?: DialogRefLoadingConfiguration['loadingContent'];
/**
* Visually hides the dialog.
@@ -37,9 +46,15 @@ export class DialogRef extends DialogRefBase {
/**
* Displays the dialog in loading state.
- * @param isLoading Value used to determine if dialog window should be displayed in loading state.
+ * @param loadingData Value used to determine if dialog window should be displayed in loading state.
*/
- loading(isLoading: boolean): void {
- this._onLoading.next(isLoading);
+ loading(loadingData: boolean | DialogRefLoadingConfiguration): void {
+ if (typeof loadingData === 'boolean') {
+ return this.loading({ isLoading: loadingData });
+ }
+ this.loadingLabel = loadingData.loadingLabel;
+ this.loadingContent = loadingData.loadingContent;
+ this.isLoading = loadingData.isLoading;
+ this._onLoading.next(loadingData.isLoading);
}
}
diff --git a/libs/core/src/lib/link/link.component.spec.ts b/libs/core/src/lib/link/link.component.spec.ts
index 7247c1a1c6c..96ef2fe1fac 100644
--- a/libs/core/src/lib/link/link.component.spec.ts
+++ b/libs/core/src/lib/link/link.component.spec.ts
@@ -4,7 +4,9 @@ import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'fd-test-tabs',
- template: ` Test Link `
+ template: ` Test Link `,
+ standalone: true,
+ imports: [LinkComponent]
})
class TestLinkComponent {
@ViewChild(LinkComponent, { static: true })
@@ -17,7 +19,7 @@ describe('LinkComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [LinkComponent, TestLinkComponent]
+ imports: [TestLinkComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/link/link.component.ts b/libs/core/src/lib/link/link.component.ts
index d158feac88e..93c4ea0f367 100644
--- a/libs/core/src/lib/link/link.component.ts
+++ b/libs/core/src/lib/link/link.component.ts
@@ -19,9 +19,10 @@ import {
import { RouterLink } from '@angular/router';
import { applyCssClass, CssClassBuilder } from '@fundamental-ngx/cdk/utils';
import { map, startWith, Subject, takeUntil, tap } from 'rxjs';
-import { DomPortal, Portal } from '@angular/cdk/portal';
+import { DomPortal, Portal, PortalModule } from '@angular/cdk/portal';
import { FD_ICON_COMPONENT, IconComponent } from '@fundamental-ngx/core/icon';
import { FD_LINK_COMPONENT } from './tokens';
+import { NgIf } from '@angular/common';
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
@@ -44,7 +45,9 @@ import { FD_LINK_COMPONENT } from './tokens';
[new Optional(), new Self(), RouterLink]
]
}
- ]
+ ],
+ imports: [NgIf, PortalModule],
+ standalone: true
})
export class LinkComponent implements OnChanges, OnInit, CssClassBuilder, AfterViewInit, OnDestroy {
/** @hidden */
diff --git a/libs/core/src/lib/link/link.module.ts b/libs/core/src/lib/link/link.module.ts
index 00a606e916f..372ccc8e1fc 100644
--- a/libs/core/src/lib/link/link.module.ts
+++ b/libs/core/src/lib/link/link.module.ts
@@ -1,12 +1,9 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
import { LinkComponent } from './link.component';
-import { PortalModule } from '@angular/cdk/portal';
@NgModule({
- declarations: [LinkComponent],
- imports: [CommonModule, PortalModule],
+ imports: [LinkComponent],
exports: [LinkComponent]
})
export class LinkModule {}
diff --git a/libs/core/src/lib/list/directives/list-secondary.directive.ts b/libs/core/src/lib/list/directives/list-secondary.directive.ts
index 8d7d3b112bf..6d27a28553d 100644
--- a/libs/core/src/lib/list/directives/list-secondary.directive.ts
+++ b/libs/core/src/lib/list/directives/list-secondary.directive.ts
@@ -1,10 +1,39 @@
-import { Directive, HostBinding } from '@angular/core';
+import { Directive, inject, Input, isDevMode, OnChanges } from '@angular/core';
+import { NgClass } from '@angular/common';
+
+export const _secondaryListItemTypes = ['positive', 'critical', 'negative', 'informative'] as const;
+
+export type SecondaryListItemType = (typeof _secondaryListItemTypes)[number];
@Directive({
- selector: '[fd-list-secondary] ,[fdListSecondary]'
+ selector: '[fd-list-secondary], [fdListSecondary]',
+ standalone: true,
+ hostDirectives: [NgClass]
})
-export class ListSecondaryDirective {
+export class ListSecondaryDirective implements OnChanges {
+ /**
+ * Type of the secondary list item.
+ */
+ @Input()
+ type: SecondaryListItemType;
+
+ /** @hidden */
+ ngClass = inject(NgClass);
+
+ /** @hidden */
+ constructor() {
+ this.ngClass.ngClass = ['fd-list__secondary'];
+ }
+
/** @hidden */
- @HostBinding('class.fd-list__secondary')
- fdListSecondaryClass = true;
+ ngOnChanges(): void {
+ if (this.type && !_secondaryListItemTypes.includes(this.type) && isDevMode()) {
+ console.warn(
+ `Unknown type of the secondary list item: ${this.type}. Allowed types are: ${JSON.stringify(
+ _secondaryListItemTypes
+ )}`
+ );
+ }
+ this.ngClass.ngClass = ['fd-list__secondary', `fd-list__secondary--${this.type}`];
+ }
}
diff --git a/libs/core/src/lib/list/list.component.scss b/libs/core/src/lib/list/list.component.scss
index cc673bfea77..5e610fb6dc3 100644
--- a/libs/core/src/lib/list/list.component.scss
+++ b/libs/core/src/lib/list/list.component.scss
@@ -1,8 +1 @@
@import 'fundamental-styles/dist/list';
-
-// TODO: remove in next fundamental-styles release
-.fd-list__navigation-item--condensed {
- &.is-expanded {
- height: 2.75rem;
- }
-}
diff --git a/libs/core/src/lib/list/list.module.ts b/libs/core/src/lib/list/list.module.ts
index 42168c072d3..501ad181b19 100644
--- a/libs/core/src/lib/list/list.module.ts
+++ b/libs/core/src/lib/list/list.module.ts
@@ -27,7 +27,6 @@ import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
ListComponent,
ListItemComponent,
ListTitleDirective,
- ListSecondaryDirective,
ListIconDirective,
ListFooterDirective,
ListGroupHeaderDirective,
@@ -43,7 +42,7 @@ import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
ListNavigationItemArrowDirective,
ListNavigationItemTextDirective
],
- imports: [CommonModule, FormModule, IconModule, ContentDensityModule],
+ imports: [CommonModule, FormModule, IconModule, ContentDensityModule, ListSecondaryDirective],
exports: [
ListComponent,
ListItemComponent,
diff --git a/libs/core/src/lib/message-strip/alert/message-strip-configuration-type.ts b/libs/core/src/lib/message-strip/alert/message-strip-configuration-type.ts
index a8de24cc0f1..995f148f9db 100644
--- a/libs/core/src/lib/message-strip/alert/message-strip-configuration-type.ts
+++ b/libs/core/src/lib/message-strip/alert/message-strip-configuration-type.ts
@@ -1,5 +1,6 @@
import { Nullable } from '@fundamental-ngx/cdk/utils';
import { MessageStripType } from '../message-strip-type';
+import { MessageStripIndicationColor } from '../message-strip-indication-color';
export interface MessageStripConfiguration {
class: string;
@@ -8,6 +9,7 @@ export interface MessageStripConfiguration {
duration: number;
noIcon: boolean;
type: MessageStripType;
+ indicationColor: MessageStripIndicationColor;
id: string;
ariaLabelledBy: Nullable;
ariaLabel: Nullable;
diff --git a/libs/core/src/lib/message-strip/index.ts b/libs/core/src/lib/message-strip/index.ts
index caa2a7d949c..ed6d7315315 100644
--- a/libs/core/src/lib/message-strip/index.ts
+++ b/libs/core/src/lib/message-strip/index.ts
@@ -1,5 +1,7 @@
export * from './message-strip.module';
export * from './message-strip.component';
export * from './message-strip-type';
+export * from './message-strip-icon.directive';
+export * from './message-strip-indication-color';
export * from './auto-dismiss-message-strip.directive';
export * from './alert';
diff --git a/libs/core/src/lib/message-strip/message-strip-icon.directive.ts b/libs/core/src/lib/message-strip/message-strip-icon.directive.ts
new file mode 100644
index 00000000000..bb3c5b3bada
--- /dev/null
+++ b/libs/core/src/lib/message-strip/message-strip-icon.directive.ts
@@ -0,0 +1,10 @@
+import { Directive, TemplateRef } from '@angular/core';
+
+@Directive({
+ selector: '[fdMessageStripIcon]',
+ standalone: true
+})
+export class MessageStripIconDirective {
+ /** @hidden */
+ constructor(readonly templateRef: TemplateRef) {}
+}
diff --git a/libs/core/src/lib/message-strip/message-strip-indication-color.ts b/libs/core/src/lib/message-strip/message-strip-indication-color.ts
new file mode 100644
index 00000000000..e741ab9d44f
--- /dev/null
+++ b/libs/core/src/lib/message-strip/message-strip-indication-color.ts
@@ -0,0 +1,14 @@
+const messageStripIndicationColors = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] as const;
+
+export type MessageStripIndicationColor =
+ | `${(typeof messageStripIndicationColors)[number]}`
+ | `${(typeof messageStripIndicationColors)[number]}b`;
+
+export const _messageStripIndicationColors = messageStripIndicationColors.reduce(
+ (acc: MessageStripIndicationColor[], item) => {
+ acc.push(item);
+ acc.push(`${item}b`);
+ return acc;
+ },
+ []
+) as MessageStripIndicationColor[];
diff --git a/libs/core/src/lib/message-strip/message-strip.component.html b/libs/core/src/lib/message-strip/message-strip.component.html
index 5c8b27b8cd7..e51535638bc 100644
--- a/libs/core/src/lib/message-strip/message-strip.component.html
+++ b/libs/core/src/lib/message-strip/message-strip.component.html
@@ -1,3 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
diff --git a/libs/core/src/lib/message-strip/message-strip.component.ts b/libs/core/src/lib/message-strip/message-strip.component.ts
index c47cf172e8f..f10454b6b7d 100644
--- a/libs/core/src/lib/message-strip/message-strip.component.ts
+++ b/libs/core/src/lib/message-strip/message-strip.component.ts
@@ -1,6 +1,7 @@
import {
ChangeDetectionStrategy,
Component,
+ ContentChild,
ElementRef,
EventEmitter,
Input,
@@ -13,8 +14,11 @@ import { applyCssClass, CssClassBuilder, Nullable } from '@fundamental-ngx/cdk/u
import { I18nModule } from '@fundamental-ngx/i18n';
import { ContentDensityDirective } from '@fundamental-ngx/core/content-density';
import { ButtonModule } from '@fundamental-ngx/core/button';
-import { NgIf } from '@angular/common';
+import { NgIf, NgTemplateOutlet } from '@angular/common';
import { MessageStripType } from './message-strip-type';
+import { MessageStripIndicationColor } from './message-strip-indication-color';
+import { MessageStripIconDirective } from './message-strip-icon.directive';
+import { IconModule } from '@fundamental-ngx/core/icon';
let messageStripUniqueId = 0;
@@ -37,7 +41,7 @@ let messageStripUniqueId = 0;
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
- imports: [NgIf, ButtonModule, ContentDensityDirective, I18nModule]
+ imports: [NgIf, ButtonModule, ContentDensityDirective, I18nModule, NgTemplateOutlet, IconModule]
})
export class MessageStripComponent implements OnInit, OnChanges, CssClassBuilder {
/** User's custom classes */
@@ -75,10 +79,17 @@ export class MessageStripComponent implements OnInit, OnChanges, CssClassBuilder
/** Margin bottom of the message-strip. */
@Input() marginBottom: string;
+ /** indication color of the message-strip. */
+ @Input() indicationColor: MessageStripIndicationColor;
+
/** Event fired when the message-strip is dismissed. */
@Output() // eslint-disable-next-line @angular-eslint/no-output-on-prefix
onDismiss: EventEmitter = new EventEmitter();
+ /** Custom icon component */
+ @ContentChild(MessageStripIconDirective)
+ icon: MessageStripIconDirective;
+
/** @hidden */
constructor(public readonly elementRef: ElementRef) {}
@@ -92,6 +103,30 @@ export class MessageStripComponent implements OnInit, OnChanges, CssClassBuilder
this.buildComponentCssClass();
}
+ /** Whether icon container should be shown */
+ get shouldShowIcon(): boolean {
+ if (this.noIcon) {
+ return false;
+ }
+ return !!this.icon || !!this.type;
+ }
+
+ /** @hidden */
+ get typeSpecificIconName(): string {
+ switch (this.type) {
+ case 'warning':
+ return 'alert';
+ case 'success':
+ return 'sys-enter-2';
+ case 'error':
+ return 'error';
+ case 'information':
+ return 'information';
+ default:
+ return '';
+ }
+ }
+
/**
* Dismisses the message-strip.
*/
@@ -113,6 +148,7 @@ export class MessageStripComponent implements OnInit, OnChanges, CssClassBuilder
this.type ? `fd-message-strip--${this.type}` : '',
this.dismissible ? 'fd-message-strip--dismissible' : '',
this.noIcon ? 'fd-message-strip--no-icon' : '',
+ this.indicationColor ? `fd-message-strip--indication-color-${this.indicationColor}` : '',
this.class
];
}
diff --git a/libs/core/src/lib/message-strip/message-strip.module.ts b/libs/core/src/lib/message-strip/message-strip.module.ts
index a97403d60ec..630ca761606 100644
--- a/libs/core/src/lib/message-strip/message-strip.module.ts
+++ b/libs/core/src/lib/message-strip/message-strip.module.ts
@@ -2,9 +2,10 @@ import { NgModule } from '@angular/core';
import { MessageStripComponent } from './message-strip.component';
import { AutoDismissMessageStripDirective } from './auto-dismiss-message-strip.directive';
+import { MessageStripIconDirective } from './message-strip-icon.directive';
@NgModule({
- imports: [MessageStripComponent, AutoDismissMessageStripDirective],
- exports: [MessageStripComponent, AutoDismissMessageStripDirective]
+ imports: [MessageStripComponent, AutoDismissMessageStripDirective, MessageStripIconDirective],
+ exports: [MessageStripComponent, AutoDismissMessageStripDirective, MessageStripIconDirective]
})
export class MessageStripModule {}
diff --git a/libs/core/src/lib/object-identifier/object-identifier.component.spec.ts b/libs/core/src/lib/object-identifier/object-identifier.component.spec.ts
index 8acd1c62d1c..7282dc1751a 100644
--- a/libs/core/src/lib/object-identifier/object-identifier.component.spec.ts
+++ b/libs/core/src/lib/object-identifier/object-identifier.component.spec.ts
@@ -35,7 +35,8 @@ describe('ObjectIdentifierComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [ObjectIdentifierComponent, TestObjectIdentifierComponent, LinkComponent]
+ declarations: [ObjectIdentifierComponent, TestObjectIdentifierComponent],
+ imports: [LinkComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-footer.directive.ts b/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-footer.directive.ts
index fe4cb046565..af15f03d356 100644
--- a/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-footer.directive.ts
+++ b/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-footer.directive.ts
@@ -1,7 +1,8 @@
import { Directive, HostBinding } from '@angular/core';
@Directive({
- selector: '[fdPopoverBodyFooter], [fd-popover-body-footer]'
+ selector: '[fdPopoverBodyFooter], [fd-popover-body-footer]',
+ standalone: true
})
export class PopoverBodyFooterDirective {
/** @hidden */
diff --git a/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-header.directive.ts b/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-header.directive.ts
index 609c0228d83..d0b982d59c2 100644
--- a/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-header.directive.ts
+++ b/libs/core/src/lib/popover/popover-body/popover-body-directives/popover-body-header.directive.ts
@@ -1,7 +1,8 @@
import { Directive, HostBinding } from '@angular/core';
@Directive({
- selector: '[fdPopoverBodyHeader], [fd-popover-body-header]'
+ selector: '[fdPopoverBodyHeader], [fd-popover-body-header]',
+ standalone: true
})
export class PopoverBodyHeaderDirective {
/** @hidden */
diff --git a/libs/core/src/lib/popover/popover-body/popover-body.component.ts b/libs/core/src/lib/popover/popover-body/popover-body.component.ts
index 8322d133bf1..26fe4d89f5f 100644
--- a/libs/core/src/lib/popover/popover-body/popover-body.component.ts
+++ b/libs/core/src/lib/popover/popover-body/popover-body.component.ts
@@ -10,9 +10,9 @@ import {
ViewEncapsulation
} from '@angular/core';
-import { ConnectionPositionPair } from '@angular/cdk/overlay';
+import { ConnectionPositionPair, CdkScrollable } from '@angular/cdk/overlay';
import { ESCAPE } from '@angular/cdk/keycodes';
-import { CdkTrapFocus } from '@angular/cdk/a11y';
+import { CdkTrapFocus, A11yModule } from '@angular/cdk/a11y';
import { Subject } from 'rxjs';
@@ -20,6 +20,7 @@ import { Nullable } from '@fundamental-ngx/cdk/utils';
import { KeyUtil } from '@fundamental-ngx/cdk/utils';
import { ContentDensityObserver, contentDensityObserverProviders } from '@fundamental-ngx/core/content-density';
import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';
+import { NgIf, NgTemplateOutlet } from '@angular/common';
/**
* A component used to enforce a certain layout for the popover.
@@ -36,7 +37,9 @@ import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./popover-body.component.scss'],
- providers: [contentDensityObserverProviders({ alwaysAddModifiers: true })]
+ providers: [contentDensityObserverProviders({ alwaysAddModifiers: true })],
+ standalone: true,
+ imports: [A11yModule, NgIf, CdkScrollable, ScrollbarDirective, NgTemplateOutlet]
})
export class PopoverBodyComponent implements AfterViewInit {
/** Whether to wrap content with fd-scrollbar directive. */
@@ -152,13 +155,10 @@ export class PopoverBodyComponent implements AfterViewInit {
if (rtl === 'rtl') {
overlayX = position.overlayX === 'end' ? 'start' : 'end';
}
- // TODO: Remove after new fundamental-styles version release.
- const originY = position.originY === 'bottom' ? 'end' : position.originY;
- // End TODO
this._arrowClasses =
`fd-popover__body--${overlayX === 'start' ? 'after' : 'before'}` +
` fd-popover__body--arrow-${overlayX === 'start' ? 'left' : 'right'}` +
- ` fd-popover__body--arrow-y-${originY} `;
+ ` fd-popover__body--arrow-y-${position.originY} `;
} else {
this._arrowClasses = 'fd-popover__body--no-arrow';
}
diff --git a/libs/core/src/lib/popover/popover-container/popover-container.directive.ts b/libs/core/src/lib/popover/popover-container/popover-container.directive.ts
index 89cc53da4b6..a445cf7bf94 100644
--- a/libs/core/src/lib/popover/popover-container/popover-container.directive.ts
+++ b/libs/core/src/lib/popover/popover-container/popover-container.directive.ts
@@ -4,7 +4,8 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Directive({
- selector: '[fdPopoverContainer]'
+ selector: '[fdPopoverContainer]',
+ standalone: true
})
export class PopoverContainerDirective implements OnInit, OnDestroy {
/** Subject which emits when popover position refresh is required. */
diff --git a/libs/core/src/lib/popover/popover-control/popover-control.component.spec.ts b/libs/core/src/lib/popover/popover-control/popover-control.component.spec.ts
index 8776c46ab93..004f6e6ae85 100644
--- a/libs/core/src/lib/popover/popover-control/popover-control.component.spec.ts
+++ b/libs/core/src/lib/popover/popover-control/popover-control.component.spec.ts
@@ -8,7 +8,7 @@ describe('PopoverControlComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [PopoverControlComponent]
+ imports: [PopoverControlComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/popover/popover-control/popover-control.component.ts b/libs/core/src/lib/popover/popover-control/popover-control.component.ts
index 5c5881943ab..2a2122ea2fa 100644
--- a/libs/core/src/lib/popover/popover-control/popover-control.component.ts
+++ b/libs/core/src/lib/popover/popover-control/popover-control.component.ts
@@ -13,7 +13,8 @@ import { AfterContentChecked, ChangeDetectionStrategy, Component, ElementRef, Vi
selector: 'fd-popover-control',
templateUrl: './popover-control.component.html',
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true
})
export class PopoverControlComponent implements AfterContentChecked {
/** @hidden */
diff --git a/libs/core/src/lib/popover/popover-mobile/popover-mobile.component.ts b/libs/core/src/lib/popover/popover-mobile/popover-mobile.component.ts
index 6f2d785928d..295db79355d 100644
--- a/libs/core/src/lib/popover/popover-mobile/popover-mobile.component.ts
+++ b/libs/core/src/lib/popover/popover-mobile/popover-mobile.component.ts
@@ -16,14 +16,18 @@ import { Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import {
- MobileModeBase,
MOBILE_MODE_CONFIG,
- MobileModeControl,
- MobileModeConfigToken
+ MobileModeBase,
+ MobileModeConfigToken,
+ MobileModeControl
} from '@fundamental-ngx/core/mobile-mode';
-import { DialogService } from '@fundamental-ngx/core/dialog';
-import { PopoverInterface, POPOVER_COMPONENT } from '../popover.interface';
+import { DialogModule, DialogService } from '@fundamental-ngx/core/dialog';
+import { POPOVER_COMPONENT, PopoverInterface } from '../popover.interface';
import { PopoverChildContent } from '../popover-child-content.interface';
+import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';
+import { CdkScrollable } from '@angular/cdk/overlay';
+import { NgIf, NgTemplateOutlet } from '@angular/common';
+import { TitleComponent } from '@fundamental-ngx/core/title';
let mobilePopoverUniqueId = 0;
@@ -31,9 +35,15 @@ let mobilePopoverUniqueId = 0;
selector: 'fd-popover-mobile',
templateUrl: './popover-mobile.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
- encapsulation: ViewEncapsulation.None
+ encapsulation: ViewEncapsulation.None,
+ standalone: true,
+ imports: [DialogModule, TitleComponent, NgIf, CdkScrollable, ScrollbarDirective, NgTemplateOutlet]
})
export class PopoverMobileComponent extends MobileModeBase implements OnInit, OnDestroy {
+ /** @hidden */
+ @ViewChild('dialogTemplate')
+ _dialogTemplate: TemplateRef;
+
/** @hidden
* from mobile class can not prefix _,
* to avoid build issues
@@ -42,16 +52,12 @@ export class PopoverMobileComponent extends MobileModeBase imp
/** Current popover title */
title: string;
-
/** Dialog body content */
viewBody: TemplateRef | null;
+
/** Dialog footer content */
viewFooter: TemplateRef | null;
- /** @hidden */
- @ViewChild('dialogTemplate')
- _dialogTemplate: TemplateRef;
-
/** @hidden */
readonly id = 'fd-popover-mobile-' + mobilePopoverUniqueId++;
diff --git a/libs/core/src/lib/popover/popover-mobile/popover-mobile.module.ts b/libs/core/src/lib/popover/popover-mobile/popover-mobile.module.ts
index 6ddc6873f60..7b4efe8dd39 100644
--- a/libs/core/src/lib/popover/popover-mobile/popover-mobile.module.ts
+++ b/libs/core/src/lib/popover/popover-mobile/popover-mobile.module.ts
@@ -6,8 +6,7 @@ import { DynamicComponentService } from '@fundamental-ngx/cdk/utils';
import { PopoverMobileComponent } from './popover-mobile.component';
@NgModule({
- declarations: [PopoverMobileComponent],
- imports: [CommonModule, DialogModule, ButtonModule],
+ imports: [CommonModule, DialogModule, ButtonModule, PopoverMobileComponent],
exports: [PopoverMobileComponent],
providers: [DynamicComponentService]
})
diff --git a/libs/core/src/lib/popover/popover-trigger.directive.ts b/libs/core/src/lib/popover/popover-trigger.directive.ts
index c658d14f125..775b5f51c09 100644
--- a/libs/core/src/lib/popover/popover-trigger.directive.ts
+++ b/libs/core/src/lib/popover/popover-trigger.directive.ts
@@ -5,7 +5,8 @@ import { Nullable } from '@fundamental-ngx/cdk/utils';
import { PopoverComponent } from './popover.component';
@Directive({
- selector: '[fdPopoverTrigger], [fd-popover-trigger]'
+ selector: '[fdPopoverTrigger], [fd-popover-trigger]',
+ standalone: true
})
export class PopoverTriggerDirective implements OnDestroy {
/** Set reference to Popover Component */
diff --git a/libs/core/src/lib/popover/popover.component.spec.ts b/libs/core/src/lib/popover/popover.component.spec.ts
index caf09618c9c..6eb7535d1d0 100644
--- a/libs/core/src/lib/popover/popover.component.spec.ts
+++ b/libs/core/src/lib/popover/popover.component.spec.ts
@@ -1,11 +1,8 @@
-import { A11yModule } from '@angular/cdk/a11y';
import { DOWN_ARROW } from '@angular/cdk/keycodes';
-import { OverlayModule } from '@angular/cdk/overlay';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { PopoverService } from './popover-service/popover.service';
import { PopoverComponent } from './popover.component';
-import { PopoverModule } from './popover.module';
import { SimpleChanges } from '@angular/core';
describe('PopoverComponent', () => {
@@ -15,7 +12,7 @@ describe('PopoverComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [PopoverModule, OverlayModule, A11yModule],
+ imports: [PopoverComponent],
providers: [{ provide: PopoverService, useClass: PopoverServiceStub }]
})
.overrideComponent(PopoverComponent, {
diff --git a/libs/core/src/lib/popover/popover.component.ts b/libs/core/src/lib/popover/popover.component.ts
index 8a345f9d29e..62b35b7be91 100644
--- a/libs/core/src/lib/popover/popover.component.ts
+++ b/libs/core/src/lib/popover/popover.component.ts
@@ -37,6 +37,7 @@ import { PopoverMobileComponent } from './popover-mobile/popover-mobile.componen
import { PopoverMobileModule } from './popover-mobile/popover-mobile.module';
import { PopoverChildContent } from './popover-child-content.interface';
import { FD_POPOVER_COMPONENT } from './tokens';
+import { NgIf } from '@angular/common';
export const SELECT_CLASS_NAMES = {
selectControl: 'fd-select__control'
@@ -66,7 +67,9 @@ let cdkPopoverUniqueId = 0;
class: 'fd-popover-custom',
'[class.fd-popover-custom--mobile]': 'mobile',
'[attr.id]': 'id'
- }
+ },
+ standalone: true,
+ imports: [NgIf, CdkOverlayOrigin]
})
export class PopoverComponent
extends BasePopoverClass
diff --git a/libs/core/src/lib/popover/popover.module.ts b/libs/core/src/lib/popover/popover.module.ts
index 86ba795ed10..bd3eae72469 100644
--- a/libs/core/src/lib/popover/popover.module.ts
+++ b/libs/core/src/lib/popover/popover.module.ts
@@ -1,20 +1,16 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
import { PopoverControlComponent } from './popover-control/popover-control.component';
import { PopoverBodyComponent } from './popover-body/popover-body.component';
import { PopoverBodyHeaderDirective } from './popover-body/popover-body-directives/popover-body-header.directive';
import { PopoverBodyFooterDirective } from './popover-body/popover-body-directives/popover-body-footer.directive';
-import { OverlayModule } from '@angular/cdk/overlay';
import { PopoverComponent } from './popover.component';
-import { A11yModule } from '@angular/cdk/a11y';
import { PopoverTriggerDirective } from './popover-trigger.directive';
import { PopoverContainerDirective } from './popover-container/popover-container.directive';
-import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar';
@NgModule({
- declarations: [
+ imports: [
PopoverControlComponent,
PopoverBodyComponent,
PopoverBodyHeaderDirective,
@@ -23,7 +19,6 @@ import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar';
PopoverTriggerDirective,
PopoverContainerDirective
],
- imports: [CommonModule, OverlayModule, A11yModule, ScrollbarModule],
exports: [
PopoverControlComponent,
PopoverBodyComponent,
diff --git a/libs/core/src/lib/radio/radio-button/radio-button.component.html b/libs/core/src/lib/radio/radio-button/radio-button.component.html
index 0600a7a128c..42248f02189 100755
--- a/libs/core/src/lib/radio/radio-button/radio-button.component.html
+++ b/libs/core/src/lib/radio/radio-button/radio-button.component.html
@@ -21,5 +21,7 @@
[attr.value]="value"
/>
-
+
+
+
diff --git a/libs/core/src/lib/shared/interfaces/search-component.interface.ts b/libs/core/src/lib/shared/interfaces/search-component.interface.ts
index 26ad6d87607..83757641400 100644
--- a/libs/core/src/lib/shared/interfaces/search-component.interface.ts
+++ b/libs/core/src/lib/shared/interfaces/search-component.interface.ts
@@ -19,5 +19,6 @@ export interface SearchComponent {
categoryButtonClass: string;
categoryDropdownButtonClass: string;
removeGroupButtonClass: boolean;
+ helperClass?: string;
};
}
diff --git a/libs/core/src/lib/shellbar/product-menu/product-menu.component.html b/libs/core/src/lib/shellbar/product-menu/product-menu.component.html
index 4454b07cbb9..69a040cda14 100644
--- a/libs/core/src/lib/shellbar/product-menu/product-menu.component.html
+++ b/libs/core/src/lib/shellbar/product-menu/product-menu.component.html
@@ -3,7 +3,7 @@
fd-button
fdType="transparent"
class="fd-shellbar__button fd-shellbar__button--menu"
- glyph="megamenu"
+ glyph="slim-arrow-down"
glyphPosition="after"
fdCozy
[disabled]="disabled"
diff --git a/libs/core/src/lib/shellbar/product-menu/product-menu.component.ts b/libs/core/src/lib/shellbar/product-menu/product-menu.component.ts
index d8465ebd42d..408be162f1b 100644
--- a/libs/core/src/lib/shellbar/product-menu/product-menu.component.ts
+++ b/libs/core/src/lib/shellbar/product-menu/product-menu.component.ts
@@ -3,6 +3,11 @@ import { MenuComponent } from '@fundamental-ngx/core/menu';
import { ShellbarMenuItem } from '../model/shellbar-menu-item';
import { Placement, PopoverFillMode } from '@fundamental-ngx/core/shared';
import { Nullable } from '@fundamental-ngx/cdk/utils';
+import { IconModule } from '@fundamental-ngx/core/icon';
+import { MenuModule } from '@fundamental-ngx/core/menu';
+import { ContentDensityDirective } from '@fundamental-ngx/core/content-density';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { NgIf, NgFor } from '@angular/common';
/**
* The component that represents a product menu.
@@ -17,7 +22,9 @@ import { Nullable } from '@fundamental-ngx/cdk/utils';
selector: 'fd-product-menu',
templateUrl: './product-menu.component.html',
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [NgIf, ButtonModule, ContentDensityDirective, MenuModule, NgFor, IconModule]
})
export class ProductMenuComponent {
/** Whether the popover should close when the escape key is pressed. */
diff --git a/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.spec.ts b/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.spec.ts
index 8844de3a03e..720c01e6340 100644
--- a/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.spec.ts
+++ b/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.spec.ts
@@ -1,7 +1,6 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ShellbarActionComponent } from './shellbar-action.component';
-import { ButtonModule } from '@fundamental-ngx/core/button';
describe('ShellbarActionComponent', () => {
let component: ShellbarActionComponent;
@@ -9,8 +8,7 @@ describe('ShellbarActionComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [ButtonModule],
- declarations: [ShellbarActionComponent]
+ imports: [ShellbarActionComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.ts b/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.ts
index bda779a49c3..478700db244 100644
--- a/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-action/shellbar-action.component.ts
@@ -1,6 +1,9 @@
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
import { FD_SHELLBAR_ACTION_COMPONENT } from '../tokens';
import { Nullable } from '@fundamental-ngx/cdk/utils';
+import { NgIf } from '@angular/common';
+import { ContentDensityDirective } from '@fundamental-ngx/core/content-density';
+import { ButtonModule } from '@fundamental-ngx/core/button';
/**
* The component that represents a shellbar action.
@@ -24,7 +27,9 @@ import { Nullable } from '@fundamental-ngx/cdk/utils';
provide: FD_SHELLBAR_ACTION_COMPONENT,
useExisting: ShellbarActionComponent
}
- ]
+ ],
+ standalone: true,
+ imports: [ButtonModule, ContentDensityDirective, NgIf]
})
export class ShellbarActionComponent {
/** The glyph (icon) name */
diff --git a/libs/core/src/lib/shellbar/shellbar-actions-mobile/shellbar-actions-mobile.component.ts b/libs/core/src/lib/shellbar/shellbar-actions-mobile/shellbar-actions-mobile.component.ts
index f970d2e0c6f..73b7df0bcfc 100644
--- a/libs/core/src/lib/shellbar/shellbar-actions-mobile/shellbar-actions-mobile.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-actions-mobile/shellbar-actions-mobile.component.ts
@@ -9,12 +9,18 @@ import {
ViewEncapsulation
} from '@angular/core';
import { ShellbarActionComponent } from '../shellbar-action/shellbar-action.component';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { NgIf, NgFor } from '@angular/common';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { ActionSheetModule } from '@fundamental-ngx/core/action-sheet';
@Component({
selector: 'fd-shellbar-actions-mobile',
templateUrl: './shellbar-actions-mobile.component.html',
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [ActionSheetModule, ButtonModule, NgIf, NgFor, FdTranslatePipe]
})
export class ShellbarActionsMobileComponent implements AfterContentChecked {
/** @hidden */
diff --git a/libs/core/src/lib/shellbar/shellbar-actions/shellbar-actions.component.ts b/libs/core/src/lib/shellbar/shellbar-actions/shellbar-actions.component.ts
index 8137f361e86..51908b57fe2 100644
--- a/libs/core/src/lib/shellbar/shellbar-actions/shellbar-actions.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-actions/shellbar-actions.component.ts
@@ -22,11 +22,13 @@ import { ShellbarActionComponent } from '../shellbar-action/shellbar-action.comp
import { ShellbarUserMenu } from '../model/shellbar-user-menu';
import { ShellbarUser } from '../model/shellbar-user';
import { ShellbarUserMenuComponent } from '../user-menu/shellbar-user-menu.component';
-import { CdkPortalOutlet, DomPortal } from '@angular/cdk/portal';
+import { CdkPortalOutlet, DomPortal, PortalModule } from '@angular/cdk/portal';
import { FD_SHELLBAR_ACTION_COMPONENT, FD_SHELLBAR_COMPONENT } from '../tokens';
import { SearchComponent } from '@fundamental-ngx/core/shared';
import { Nullable } from '@fundamental-ngx/cdk/utils';
import { ShellbarSizes } from '../model/shellbar-sizes';
+import { ShellbarActionsMobileComponent } from '../shellbar-actions-mobile/shellbar-actions-mobile.component';
+import { NgIf } from '@angular/common';
/**
* The component that represents shellbar actions.
@@ -56,7 +58,9 @@ import { ShellbarSizes } from '../model/shellbar-sizes';
host: {
'[class.fd-shellbar__group]': 'true',
'[class.fd-shellbar__group--actions]': 'true'
- }
+ },
+ standalone: true,
+ imports: [NgIf, PortalModule, ShellbarActionsMobileComponent, ShellbarActionComponent, ShellbarUserMenuComponent]
})
export class ShellbarActionsComponent implements OnDestroy {
/** The user data. */
diff --git a/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.spec.ts b/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.spec.ts
index f603428d05d..66282a71101 100644
--- a/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.spec.ts
+++ b/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.spec.ts
@@ -8,7 +8,7 @@ describe('ShellbarLogoComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [ShellbarLogoComponent]
+ imports: [ShellbarLogoComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.ts b/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.ts
index d4a450adce4..1b1094a25d8 100644
--- a/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-logo/shellbar-logo.component.ts
@@ -13,6 +13,7 @@ import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/
selector: 'fd-shellbar-logo',
templateUrl: './shellbar-logo.component.html',
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true
})
export class ShellbarLogoComponent {}
diff --git a/libs/core/src/lib/shellbar/shellbar-sidenav.directive.ts b/libs/core/src/lib/shellbar/shellbar-sidenav.directive.ts
index 73d0b450dd9..d081ce20bf5 100644
--- a/libs/core/src/lib/shellbar/shellbar-sidenav.directive.ts
+++ b/libs/core/src/lib/shellbar/shellbar-sidenav.directive.ts
@@ -4,6 +4,7 @@ import { Directive } from '@angular/core';
selector: '[fdShellbarSidenav], [fd-shellbar-side-nav]',
host: {
class: 'fd-shellbar__button'
- }
+ },
+ standalone: true
})
export class ShellbarSidenavDirective {}
diff --git a/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.spec.ts b/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.spec.ts
index f878ea632c5..a82b32ad65b 100644
--- a/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.spec.ts
+++ b/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.spec.ts
@@ -8,7 +8,7 @@ describe('ShellbarSubtitleComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [ShellbarSubtitleComponent]
+ imports: [ShellbarSubtitleComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.ts b/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.ts
index 585d5170d3e..812b0907612 100644
--- a/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-subtitle/shellbar-subtitle.component.ts
@@ -20,6 +20,7 @@ import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/
display: flex;
}
`
- ]
+ ],
+ standalone: true
})
export class ShellbarSubtitleComponent {}
diff --git a/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.spec.ts b/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.spec.ts
index dc8c52fe15c..27a7fefc289 100644
--- a/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.spec.ts
+++ b/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.spec.ts
@@ -8,7 +8,7 @@ describe('ShellbarTitleComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [ShellbarTitleComponent]
+ imports: [ShellbarTitleComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.ts b/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.ts
index fcff013b370..54c4c41ba72 100644
--- a/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar-title/shellbar-title.component.ts
@@ -13,6 +13,7 @@ import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/
selector: 'fd-shellbar-title',
templateUrl: './shellbar-title.component.html',
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true
})
export class ShellbarTitleComponent {}
diff --git a/libs/core/src/lib/shellbar/shellbar.component.scss b/libs/core/src/lib/shellbar/shellbar.component.scss
index 6bc9ecca85e..5f7ffdf457a 100644
--- a/libs/core/src/lib/shellbar/shellbar.component.scss
+++ b/libs/core/src/lib/shellbar/shellbar.component.scss
@@ -29,13 +29,3 @@ fd-shellbar-actions {
.fd-shellbar__action.fd-shellbar__action--desktop:empty {
display: none;
}
-
-// TODO: remove when updating fundamental-styles to 0.29.0
-.fd-shellbar__group--shrink {
- flex-grow: 0;
-}
-
-// TODO: remove when updating fundamental-styles to 0.29.0
-.fd-shellbar__group--basis-auto {
- flex-basis: auto;
-}
diff --git a/libs/core/src/lib/shellbar/shellbar.component.spec.ts b/libs/core/src/lib/shellbar/shellbar.component.spec.ts
index 7ee8e1f15bd..2bb2079a456 100644
--- a/libs/core/src/lib/shellbar/shellbar.component.spec.ts
+++ b/libs/core/src/lib/shellbar/shellbar.component.spec.ts
@@ -8,7 +8,7 @@ describe('ShellbarComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [ShellbarComponent]
+ imports: [ShellbarComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/shellbar/shellbar.component.ts b/libs/core/src/lib/shellbar/shellbar.component.ts
index e0d16c853e8..6d82beb3491 100644
--- a/libs/core/src/lib/shellbar/shellbar.component.ts
+++ b/libs/core/src/lib/shellbar/shellbar.component.ts
@@ -1,4 +1,4 @@
-import { CdkPortalOutlet, DomPortal } from '@angular/cdk/portal';
+import { CdkPortalOutlet, DomPortal, PortalModule } from '@angular/cdk/portal';
import {
AfterContentInit,
AfterViewInit,
@@ -28,6 +28,8 @@ import { FD_SHELLBAR_COMPONENT, FD_SHELLBAR_SEARCH_COMPONENT } from './tokens';
import { SideNavigationInterface } from '@fundamental-ngx/core/side-navigation';
import { Breakpoints, NormalizedBreakpoint, ShellbarGroupFlexOptions, ShellbarSizes } from './model/shellbar-sizes';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { NgIf } from '@angular/common';
/**
* The shellbar offers consistent, responsive navigation across all products and applications.
@@ -49,7 +51,9 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
provide: FD_SHELLBAR_COMPONENT,
useExisting: ShellbarComponent
}
- ]
+ ],
+ standalone: true,
+ imports: [NgIf, PortalModule, FdTranslatePipe]
})
export class ShellbarComponent implements AfterContentInit, AfterViewInit, OnDestroy {
/** Size of Shellbar component 's' | 'm' | 'l' | 'xl' */
@@ -146,7 +150,8 @@ export class ShellbarComponent implements AfterContentInit, AfterViewInit, OnDes
addonClass: 'fd-shellbar__search-field-addon',
categoryButtonClass: 'fd-shellbar__search-category',
categoryDropdownButtonClass: 'fd-shellbar__search-dropdown',
- removeGroupButtonClass: true
+ removeGroupButtonClass: true,
+ helperClass: 'fd-shellbar__search-field-helper'
};
this._searchSubmitSubscription?.unsubscribe();
diff --git a/libs/core/src/lib/shellbar/shellbar.module.ts b/libs/core/src/lib/shellbar/shellbar.module.ts
index c25e091b74f..082dfa846aa 100644
--- a/libs/core/src/lib/shellbar/shellbar.module.ts
+++ b/libs/core/src/lib/shellbar/shellbar.module.ts
@@ -1,11 +1,6 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { ActionSheetModule } from '@fundamental-ngx/core/action-sheet';
import { ShellbarComponent } from './shellbar.component';
import { ProductMenuComponent } from './product-menu/product-menu.component';
-import { PopoverModule } from '@fundamental-ngx/core/popover';
-import { MenuModule } from '@fundamental-ngx/core/menu';
-import { ButtonModule } from '@fundamental-ngx/core/button';
import { ShellbarSubtitleComponent } from './shellbar-subtitle/shellbar-subtitle.component';
import { ShellbarActionsComponent } from './shellbar-actions/shellbar-actions.component';
@@ -14,19 +9,12 @@ import { ShellbarLogoComponent } from './shellbar-logo/shellbar-logo.component';
import { ShellbarTitleComponent } from './shellbar-title/shellbar-title.component';
import { ShellbarUserMenuComponent } from './user-menu/shellbar-user-menu.component';
-import { IconModule } from '@fundamental-ngx/core/icon';
-import { DragAndDropModule } from '@fundamental-ngx/cdk/utils';
-import { DragDropModule } from '@angular/cdk/drag-drop';
-import { ProductSwitchModule } from '@fundamental-ngx/core/product-switch';
import { ShellbarSidenavDirective } from './shellbar-sidenav.directive';
import { ShellbarActionsMobileComponent } from './shellbar-actions-mobile/shellbar-actions-mobile.component';
-import { I18nModule } from '@fundamental-ngx/i18n';
-import { AvatarModule } from '@fundamental-ngx/core/avatar';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
-import { PortalModule } from '@angular/cdk/portal';
@NgModule({
- declarations: [
+ imports: [
ShellbarComponent,
ProductMenuComponent,
ShellbarSubtitleComponent,
@@ -38,22 +26,6 @@ import { PortalModule } from '@angular/cdk/portal';
ShellbarUserMenuComponent,
ShellbarSidenavDirective
],
- imports: [
- CommonModule,
- PopoverModule,
- MenuModule,
- ActionSheetModule,
- ButtonModule,
- DragAndDropModule,
- DragDropModule,
- ProductSwitchModule,
- IconModule,
- I18nModule,
- AvatarModule,
- ContentDensityModule,
- PortalModule,
- I18nModule
- ],
exports: [
ShellbarComponent,
ProductMenuComponent,
diff --git a/libs/core/src/lib/shellbar/user-menu/shellbar-user-menu.component.ts b/libs/core/src/lib/shellbar/user-menu/shellbar-user-menu.component.ts
index 87c01723e0e..ba29a2c7abd 100644
--- a/libs/core/src/lib/shellbar/user-menu/shellbar-user-menu.component.ts
+++ b/libs/core/src/lib/shellbar/user-menu/shellbar-user-menu.component.ts
@@ -4,6 +4,10 @@ import { ShellbarUserMenu } from '../model/shellbar-user-menu';
import { MenuComponent } from '@fundamental-ngx/core/menu';
import { Placement, PopoverFillMode } from '@fundamental-ngx/core/shared';
import { Nullable } from '@fundamental-ngx/cdk/utils';
+import { AvatarModule } from '@fundamental-ngx/core/avatar';
+import { MenuModule } from '@fundamental-ngx/core/menu';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { NgIf, NgFor } from '@angular/common';
/**
* This Component extends popover component and passes all the options and events from outside to popover component
@@ -12,7 +16,9 @@ import { Nullable } from '@fundamental-ngx/cdk/utils';
@Component({
selector: 'fd-shellbar-user-menu',
templateUrl: './shellbar-user-menu.component.html',
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [NgIf, ButtonModule, MenuModule, AvatarModule, NgFor]
})
export class ShellbarUserMenuComponent {
/** The user data. */
diff --git a/libs/core/src/lib/slider/slider-position.directive.ts b/libs/core/src/lib/slider/slider-position.directive.ts
index c18923f1d4d..4c02d737e96 100644
--- a/libs/core/src/lib/slider/slider-position.directive.ts
+++ b/libs/core/src/lib/slider/slider-position.directive.ts
@@ -1,17 +1,22 @@
-import { ChangeDetectorRef, Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, Optional } from '@angular/core';
+import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, Optional, Renderer2 } from '@angular/core';
import { Subscription } from 'rxjs';
import { startWith } from 'rxjs/operators';
import { RtlService } from '@fundamental-ngx/cdk/utils';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
- selector: '[fd-slider-position]'
+ selector: '[fd-slider-position]',
+ standalone: true
})
export class SliderPositionDirective implements OnInit, OnChanges, OnDestroy {
/** Position of the slider */
@Input()
position: number;
+ /** Whether the slider is rendered vertically. */
+ @Input()
+ vertical = false;
+
/** @hidden */
private _isRtl = false;
@@ -20,8 +25,8 @@ export class SliderPositionDirective implements OnInit, OnChanges, OnDestroy {
/** @hidden */
constructor(
- private readonly _cd: ChangeDetectorRef,
private readonly _elementRef: ElementRef,
+ private readonly _renderer: Renderer2,
@Optional() private readonly _rtlService: RtlService
) {}
@@ -44,10 +49,13 @@ export class SliderPositionDirective implements OnInit, OnChanges, OnDestroy {
/** @hidden */
private _setPosition(): void {
- const { style } = this._elementRef.nativeElement;
+ if (this.vertical) {
+ this._renderer.setStyle(this._elementRef.nativeElement, 'bottom', `${this.position}%`);
+ return;
+ }
- style.left = !this._isRtl ? `${this.position}%` : 'unset';
- style.right = this._isRtl ? `${this.position}%` : 'unset';
+ this._renderer.setStyle(this._elementRef.nativeElement, 'left', !this._isRtl ? `${this.position}%` : 'unset');
+ this._renderer.setStyle(this._elementRef.nativeElement, 'right', this._isRtl ? `${this.position}%` : 'unset');
}
/** @hidden Rtl change subscription */
diff --git a/libs/core/src/lib/slider/slider.component.html b/libs/core/src/lib/slider/slider.component.html
index 5a9a3b5b34e..e4deb8853eb 100644
--- a/libs/core/src/lib/slider/slider.component.html
+++ b/libs/core/src/lib/slider/slider.component.html
@@ -12,6 +12,7 @@
{{ tick.label }}
@@ -40,17 +42,32 @@
-
+
+ >
+
+
@@ -80,6 +97,7 @@
: getValuenow(_position, _sliderValueTargets.SINGLE_SLIDER)
"
fd-slider-position
+ [vertical]="vertical"
[position]="_progress"
(mousedown)="onHandleClick($event); $event.stopPropagation()"
(focus)="_handleFocused$.next(true)"
@@ -133,9 +151,10 @@
: getValuenow(_handle1Value, _sliderValueTargets.RANGE_SLIDER1)
"
fd-slider-position
+ [vertical]="vertical"
[position]="_handle1Position"
(mousedown)="onHandleClick($event); $event.stopPropagation()"
- (keydown)="onKeyDown($event)"
+ (keydown)="onKeyDown($event, _handles.First)"
(focus)="_rangeHandle1Focused$.next(true)"
(blur)="_rangeHandle1Focused$.next(false)"
>
@@ -166,9 +185,10 @@
: getValuenow(_handle2Value, _sliderValueTargets.RANGE_SLIDER2)
"
fd-slider-position
+ [vertical]="vertical"
[position]="_handle2Position"
(mousedown)="onHandleClick($event); $event.stopPropagation()"
- (keydown)="onKeyDown($event)"
+ (keydown)="onKeyDown($event, _handles.Second)"
(focus)="_rangeHandle2Focused$.next(true)"
(blur)="_rangeHandle2Focused$.next(false)"
>
diff --git a/libs/core/src/lib/slider/slider.component.spec.ts b/libs/core/src/lib/slider/slider.component.spec.ts
index 261b81ad2e8..0d00ed050c9 100644
--- a/libs/core/src/lib/slider/slider.component.spec.ts
+++ b/libs/core/src/lib/slider/slider.component.spec.ts
@@ -4,7 +4,11 @@ import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { whenStable } from '@fundamental-ngx/core/tests';
-import { ContentDensityMode, mockedLocalContentDensityDirective } from '@fundamental-ngx/core/content-density';
+import {
+ ContentDensityMode,
+ ContentDensityModule,
+ mockedLocalContentDensityDirective
+} from '@fundamental-ngx/core/content-density';
import { SliderComponent } from './slider.component';
import { SliderModule } from './slider.module';
@@ -79,7 +83,7 @@ class TestSliderComponent {
}
/** TODO: #6317 */
-xdescribe('SliderComponent', () => {
+describe('SliderComponent', () => {
let component: TestSliderComponent;
let fixture: ComponentFixture;
let sliders: SliderComponent[];
@@ -88,7 +92,7 @@ xdescribe('SliderComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [TestSliderComponent],
- imports: [SliderModule, FormsModule],
+ imports: [SliderModule, FormsModule, ContentDensityModule],
providers: [contentDensityDirectiveProvider]
}).compileComponents();
}));
@@ -100,7 +104,7 @@ xdescribe('SliderComponent', () => {
await whenStable(fixture);
sliders = component.sliders.toArray();
- bodyClientWidth = fixture.nativeElement.ownerDocument.body.clientWidth;
+ bodyClientWidth = 100;
});
it('should create', () => {
@@ -112,7 +116,53 @@ xdescribe('SliderComponent', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('.fd-slider--lg').length).toBe(sliders.length);
setContentDensity(ContentDensityMode.COMPACT);
- expect(fixture.nativeElement.querySelectorAll('.fd-slider--lg').length).toBe(0);
+ expect(fixture.nativeElement.querySelectorAll('.fd-slider--lg').length).toBe(1);
+ });
+
+ it('should consume vertical state', () => {
+ const slider = component.sliders.get(0)!;
+ slider.vertical = true;
+ slider.buildComponentCssClass();
+ expect(slider?.elementRef.nativeElement.classList).toContain('fd-slider--vertical');
+ });
+
+ it('should move range when dragging range group', () => {
+ const slider = sliders[3];
+
+ const event = new MouseEvent('mousedown');
+
+ jest.spyOn(slider.rangeHandle1.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 20,
+ width: 40,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+
+ jest.spyOn(slider.trackEl.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 2,
+ width: bodyClientWidth,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+
+ slider.onHandleClick(event, true);
+
+ const mousemove = new MouseEvent('mousemove', { clientX: getPixelsByPercentage(bodyClientWidth, 20) });
+ fixture.nativeElement.ownerDocument.dispatchEvent(mousemove);
+
+ const upEvent = new MouseEvent('mouseup');
+
+ fixture.nativeElement.ownerDocument.dispatchEvent(upEvent);
+
+ expect(component.value4).toEqual([40, 90]);
});
it('handle should be on the center of slider', () => {
@@ -125,6 +175,17 @@ xdescribe('SliderComponent', () => {
const slider = sliders[0];
const event = new MouseEvent('mousedown');
+ jest.spyOn(slider.trackEl.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 2,
+ width: bodyClientWidth,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+
slider.onHandleClick(event);
const mousemove = new MouseEvent('mousemove', { clientX: getPixelsByPercentage(bodyClientWidth, 10) });
@@ -158,6 +219,18 @@ xdescribe('SliderComponent', () => {
});
it('should display 11 ticks marks and 11 Labels', () => {
+ jest.spyOn(sliders[0].trackEl.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 2,
+ width: bodyClientWidth,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+ (sliders[0] as any)._onResize();
+ fixture.detectChanges();
const ticksMarks = fixture.debugElement.queryAll(By.css('.example-1 .fd-slider__tick'));
const labels = fixture.debugElement.queryAll(By.css('.example-1 .fd-slider__label'));
@@ -166,6 +239,18 @@ xdescribe('SliderComponent', () => {
});
it('should display 11 ticks marks and 6 Labels', () => {
+ jest.spyOn(sliders[1].trackEl.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 2,
+ width: bodyClientWidth,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+ (sliders[1] as any)._onResize();
+ fixture.detectChanges();
const ticksMarks = fixture.debugElement.queryAll(By.css('.example-2 .fd-slider__tick'));
const labels = fixture.debugElement.queryAll(By.css('.example-2 .fd-slider__label'));
@@ -177,7 +262,7 @@ xdescribe('SliderComponent', () => {
const labels = fixture.debugElement.queryAll(By.css('.example-3 .fd-slider__label'));
expect(labels.length).toEqual(component.customValues.length);
- expect(labels[0].nativeElement.innerHTML).toEqual(component.customValues[0].label);
+ expect(labels[0].nativeElement.innerHTML.trim()).toEqual(component.customValues[0].label);
});
it('range slider should display 2 handles', async () => {
@@ -195,6 +280,17 @@ xdescribe('SliderComponent', () => {
const event = { target: slider.rangeHandle2.nativeElement } as any;
const valueOfFirstHandleBeforeMoving = slider.value[0];
+ jest.spyOn(slider.trackEl.nativeElement as any, 'getBoundingClientRect').mockImplementation(() => ({
+ height: 2,
+ width: bodyClientWidth,
+ x: 0,
+ y: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0
+ }));
+
slider.onHandleClick(event);
const mousemove = new MouseEvent('mousemove', { clientX: getPixelsByPercentage(bodyClientWidth, 11) });
diff --git a/libs/core/src/lib/slider/slider.component.ts b/libs/core/src/lib/slider/slider.component.ts
index 68499e2a6c5..b7432c4d046 100644
--- a/libs/core/src/lib/slider/slider.component.ts
+++ b/libs/core/src/lib/slider/slider.component.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/member-ordering */
import {
AfterViewInit,
ChangeDetectionStrategy,
@@ -17,7 +18,7 @@ import {
ViewChildren,
ViewEncapsulation
} from '@angular/core';
-import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
import { DOWN_ARROW, ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE, UP_ARROW } from '@angular/cdk/keycodes';
import { Platform } from '@angular/cdk/platform';
import { coerceNumberProperty } from '@angular/cdk/coercion';
@@ -34,8 +35,9 @@ import {
take,
takeUntil
} from 'rxjs/operators';
-import { PopoverComponent } from '@fundamental-ngx/core/popover';
-import { Nullable } from '@fundamental-ngx/cdk/utils';
+
+import { PopoverComponent, PopoverModule } from '@fundamental-ngx/core/popover';
+import { Nullable, OnlyDigitsDirective } from '@fundamental-ngx/cdk/utils';
import {
SliderControlValue,
SliderCustomValue,
@@ -51,6 +53,9 @@ import {
ContentDensityObserver,
contentDensityObserverProviders
} from '@fundamental-ngx/core/content-density';
+import { SliderPositionDirective } from './slider-position.directive';
+import { NgTemplateOutlet, NgIf, NgFor, AsyncPipe } from '@angular/common';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
export const SLIDER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
@@ -78,7 +83,19 @@ let sliderId = 0;
'(mouseenter)': 'this._componentHovered$.next(true)',
'(mouseleave)': 'this._componentHovered$.next(false)',
'(focusout)': 'onTouched()'
- }
+ },
+ standalone: true,
+ imports: [
+ NgTemplateOutlet,
+ NgIf,
+ NgFor,
+ SliderPositionDirective,
+ PopoverModule,
+ FormsModule,
+ OnlyDigitsDirective,
+ AsyncPipe,
+ FdTranslatePipe
+ ]
})
export class SliderComponent
implements OnInit, OnChanges, AfterViewInit, OnDestroy, ControlValueAccessor, CssClassBuilder, FormItemControl
@@ -189,6 +206,12 @@ export class SliderComponent
@Input()
disabled = false;
+ /**
+ * Whether slider should have vertical alignment.
+ */
+ @Input()
+ vertical = false;
+
/** @hidden */
_position: number | number[] = 0;
@@ -207,9 +230,7 @@ export class SliderComponent
}
/** @hidden */
- @ViewChild('track', {
- read: ElementRef
- })
+ @ViewChild('track', { read: ElementRef, static: true })
trackEl: ElementRef;
/** @hidden */
@@ -230,6 +251,10 @@ export class SliderComponent
})
rangeHandle2: ElementRef;
+ /** @hidden */
+ @ViewChild('rangeGroupHandle', { read: ElementRef, static: false })
+ _rangeGroupHandle: ElementRef;
+
/** @hidden */
@ViewChildren(PopoverComponent)
_popovers: QueryList;
@@ -281,6 +306,9 @@ export class SliderComponent
*/
_useSliderValuePrefix = true;
+ /** @hidden */
+ _handles = SliderRangeHandles;
+
/** @hidden */
private _min = 0;
@@ -337,6 +365,25 @@ export class SliderComponent
_contentDensityObserver.subscribe();
}
+ /**
+ * @hidden
+ * CssClassBuilder interface implementation
+ * function must return single string
+ * function is responsible for order which css classes are applied
+ */
+ @applyCssClass
+ buildComponentCssClass(): string[] {
+ return [
+ 'fd-slider',
+ this.disabled ? 'is-disabled' : '',
+ this._isRange ? 'fd-slider--range' : '',
+ this.showTicks && this.showTicksLabels ? 'fd-slider--with-labels' : '',
+ this.vertical ? 'fd-slider--vertical' : '',
+ this.class,
+ this._platform.EDGE || this._platform.TRIDENT ? 'fd-slider__alternative-tick-width' : ''
+ ];
+ }
+
/** @hidden */
ngOnInit(): void {
this._subscribeToRtl();
@@ -368,11 +415,6 @@ export class SliderComponent
this._onDestroy$.complete();
}
- /** @hidden */
- private isRtl(): boolean {
- return this._rtlService?.rtl.getValue();
- }
-
/** @hidden */
getValuenow(position: number | number[], sliderValueTarget: SliderValueTargets): string | number {
return this.customValues.length > 0
@@ -390,23 +432,6 @@ export class SliderComponent
return this.customValues.length > 0 ? this.customValues[this.max as number].label : this.max;
}
- /**
- * @hidden
- * CssClassBuilder interface implementation
- * function must return single string
- * function is responsible for order which css classes are applied
- */
- @applyCssClass
- buildComponentCssClass(): string[] {
- return [
- 'fd-slider',
- this.disabled ? 'is-disabled' : '',
- this._isRange ? 'fd-slider--range' : '',
- this.showTicks && this.showTicksLabels ? 'fd-slider--with-labels' : '',
- this.class,
- this._platform.EDGE || this._platform.TRIDENT ? 'fd-slider__alternative-tick-width' : ''
- ];
- }
/** @hidden */
onChange: (value: SliderControlValue) => void = () => {};
@@ -444,25 +469,57 @@ export class SliderComponent
}
/** @hidden */
- onHandleClick(event: MouseEvent): void {
+ onHandleClick(event: MouseEvent, group = false): void {
if (this.disabled) {
return;
}
- const unsubscribeFromMousemove = this._renderer.listen('document', 'mousemove', (moveEvent) => {
+
+ let firstHandleCoords: { x: number; y: number };
+ let rangeSliderStartCoords: { x: number; y: number };
+
+ if (group) {
+ rangeSliderStartCoords = {
+ x: event.clientX,
+ y: event.clientY
+ };
+
+ const firstHandleRect = this.rangeHandle1.nativeElement.getBoundingClientRect();
+
+ firstHandleCoords = {
+ x: firstHandleRect.x + firstHandleRect.width / 2,
+ y: firstHandleRect.y + firstHandleRect.height / 2
+ };
+ }
+
+ const unsubscribeFromMousemove = this._renderer.listen('document', 'mousemove', (moveEvent: MouseEvent) => {
this._updatePopoversPosition();
if (!this._isRange) {
this._setValue(this._calculateValueFromPointerPosition(moveEvent));
return;
}
+
+ let coords = {
+ clientX: moveEvent.clientX,
+ clientY: moveEvent.clientY
+ };
+
let handleIndex: SliderRangeHandles;
- if (event.target === this.rangeHandle1.nativeElement) {
+ if (group) {
+ handleIndex = SliderRangeHandles.Both;
+ // Mimic dragging first handle to calculate the difference between old and new values.
+ coords = {
+ clientX: firstHandleCoords!.x + (moveEvent.clientX - rangeSliderStartCoords!.x),
+ clientY: firstHandleCoords!.y + (moveEvent.clientY - rangeSliderStartCoords!.y)
+ };
+ } else if (event.target === this.rangeHandle1.nativeElement) {
handleIndex = SliderRangeHandles.First;
} else if (event.target === this.rangeHandle2.nativeElement) {
handleIndex = SliderRangeHandles.Second;
} else {
return;
}
- const value = this._calculateValueFromPointerPosition(moveEvent, false) as number;
+
+ const value = this._calculateValueFromPointerPosition(coords, false) as number;
this._setRangeHandleValueAndPosition(handleIndex, value);
this._setValue(this._constructRangeModelValue());
});
@@ -473,7 +530,7 @@ export class SliderComponent
}
/** @hidden */
- onKeyDown(event: KeyboardEvent): void {
+ onKeyDown(event: KeyboardEvent, handle?: SliderRangeHandles): void {
if (this.disabled) {
return;
}
@@ -482,44 +539,35 @@ export class SliderComponent
return;
}
event.preventDefault();
- const diff = event.shiftKey ? this.jump : this.step;
- let newValue: number | SliderTickMark | null = null;
- let prevValue = this._position as number;
- let handleIndex: SliderRangeHandles | undefined;
- if (this._isRange) {
- if (event.target === this.rangeHandle1.nativeElement) {
- prevValue = this._handle1Value;
- handleIndex = SliderRangeHandles.First;
- } else if (event.target === this.rangeHandle2.nativeElement) {
- prevValue = this._handle2Value;
- handleIndex = SliderRangeHandles.Second;
- }
- }
- if (this.isRtl()) {
- if (KeyUtil.isKeyCode(event, LEFT_ARROW) || KeyUtil.isKeyCode(event, UP_ARROW)) {
- newValue = prevValue + diff;
- }
- if (KeyUtil.isKeyCode(event, RIGHT_ARROW) || KeyUtil.isKeyCode(event, DOWN_ARROW)) {
- newValue = prevValue - diff;
- }
- } else {
- if (KeyUtil.isKeyCode(event, LEFT_ARROW) || KeyUtil.isKeyCode(event, DOWN_ARROW)) {
- newValue = prevValue - diff;
- }
- if (KeyUtil.isKeyCode(event, RIGHT_ARROW) || KeyUtil.isKeyCode(event, UP_ARROW)) {
- newValue = prevValue + diff;
- }
- }
- if (newValue === null) {
+ const upActionKey = KeyUtil.isKeyCode(event, [UP_ARROW, this._isRtl ? LEFT_ARROW : RIGHT_ARROW]);
+ const downActionKey = KeyUtil.isKeyCode(event, [DOWN_ARROW, this._isRtl ? RIGHT_ARROW : LEFT_ARROW]);
+
+ if (!upActionKey && !downActionKey) {
return;
}
- newValue = this._processNewValue(newValue as number, !this._isRange);
+
+ const diff = event.shiftKey ? this.jump : this.step;
+ let newValue: number | SliderTickMark | null = null;
if (!this._isRange) {
+ newValue = (this._position as number) + diff * (upActionKey ? 1 : -1);
+
+ if (newValue === null) {
+ return;
+ }
+
+ newValue = this._processNewValue(newValue as number, !this._isRange);
+
this._setValue(newValue);
- } else if (handleIndex) {
- this._setRangeHandleValueAndPosition(handleIndex, newValue as number);
- this._setValue(this._constructRangeModelValue());
+ this._updatePopoversPosition();
+ return;
}
+
+ this._handleRangeKeydown(
+ handle === SliderRangeHandles.Both ? [SliderRangeHandles.First, SliderRangeHandles.Second] : handle!,
+ diff,
+ upActionKey
+ );
+
this._updatePopoversPosition();
}
@@ -544,6 +592,36 @@ export class SliderComponent
this._updatePopoversPosition();
}
+ /** @hidden */
+ private _handleRangeKeydown(handles: SliderRangeHandles | SliderRangeHandles[], diff: number, up: boolean): void {
+ handles = Array.isArray(handles) ? handles : [handles];
+ const valueMap = new Map<
+ SliderRangeHandles,
+ { prev: number | SliderTickMark | null; current: number | SliderTickMark | null }
+ >();
+ handles.forEach((handle) => {
+ const prevValue = handle === SliderRangeHandles.First ? this._handle1Value : this._handle2Value;
+ let newValue: number | SliderTickMark | null = prevValue + diff * (up ? 1 : -1);
+ if (newValue === null) {
+ return;
+ }
+
+ newValue = this._processNewValue(newValue as number, !this._isRange);
+
+ valueMap.set(handle, { prev: prevValue, current: newValue });
+ });
+
+ if (Array.from(valueMap.values()).some((entry) => entry.current === entry.prev)) {
+ return;
+ }
+
+ valueMap.forEach((entry, handle) => {
+ this._setRangeHandleValueAndPosition(handle, entry.current as number);
+ });
+
+ this._setValue(this._constructRangeModelValue());
+ }
+
/** @hidden */
private _setValue(value: SliderControlValue, emitEvent = true): void {
if (this._isRange) {
@@ -565,9 +643,13 @@ export class SliderComponent
}
/** @hidden */
- private _calculateValueFromPointerPosition(event: MouseEvent, takeCustomValue = true): number | SliderTickMark {
- const { left, width } = this.trackEl.nativeElement.getBoundingClientRect();
- let percentage = (event.clientX - left) / width;
+ private _calculateValueFromPointerPosition(
+ coords: { clientY: number; clientX: number },
+ takeCustomValue = true
+ ): number | SliderTickMark {
+ const { left, width, bottom, height } = this.trackEl.nativeElement.getBoundingClientRect();
+ let percentage = this.vertical ? (bottom - coords.clientY) / height : (coords.clientX - left) / width;
+
if (this._isRtl) {
percentage = 1 - percentage;
}
@@ -604,10 +686,25 @@ export class SliderComponent
if (handleIndex === SliderRangeHandles.First) {
this._handle1Value = value;
this._handle1Position = position;
- }
- if (handleIndex === SliderRangeHandles.Second) {
+ } else if (handleIndex === SliderRangeHandles.Second) {
this._handle2Value = value;
this._handle2Position = position;
+ } else if (handleIndex === SliderRangeHandles.Both) {
+ // Calculate how much steps being skipped.
+ const oldValueIndex = this._valuesBySteps.indexOf(this._handle1Value);
+ const newValueIndex = this._valuesBySteps.indexOf(value);
+ const diff = oldValueIndex - newValueIndex;
+ const handle2ValueIndex = this._valuesBySteps.indexOf(this._handle2Value);
+
+ if (diff === 0 || this._valuesBySteps.length <= handle2ValueIndex - diff) {
+ return;
+ }
+
+ const positionShift = position - this._handle1Position;
+ this._handle1Position = position;
+ this._handle2Position = this._handle2Position + positionShift;
+ this._handle1Value = value;
+ this._handle2Value = this._valuesBySteps[handle2ValueIndex - diff];
}
this._rangeProgress = Math.abs(this._handle2Position - this._handle1Position);
}
@@ -715,7 +812,10 @@ export class SliderComponent
if (!this.trackEl || !this.trackEl.nativeElement) {
return;
}
- return Math.floor(this.trackEl.nativeElement.getBoundingClientRect().width / MIN_DISTANCE_BETWEEN_TICKS);
+
+ const { width, height } = this.trackEl.nativeElement.getBoundingClientRect();
+
+ return Math.floor((this.vertical ? height : width) / MIN_DISTANCE_BETWEEN_TICKS);
}
/** @hidden */
diff --git a/libs/core/src/lib/slider/slider.model.ts b/libs/core/src/lib/slider/slider.model.ts
index 84ed73051b9..30f1668f635 100644
--- a/libs/core/src/lib/slider/slider.model.ts
+++ b/libs/core/src/lib/slider/slider.model.ts
@@ -6,7 +6,8 @@ export enum SliderValueTargets {
export enum SliderRangeHandles {
First,
- Second
+ Second,
+ Both
}
export interface SliderTickMark {
diff --git a/libs/core/src/lib/slider/slider.module.ts b/libs/core/src/lib/slider/slider.module.ts
index b4b840acc27..d9ea123c4b0 100644
--- a/libs/core/src/lib/slider/slider.module.ts
+++ b/libs/core/src/lib/slider/slider.module.ts
@@ -9,9 +9,10 @@ import { OnlyDigitsModule } from '@fundamental-ngx/cdk/utils';
import { I18nModule } from '@fundamental-ngx/i18n';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
+const EXPORTS = [SliderComponent, SliderPositionDirective];
+
@NgModule({
- declarations: [SliderComponent, SliderPositionDirective],
- imports: [CommonModule, PopoverModule, FormsModule, OnlyDigitsModule, ContentDensityModule, I18nModule],
- exports: [SliderComponent, ContentDensityModule]
+ imports: [CommonModule, PopoverModule, FormsModule, OnlyDigitsModule, ContentDensityModule, I18nModule, ...EXPORTS],
+ exports: [...EXPORTS]
})
export class SliderModule {}
diff --git a/libs/core/src/lib/table/table.component.scss b/libs/core/src/lib/table/table.component.scss
index bbe703fd920..a3bafaea549 100644
--- a/libs/core/src/lib/table/table.component.scss
+++ b/libs/core/src/lib/table/table.component.scss
@@ -12,8 +12,3 @@
margin: 0;
}
}
-
-// TODO: remove hardcoded style
-.fd-table__expand {
- min-width: var(--fdTable_Header_Cell_Height) !important;
-}
diff --git a/libs/core/src/lib/text/text.component.spec.ts b/libs/core/src/lib/text/text.component.spec.ts
index 8dc46837d0e..d2d6a7af808 100644
--- a/libs/core/src/lib/text/text.component.spec.ts
+++ b/libs/core/src/lib/text/text.component.spec.ts
@@ -1,7 +1,6 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { TextComponent } from './text.component';
-import { TextModule } from './text.module';
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
import { patchLanguage } from '@fundamental-ngx/i18n';
@@ -14,7 +13,7 @@ describe('TextComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
- imports: [TextModule],
+ imports: [TextComponent],
schemas: [NO_ERRORS_SCHEMA]
})
.overrideComponent(TextComponent, {
diff --git a/libs/core/src/lib/text/text.component.ts b/libs/core/src/lib/text/text.component.ts
index bb92372e3a2..1dad6114bb8 100644
--- a/libs/core/src/lib/text/text.component.ts
+++ b/libs/core/src/lib/text/text.component.ts
@@ -7,7 +7,10 @@ import {
Output,
ViewEncapsulation
} from '@angular/core';
-import { Nullable } from '@fundamental-ngx/cdk/utils';
+import { LineClampDirective, LineClampTargetDirective, Nullable } from '@fundamental-ngx/cdk/utils';
+import { LinkComponent } from '@fundamental-ngx/core/link';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { NgIf } from '@angular/common';
/** Type of hyphenation */
export type HyphenationType = 'none' | 'manual' | 'auto' | null;
@@ -17,7 +20,9 @@ export type HyphenationType = 'none' | 'manual' | 'auto' | null;
templateUrl: './text.component.html',
styleUrls: ['./text.component.scss'],
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ imports: [LineClampDirective, LineClampTargetDirective, LinkComponent, FdTranslatePipe, NgIf],
+ standalone: true
})
export class TextComponent {
/**
diff --git a/libs/core/src/lib/text/text.module.ts b/libs/core/src/lib/text/text.module.ts
index 49a3946d14f..0714a317d1b 100644
--- a/libs/core/src/lib/text/text.module.ts
+++ b/libs/core/src/lib/text/text.module.ts
@@ -1,14 +1,8 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-
import { TextComponent } from './text.component';
-import { LinkModule } from '@fundamental-ngx/core/link';
-import { LineClampModule } from '@fundamental-ngx/cdk/utils';
-import { I18nModule } from '@fundamental-ngx/i18n';
@NgModule({
- declarations: [TextComponent],
- imports: [CommonModule, LinkModule, LineClampModule, I18nModule],
+ imports: [TextComponent],
exports: [TextComponent]
})
export class TextModule {}
diff --git a/libs/core/src/lib/title/title.component.spec.ts b/libs/core/src/lib/title/title.component.spec.ts
index 868ba10a60e..300ea77ceff 100644
--- a/libs/core/src/lib/title/title.component.spec.ts
+++ b/libs/core/src/lib/title/title.component.spec.ts
@@ -1,6 +1,5 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { TitleComponent } from './title.component';
-import { TitleModule } from './title.module';
describe('TitleComponent', () => {
let component: TitleComponent;
@@ -8,7 +7,7 @@ describe('TitleComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [TitleModule]
+ imports: [TitleComponent]
}).compileComponents();
}));
diff --git a/libs/core/src/lib/title/title.component.ts b/libs/core/src/lib/title/title.component.ts
index b4f1a30173a..9b528ed93c4 100644
--- a/libs/core/src/lib/title/title.component.ts
+++ b/libs/core/src/lib/title/title.component.ts
@@ -20,7 +20,8 @@ export abstract class TitleToken {
styleUrls: ['./title.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
- providers: [{ provide: TitleToken, useExisting: TitleComponent }]
+ providers: [{ provide: TitleToken, useExisting: TitleComponent }],
+ standalone: true
})
export class TitleComponent extends TitleToken implements OnInit {
/** The size of the header */
diff --git a/libs/core/src/lib/title/title.module.ts b/libs/core/src/lib/title/title.module.ts
index 947176e7e44..a1933f51e3d 100644
--- a/libs/core/src/lib/title/title.module.ts
+++ b/libs/core/src/lib/title/title.module.ts
@@ -1,10 +1,8 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
import { TitleComponent } from './title.component';
@NgModule({
- declarations: [TitleComponent],
- imports: [CommonModule],
+ imports: [TitleComponent],
exports: [TitleComponent]
})
export class TitleModule {}
diff --git a/libs/core/src/lib/toolbar/deprecated-toolbar-size.directive.ts b/libs/core/src/lib/toolbar/deprecated-toolbar-size.directive.ts
index 63cebd10666..f3431c69cd3 100644
--- a/libs/core/src/lib/toolbar/deprecated-toolbar-size.directive.ts
+++ b/libs/core/src/lib/toolbar/deprecated-toolbar-size.directive.ts
@@ -17,7 +17,8 @@ type ToolbarSize = 'cozy' | 'compact' | 'condensed' | null;
provide: CONTENT_DENSITY_DIRECTIVE,
useExisting: forwardRef(() => DeprecatedToolbarSizeDirective)
}
- ]
+ ],
+ standalone: true
})
export class DeprecatedToolbarSizeDirective
extends BehaviorSubject
diff --git a/libs/core/src/lib/toolbar/toolbar-form-label.directive.ts b/libs/core/src/lib/toolbar/toolbar-form-label.directive.ts
index 7118a8e6845..1fbc624b056 100644
--- a/libs/core/src/lib/toolbar/toolbar-form-label.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-form-label.directive.ts
@@ -6,6 +6,7 @@ import { ToolbarItemDirective } from './toolbar-item.directive';
selector: '[fd-toolbar-form-label]',
host: {
class: 'fd-form-label fd-toolbar__overflow-form-label fd-toolbar__overflow-form-label--text'
- }
+ },
+ standalone: true
})
export class ToolbarFormLabelDirective extends ToolbarItemDirective {}
diff --git a/libs/core/src/lib/toolbar/toolbar-item.directive.ts b/libs/core/src/lib/toolbar/toolbar-item.directive.ts
index 568f325a424..55f121c620d 100644
--- a/libs/core/src/lib/toolbar/toolbar-item.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-item.directive.ts
@@ -5,7 +5,8 @@ import { OverflowPriorityEnum } from './toolbar.component';
@Directive({
selector: '[fd-toolbar-item], [fdOverflowGroup], [fdOverflowPriority]',
- providers: [{ provide: ToolbarItem, useExisting: forwardRef(() => ToolbarItemDirective) }]
+ providers: [{ provide: ToolbarItem, useExisting: forwardRef(() => ToolbarItemDirective) }],
+ standalone: true
})
export class ToolbarItemDirective implements ToolbarItem {
/** @hidden */
diff --git a/libs/core/src/lib/toolbar/toolbar-label.directive.ts b/libs/core/src/lib/toolbar/toolbar-label.directive.ts
index c27f50442ef..93c567caff5 100644
--- a/libs/core/src/lib/toolbar/toolbar-label.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-label.directive.ts
@@ -7,6 +7,7 @@ import { ToolbarItemDirective } from './toolbar-item.directive';
selector: '[fd-toolbar-label]',
host: {
class: 'fd-label fd-toolbar__overflow-label'
- }
+ },
+ standalone: true
})
export class ToolbarLabelDirective extends ToolbarItemDirective {}
diff --git a/libs/core/src/lib/toolbar/toolbar-overflow-button-menu.directive.ts b/libs/core/src/lib/toolbar/toolbar-overflow-button-menu.directive.ts
index fe3baf010f3..4ea3e8e6d1e 100644
--- a/libs/core/src/lib/toolbar/toolbar-overflow-button-menu.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-overflow-button-menu.directive.ts
@@ -5,6 +5,7 @@ import { ToolbarItemDirective } from './toolbar-item.directive';
selector: '[fdToolbarOverflowButtonMenu], [fd-toolbar-overflow-button-menu]',
host: {
class: 'fd-toolbar__overflow-button--menu'
- }
+ },
+ standalone: true
})
export class ToolbarOverflowButtonMenuDirective extends ToolbarItemDirective {}
diff --git a/libs/core/src/lib/toolbar/toolbar-overflow-button.directive.ts b/libs/core/src/lib/toolbar/toolbar-overflow-button.directive.ts
index 80d9aa05c67..e94803b780e 100644
--- a/libs/core/src/lib/toolbar/toolbar-overflow-button.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-overflow-button.directive.ts
@@ -5,6 +5,7 @@ import { ToolbarItemDirective } from './toolbar-item.directive';
selector: '[fdToolbarOverflowButton], [fd-toolbar-overflow-button]',
host: {
class: 'fd-toolbar__overflow-button'
- }
+ },
+ standalone: true
})
export class ToolbarOverflowButtonDirective extends ToolbarItemDirective {}
diff --git a/libs/core/src/lib/toolbar/toolbar-separator.component.ts b/libs/core/src/lib/toolbar/toolbar-separator.component.ts
index 40f6908b5ff..3138f71df06 100644
--- a/libs/core/src/lib/toolbar/toolbar-separator.component.ts
+++ b/libs/core/src/lib/toolbar/toolbar-separator.component.ts
@@ -7,6 +7,7 @@ import { Component, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'fd-toolbar__separator'
- }
+ },
+ standalone: true
})
export class ToolbarSeparatorComponent {}
diff --git a/libs/core/src/lib/toolbar/toolbar-spacer.directive.ts b/libs/core/src/lib/toolbar/toolbar-spacer.directive.ts
index 392a97a250e..5ccbb4e45a1 100644
--- a/libs/core/src/lib/toolbar/toolbar-spacer.directive.ts
+++ b/libs/core/src/lib/toolbar/toolbar-spacer.directive.ts
@@ -2,7 +2,8 @@ import { Directive, HostBinding, Input } from '@angular/core';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
- selector: 'fd-toolbar-spacer'
+ selector: 'fd-toolbar-spacer',
+ standalone: true
})
export class ToolbarSpacerDirective {
/** Determines the width of spacer when fixed property is set to true
diff --git a/libs/core/src/lib/toolbar/toolbar.component.html b/libs/core/src/lib/toolbar/toolbar.component.html
index 9f3ab1904d1..77cc5161151 100644
--- a/libs/core/src/lib/toolbar/toolbar.component.html
+++ b/libs/core/src/lib/toolbar/toolbar.component.html
@@ -1,35 +1,33 @@
-
-
+
-
+
-
0">
-
-
-
-
-
-
+ 0">
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/core/src/lib/toolbar/toolbar.component.spec.ts b/libs/core/src/lib/toolbar/toolbar.component.spec.ts
index c3da81e0f29..e790d815c8f 100644
--- a/libs/core/src/lib/toolbar/toolbar.component.spec.ts
+++ b/libs/core/src/lib/toolbar/toolbar.component.spec.ts
@@ -63,7 +63,7 @@ describe('ToolbarComponent', () => {
expect(actualOverflowItems.length).toBeGreaterThan(0);
doneFn();
});
- resizeService.trigger(toolbar.toolbar.nativeElement, []);
+ resizeService.trigger(toolbar.elementRef.nativeElement, []);
});
});
});
@@ -111,7 +111,7 @@ describe('ToolbarComponent - Prioritization', () => {
expect(actualOverflownItems.map((el) => el.priority)).toEqual(overflownItems);
doneFn();
});
- resizeService.trigger(toolbar.toolbar.nativeElement, []);
+ resizeService.trigger(toolbar.elementRef.nativeElement, []);
});
});
});
@@ -166,7 +166,7 @@ describe('ToolbarComponent - Prioritization and Grouping', () => {
);
doneFn();
});
- resizeService.trigger(toolbar.toolbar.nativeElement, []);
+ resizeService.trigger(toolbar.elementRef.nativeElement, []);
});
});
});
diff --git a/libs/core/src/lib/toolbar/toolbar.component.ts b/libs/core/src/lib/toolbar/toolbar.component.ts
index 00a06b9de54..2b8162f2835 100644
--- a/libs/core/src/lib/toolbar/toolbar.component.ts
+++ b/libs/core/src/lib/toolbar/toolbar.component.ts
@@ -10,6 +10,8 @@ import {
DestroyRef,
ElementRef,
forwardRef,
+ HostBinding,
+ inject,
Inject,
Input,
Optional,
@@ -36,6 +38,12 @@ import {
} from '@fundamental-ngx/core/content-density';
import { ToolbarItem } from './abstract-toolbar-item.class';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { DynamicPortalComponent } from '@fundamental-ngx/cdk/utils';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { PopoverModule } from '@fundamental-ngx/core/popover';
+import { ToolbarSeparatorComponent } from './toolbar-separator.component';
+import { ToolbarSpacerDirective } from './toolbar-spacer.directive';
+import { NgIf, NgFor } from '@angular/common';
const ELEMENT_MARGIN = 8;
const OVERFLOW_SPACE = 50 + 2 * ELEMENT_MARGIN;
@@ -61,6 +69,16 @@ export const enum OverflowPriorityEnum {
contentDensityObserverProviders({
defaultContentDensity: ContentDensityMode.COMPACT
})
+ ],
+ standalone: true,
+ imports: [
+ NgIf,
+ ToolbarSpacerDirective,
+ ToolbarSeparatorComponent,
+ PopoverModule,
+ ButtonModule,
+ NgFor,
+ DynamicPortalComponent
]
})
export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssClassBuilder, AfterContentInit {
@@ -119,9 +137,15 @@ export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssCla
@Input()
tabindex = -1;
- /** @hidden */
- @ViewChild('toolbar')
- toolbar: ElementRef;
+ /** Toolbar Aria-label attribute. */
+ @Input()
+ @HostBinding('attr.aria-label')
+ ariaLabel: string;
+
+ /** Toolbar Aria-labelledby attribute. */
+ @Input()
+ @HostBinding('attr.aria-labelledby')
+ ariaLabelledBy: string;
/** @hidden */
@ViewChild('titleElement')
@@ -147,6 +171,13 @@ export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssCla
/** @hidden */
overflownItems: ToolbarItem[] = [];
+ /** HTML Element Reference. */
+ readonly elementRef = inject(ElementRef);
+
+ /** @hidden */
+ @HostBinding('attr.role')
+ private readonly _role = 'toolbar';
+
/** @hidden */
private _titleComponent$: BehaviorSubject = new BehaviorSubject(null);
@@ -155,7 +186,7 @@ export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssCla
/** @hidden */
private get _toolbarWidth(): number {
- return (this.toolbar.nativeElement as HTMLElement).clientWidth - OVERFLOW_SPACE;
+ return (this.elementRef.nativeElement as HTMLElement).clientWidth - OVERFLOW_SPACE;
}
/** @hidden */
@@ -191,7 +222,7 @@ export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssCla
/** @hidden */
ngAfterViewInit(): void {
this.overflowItems$ = combineLatest([
- this.resizeObserverService.observe(this.toolbar.nativeElement).pipe(map(() => this._toolbarWidth)),
+ this.resizeObserverService.observe(this.elementRef.nativeElement).pipe(map(() => this._toolbarWidth)),
this.toolbarItems.changes.pipe(
startWith(this.toolbarItems),
map((toolbarItems) => toolbarItems.toArray())
@@ -276,11 +307,6 @@ export class ToolbarComponent implements AfterViewInit, AfterViewChecked, CssCla
this._cd.detectChanges();
}
- /** @hidden */
- get elementRef(): ElementRef {
- return this.toolbar;
- }
-
/** Method triggering collapsible toolbar */
updateCollapsibleItems(): void {
this._refreshOverflow$.next();
diff --git a/libs/core/src/lib/toolbar/toolbar.module.ts b/libs/core/src/lib/toolbar/toolbar.module.ts
index 31c6939ceb0..b7ad147a3c3 100644
--- a/libs/core/src/lib/toolbar/toolbar.module.ts
+++ b/libs/core/src/lib/toolbar/toolbar.module.ts
@@ -1,8 +1,4 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-
-import { ButtonModule } from '@fundamental-ngx/core/button';
-import { PopoverModule } from '@fundamental-ngx/core/popover';
import { ToolbarComponent } from './toolbar.component';
import { ToolbarItemDirective } from './toolbar-item.directive';
import { ToolbarSeparatorComponent } from './toolbar-separator.component';
@@ -13,7 +9,6 @@ import { ToolbarOverflowButtonMenuDirective } from './toolbar-overflow-button-me
import { ToolbarFormLabelDirective } from './toolbar-form-label.directive';
import { DeprecatedToolbarSizeDirective } from './deprecated-toolbar-size.directive';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
-import { DynamicPortalComponent } from '@fundamental-ngx/cdk/utils';
const components = [
ToolbarComponent,
@@ -28,8 +23,7 @@ const components = [
];
@NgModule({
- declarations: [...components],
- imports: [CommonModule, ButtonModule, PopoverModule, ContentDensityModule, DynamicPortalComponent],
+ imports: [ContentDensityModule, ...components],
exports: [...components, ContentDensityModule]
})
export class ToolbarModule {}
diff --git a/libs/core/src/lib/tree/tree.component.scss b/libs/core/src/lib/tree/tree.component.scss
index 471f274659e..3afc690e207 100644
--- a/libs/core/src/lib/tree/tree.component.scss
+++ b/libs/core/src/lib/tree/tree.component.scss
@@ -31,11 +31,3 @@ $block: fd-tree;
}
}
}
-
-// TODO: Remove these stylings after new stable fundamental-styles version bump.
-
-.fd-tree__item[aria-level='1'] > .fd-tree__item-container--active.is-focus:before,
-.fd-tree__item[aria-level='1'] > .fd-tree__item-container--active:focus:before,
-.fd-tree__item-container--active:focus:before {
- bottom: 0.0625rem;
-}
diff --git a/libs/core/src/lib/vertical-navigation/vertical-navigation.component.spec.ts b/libs/core/src/lib/vertical-navigation/vertical-navigation.component.spec.ts
index a53aaa19924..0a1763d6578 100644
--- a/libs/core/src/lib/vertical-navigation/vertical-navigation.component.spec.ts
+++ b/libs/core/src/lib/vertical-navigation/vertical-navigation.component.spec.ts
@@ -1,9 +1,7 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { Component, ElementRef, ViewChild } from '@angular/core';
+import { Component, ElementRef, NO_ERRORS_SCHEMA, ViewChild } from '@angular/core';
import { VerticalNavigationComponent } from './vertical-navigation.component';
-import { LinkComponent } from '@fundamental-ngx/core/link';
-import { IconModule } from '@fundamental-ngx/core/icon';
import { ListNavigationItemComponent, ListModule } from '@fundamental-ngx/core/list';
@Component({
@@ -56,8 +54,9 @@ describe('VerticalNavigationComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- declarations: [VerticalNavigationComponent, TestVerticalNavigationComponent, LinkComponent],
- imports: [IconModule, ListModule]
+ declarations: [VerticalNavigationComponent, TestVerticalNavigationComponent],
+ imports: [ListModule],
+ schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
diff --git a/libs/docs/core/card/e2e/card.po.ts b/libs/docs/core/card/e2e/card.po.ts
index 9dfb8c874ec..b41a612ea8b 100644
--- a/libs/docs/core/card/e2e/card.po.ts
+++ b/libs/docs/core/card/e2e/card.po.ts
@@ -26,7 +26,7 @@ export class CardPo extends CoreBaseComponentPo {
ftCardListItems = 'fd-card-footer-example fd-card:first-of-type li';
ftFooter = 'fd-card-footer-example fd-card-footer';
ftCardFooterActionItems =
- 'fd-card-footer-example fd-card:first-of-type fd-card-footer .fd-card__footer-actions-item';
+ 'fd-card-footer-example fd-card:first-of-type fd-card-footer .fd-card__footer-actions button';
// analytical card examples
kpiCardHeader = 'fd-card-kpi-example fd-card-header';
kpiCardTitle = 'fd-card-kpi-example .fd-card__title';
diff --git a/libs/docs/core/carousel/carousel-docs.component.html b/libs/docs/core/carousel/carousel-docs.component.html
index 0a65db7e3a9..75f99ed4824 100644
--- a/libs/docs/core/carousel/carousel-docs.component.html
+++ b/libs/docs/core/carousel/carousel-docs.component.html
@@ -151,3 +151,28 @@
+
+
+Background modifiers
+
+
+ The background of the Carousel Content and Page Indicator Container can be changed by providing
+ [contentBackground]
and [pageIndicatorBackground]
input properties.
+
+ Background options can be following:
+
+ translucent
+ transparent
+ solid
+
+ The default background for the Carousel Content is translucent
.
+ The default background for the Page Indicator Container is solid
.
+
+ Additionally, developers can pass [noPaginationContainerBorder]="true"
to remove the border top or
+ bottom of the Pagination container.
+
+
+
+
+
+
diff --git a/libs/docs/core/carousel/carousel-docs.module.ts b/libs/docs/core/carousel/carousel-docs.module.ts
index a1a02b4d8fd..b0cbd043667 100644
--- a/libs/docs/core/carousel/carousel-docs.module.ts
+++ b/libs/docs/core/carousel/carousel-docs.module.ts
@@ -22,6 +22,7 @@ import { CarouselLoopedNavigationExampleComponent } from './examples/carousel-lo
import { CarouselErrorMessageExampleComponent } from './examples/carousel-error-message-example.component';
import { CarouselLoadingContentExampleComponent } from './examples/carousel-loading-content-example.component';
import { CarouselAutoSlidesExampleComponent } from './examples/carousel-auto-slides-example.component';
+import { CarouselBackgroundExampleComponent } from './examples/carousel-background-example.component';
const routes: Routes = [
{
@@ -60,7 +61,8 @@ const routes: Routes = [
CarouselLoopedNavigationExampleComponent,
CarouselErrorMessageExampleComponent,
CarouselLoadingContentExampleComponent,
- CarouselAutoSlidesExampleComponent
+ CarouselAutoSlidesExampleComponent,
+ CarouselBackgroundExampleComponent
],
providers: [currentComponentProvider('carousel')]
})
diff --git a/libs/docs/core/carousel/e2e/carousel.e2e-spec.ts b/libs/docs/core/carousel/e2e/carousel.e2e-spec.ts
index ab44ebc9810..f6e264c1e52 100644
--- a/libs/docs/core/carousel/e2e/carousel.e2e-spec.ts
+++ b/libs/docs/core/carousel/e2e/carousel.e2e-spec.ts
@@ -215,17 +215,17 @@ describe('Carousel test suite', () => {
describe('carousel with looped navigation example', () => {
it('should check loop navigation', async () => {
- const firstImg = await getAttributeByName(displayedImg, imgSource, 5);
+ const firstImg = await getAttributeByName(displayedImg, imgSource, 6);
- await click(navBtns, 14);
+ await click(navBtns, 16);
// pause for animation to complete
await pause(1500);
- await expect(await getAttributeByName(displayedImg, imgSource, 5)).not.toBe(firstImg);
+ await expect(await getAttributeByName(displayedImg, imgSource, 6)).not.toBe(firstImg);
- await click(navBtns, 15);
+ await click(navBtns, 17);
// pause for animation to complete
await pause(1500);
- await expect(await getAttributeByName(displayedImg, imgSource, 5)).toBe(firstImg);
+ await expect(await getAttributeByName(displayedImg, imgSource, 6)).toBe(firstImg);
});
});
diff --git a/libs/docs/core/carousel/examples/carousel-background-example.component.html b/libs/docs/core/carousel/examples/carousel-background-example.component.html
new file mode 100644
index 00000000000..244cb650162
--- /dev/null
+++ b/libs/docs/core/carousel/examples/carousel-background-example.component.html
@@ -0,0 +1,62 @@
+Transparent Carousel Content:
+
+Solid Carousel Content:
+
+Transparent Page Indicator Container:
+
+Translucent Page Indicator Container:
+
+Page Indicator Container with no border:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/docs/core/carousel/examples/carousel-background-example.component.ts b/libs/docs/core/carousel/examples/carousel-background-example.component.ts
new file mode 100644
index 00000000000..b788036166d
--- /dev/null
+++ b/libs/docs/core/carousel/examples/carousel-background-example.component.ts
@@ -0,0 +1,9 @@
+import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
+
+@Component({
+ selector: 'fd-carousel-background-example',
+ templateUrl: './carousel-background-example.component.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class CarouselBackgroundExampleComponent {}
diff --git a/libs/docs/core/carousel/examples/carousel-content-navigation-example.component.html b/libs/docs/core/carousel/examples/carousel-content-navigation-example.component.html
index 948da29d4f2..6993b7624ee 100644
--- a/libs/docs/core/carousel/examples/carousel-content-navigation-example.component.html
+++ b/libs/docs/core/carousel/examples/carousel-content-navigation-example.component.html
@@ -1,39 +1,52 @@
-
+Horizontal navigation:
+
+Vertical navigation:
+
+
+
+
+
diff --git a/libs/docs/core/checkbox/checkbox-docs.component.html b/libs/docs/core/checkbox/checkbox-docs.component.html
index 0268b2958c6..f74d05eef3d 100644
--- a/libs/docs/core/checkbox/checkbox-docs.component.html
+++ b/libs/docs/core/checkbox/checkbox-docs.component.html
@@ -70,6 +70,21 @@
+
+ Checkbox with label wrapping
+
+
+ Checkbox labels by default do not wrap. If you want to wrap the labels, then you should use
+ fd-checkbox[wrapLabel]
+ input
+
+
+
+
+
+
+
+
Checkbox styling properties
Checkbox can be but in various states by modifying following properties:
@@ -92,3 +107,17 @@
+
+
+
+
+ Checkbox with Display-only mode
+
+
+ For cases when users should not interact with the Checkbox, developers can set it to 'Display-only' mode with
+ [displayOnly]="true"
input property.
+
+
+
+
+
diff --git a/libs/docs/core/checkbox/checkbox-docs.component.ts b/libs/docs/core/checkbox/checkbox-docs.component.ts
index 7e67e02d35c..353ed629145 100644
--- a/libs/docs/core/checkbox/checkbox-docs.component.ts
+++ b/libs/docs/core/checkbox/checkbox-docs.component.ts
@@ -8,6 +8,8 @@ const checkboxCustomValuesTsCode = 'checkbox-custom-values-example.component.ts'
const checkboxReactiveFormsTsCode = 'checkbox-reactive-forms-example.component.ts';
const checkboxStatesTsCode = 'checkbox-states-example.component.ts';
const checkboxCustomLabelTsCode = 'checkbox-custom-label-example.component.ts';
+const checkboxWrappingTsCode = 'checkbox-label-wrapping-example.component.ts';
+const checkboxDisplayOnlyMode = 'checkbox-display-mode-example.component.ts';
@Component({
selector: 'app-input',
@@ -67,4 +69,22 @@ export class CheckboxDocsComponent {
code: getAssetFromModuleAssets(checkboxCustomLabelTsCode)
}
];
+
+ checkboxLabelWrapping: ExampleFile[] = [
+ {
+ language: 'typescript',
+ fileName: 'checkbox-label-wrapping-example',
+ component: 'CheckboxLabelWrappingExampleComponent',
+ code: getAssetFromModuleAssets(checkboxWrappingTsCode)
+ }
+ ];
+
+ checkboxDisplayOnlyMode: ExampleFile[] = [
+ {
+ language: 'typescript',
+ fileName: 'checkbox-display-mode-example',
+ component: 'CheckboxDisplayModeExampleComponent',
+ code: getAssetFromModuleAssets(checkboxDisplayOnlyMode)
+ }
+ ];
}
diff --git a/libs/docs/core/checkbox/checkbox-docs.module.ts b/libs/docs/core/checkbox/checkbox-docs.module.ts
index 6c71b8c0927..fc499456ccf 100644
--- a/libs/docs/core/checkbox/checkbox-docs.module.ts
+++ b/libs/docs/core/checkbox/checkbox-docs.module.ts
@@ -6,6 +6,7 @@ import { CheckboxHeaderComponent } from './checkbox-header/checkbox-header.compo
import { CheckboxDocsComponent } from './checkbox-docs.component';
import { examples } from './examples';
import { FormModule } from '@fundamental-ngx/core/form';
+import { CheckboxDisplayModeExampleComponent } from './examples/checkbox-display-mode-example.component';
import { CheckboxModule } from '@fundamental-ngx/core/checkbox';
const routes: Routes = [
@@ -21,8 +22,8 @@ const routes: Routes = [
@NgModule({
imports: [FormModule, CheckboxModule, RouterModule.forChild(routes), SharedDocumentationPageModule],
- exports: [RouterModule],
- declarations: [examples, CheckboxDocsComponent, CheckboxHeaderComponent],
+ exports: [RouterModule, CheckboxDisplayModeExampleComponent],
+ declarations: [examples, CheckboxDocsComponent, CheckboxHeaderComponent, CheckboxDisplayModeExampleComponent],
providers: [currentComponentProvider('checkbox')]
})
export class CheckboxDocsModule {}
diff --git a/libs/docs/core/checkbox/e2e/checkbox-content.ts b/libs/docs/core/checkbox/e2e/checkbox-content.ts
index 2d913e69fbf..c26791fba24 100644
--- a/libs/docs/core/checkbox/e2e/checkbox-content.ts
+++ b/libs/docs/core/checkbox/e2e/checkbox-content.ts
@@ -1,4 +1,3 @@
-export const emptyDataArr = ['""', null, undefined];
export const emptyString = '""';
export const customLabelsArr = ['Yes', 'No', 'I dont have an opinion'];
export const allMarkedTrue =
diff --git a/libs/docs/core/checkbox/e2e/checkbox.e2e-spec.ts b/libs/docs/core/checkbox/e2e/checkbox.e2e-spec.ts
index 74db1c61d72..69525096839 100644
--- a/libs/docs/core/checkbox/e2e/checkbox.e2e-spec.ts
+++ b/libs/docs/core/checkbox/e2e/checkbox.e2e-spec.ts
@@ -1,7 +1,6 @@
import { CheckboxPo } from './checkbox.po';
// eslint-disable-next-line @nx/enforce-module-boundaries
import {
- applyState,
browserIsSafari,
click,
executeScriptBeforeTagAttr,
@@ -24,7 +23,6 @@ import {
altCustomLabel,
customLabel,
customLabelsArr,
- emptyDataArr,
emptyString,
stateClassesArr
} from './checkbox-content';
@@ -41,6 +39,7 @@ describe('checkbox test suite', () => {
checkbox,
checkboxInput,
checkboxLabel,
+ checkboxCheckmark,
link,
tristateOutput
} = checkboxPage;
@@ -53,14 +52,14 @@ describe('checkbox test suite', () => {
it('should mark checkbox', async () => {
await scrollIntoView(standardCheckbox);
- await expect(await executeScriptBeforeTagAttr(standardCheckbox + checkboxLabel, 'content')).toEqual(
+ await expect(await executeScriptBeforeTagAttr(standardCheckbox + checkboxCheckmark, 'content')).toEqual(
emptyString,
'mark is present'
);
await click(standardCheckbox + checkboxLabel);
- await expect(await executeScriptBeforeTagAttr(standardCheckbox + checkboxLabel, 'content')).not.toEqual(
+ await expect(await executeScriptBeforeTagAttr(standardCheckbox + checkboxCheckmark, 'content')).not.toEqual(
emptyString,
'mark is not present'
);
@@ -199,7 +198,7 @@ describe('checkbox test suite', () => {
for (let i = 0; i < checkboxCount; i++) {
await expect(
- await executeScriptBeforeTagAttr(reactiveFormCheckbox + checkboxLabel, 'content', i)
+ await executeScriptBeforeTagAttr(reactiveFormCheckbox + checkboxCheckmark, 'content', i)
).not.toEqual(emptyString);
}
const textArr = (await getText(reactiveFormCheckbox)).split('\n');
@@ -218,7 +217,7 @@ describe('checkbox test suite', () => {
for (let i = 0; i < checkboxCount; i++) {
await expect(
- await executeScriptBeforeTagAttr(reactiveFormCheckbox + checkboxLabel, 'content', i)
+ await executeScriptBeforeTagAttr(reactiveFormCheckbox + checkboxCheckmark, 'content', i)
).toEqual(emptyString);
}
const textArr2 = (await getText(reactiveFormCheckbox)).split('\n');
diff --git a/libs/docs/core/checkbox/e2e/checkbox.po.ts b/libs/docs/core/checkbox/e2e/checkbox.po.ts
index 922a3fee332..ab61c205aa9 100644
--- a/libs/docs/core/checkbox/e2e/checkbox.po.ts
+++ b/libs/docs/core/checkbox/e2e/checkbox.po.ts
@@ -14,6 +14,7 @@ export class CheckboxPo extends CoreBaseComponentPo {
checkbox = 'fd-checkbox';
checkboxInput = this.checkbox + ' input';
checkboxLabel = this.checkbox + ' label';
+ checkboxCheckmark = this.checkboxLabel + ' span.fd-checkbox__checkmark';
link = this.checkbox + ' a';
tristateOutput = this.tristateCheckbox + 'div';
diff --git a/libs/docs/core/checkbox/examples/checkbox-display-mode-example.component.ts b/libs/docs/core/checkbox/examples/checkbox-display-mode-example.component.ts
new file mode 100644
index 00000000000..f08b93cc246
--- /dev/null
+++ b/libs/docs/core/checkbox/examples/checkbox-display-mode-example.component.ts
@@ -0,0 +1,29 @@
+import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
+
+@Component({
+ selector: 'fd-checkbox-display-mode-example',
+ template: `
+ Display-only checkboxes can be controlled programmatically. They will not react on any user interaction.
+ Display-only checkbox
+
+ Value: {{ checkboxValue }}
+
+
+ Change value to {{ checkboxValue ? 'false' : 'true' }}
+
+ `,
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class CheckboxDisplayModeExampleComponent {
+ checkboxValue = false;
+
+ toggleCheckboxValue(): void {
+ this.checkboxValue = !this.checkboxValue;
+ }
+}
diff --git a/libs/docs/core/checkbox/examples/checkbox-label-wrapping-example.component.ts b/libs/docs/core/checkbox/examples/checkbox-label-wrapping-example.component.ts
new file mode 100644
index 00000000000..4203644d89f
--- /dev/null
+++ b/libs/docs/core/checkbox/examples/checkbox-label-wrapping-example.component.ts
@@ -0,0 +1,34 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'fd-checkbox-label-wrapping-example',
+ template: `
+
+
+ LABEL WILL BE POSITIONED IN THE MIDDLE. Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+ Corporis ea eos in porro quae ullam. Aliquid corporis doloribus exercitationem facilis hic illo labore
+ laudantium quam reprehenderit sapiente, tempore voluptatibus voluptatum?
+
+
+
+
+ LABEL WILL BE POSITIONED ON THE TOP. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corporis
+ ea eos in porro quae ullam. Aliquid corporis doloribus exercitationem facilis hic illo labore laudantium
+ quam reprehenderit sapiente, tempore voluptatibus voluptatum?
+
+
+ `,
+ styles: [
+ `
+ :host {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ }
+ div {
+ max-width: 300px;
+ }
+ `
+ ]
+})
+export class CheckboxLabelWrappingExampleComponent {}
diff --git a/libs/docs/core/checkbox/examples/index.ts b/libs/docs/core/checkbox/examples/index.ts
index 0c101e8ccde..e861d992702 100644
--- a/libs/docs/core/checkbox/examples/index.ts
+++ b/libs/docs/core/checkbox/examples/index.ts
@@ -4,6 +4,7 @@ import { CheckboxDefaultExampleComponent } from './checkbox-default-example.comp
import { CheckboxReactiveFormsExampleComponent } from './checkbox-reactive-forms-example.component';
import { CheckboxStatesExampleComponent } from './checkbox-states-example.component';
import { CheckboxTristateExampleComponent } from './checkbox-tristate-example.component';
+import { CheckboxLabelWrappingExampleComponent } from './checkbox-label-wrapping-example.component';
export * from './checkbox-custom-label-example.component';
export * from './checkbox-custom-values-example.component';
@@ -18,5 +19,6 @@ export const examples = [
CheckboxTristateExampleComponent,
CheckboxCustomLabelExampleComponent,
CheckboxCustomValuesExampleComponent,
- CheckboxReactiveFormsExampleComponent
+ CheckboxReactiveFormsExampleComponent,
+ CheckboxLabelWrappingExampleComponent
];
diff --git a/libs/docs/core/checkbox/index.ts b/libs/docs/core/checkbox/index.ts
index 4ebc3c53c0c..408867e9222 100644
--- a/libs/docs/core/checkbox/index.ts
+++ b/libs/docs/core/checkbox/index.ts
@@ -1 +1,3 @@
export * from './checkbox-docs.module';
+
+export * from './examples/checkbox-display-mode-example.component';
diff --git a/libs/docs/core/dialog/examples/dialog-state/dialog-state-example.component.ts b/libs/docs/core/dialog/examples/dialog-state/dialog-state-example.component.ts
index 81e3183152f..f290f49e6cb 100644
--- a/libs/docs/core/dialog/examples/dialog-state/dialog-state-example.component.ts
+++ b/libs/docs/core/dialog/examples/dialog-state/dialog-state-example.component.ts
@@ -49,6 +49,10 @@ export class DialogStateExampleComponent {
ariaLabelledBy: 'fd-dialog-header-7',
ariaDescribedBy: 'fd-dialog-body-7'
});
- dialogRef.loading(true);
+ dialogRef.loading({
+ isLoading: true,
+ loadingLabel: 'Some loading label',
+ loadingContent: '... now loading data from a far far away server from far far away.'
+ });
}
}
diff --git a/libs/docs/core/list-byline/e2e/list-byline.e2e-spec.ts b/libs/docs/core/list-byline/e2e/list-byline.e2e-spec.ts
index c37555de489..8c1a1ca2cdd 100644
--- a/libs/docs/core/list-byline/e2e/list-byline.e2e-spec.ts
+++ b/libs/docs/core/list-byline/e2e/list-byline.e2e-spec.ts
@@ -12,7 +12,7 @@ import {
describe('List byline test suite', () => {
const listBylinePage = new ListBylinePo();
- const { selectionExample, buttonExample, button, checkbox, listItem, radioButton, radioButtonInput } =
+ const { selectionExample, buttonExample, button, checkbox, listItem, radioButtonLabel, radioButtonInput } =
listBylinePage;
beforeAll(async () => {
@@ -47,11 +47,14 @@ describe('List byline test suite', () => {
});
it('verify that radio buttons work correctly', async () => {
- const radioButtonLength = await getElementArrayLength(selectionExample + radioButton);
- for (let i = 0; i < radioButtonLength; i++) {
- await scrollIntoView(selectionExample + radioButton, i);
- await click(selectionExample + radioButton, i);
- await expect(await getAttributeByName(radioButtonInput, 'aria-checked', i)).toBe('true');
+ const radioButtonLabels = await $$(`${selectionExample} ${radioButtonLabel}`);
+ const radioButtonInputs = await $$(`${selectionExample} ${radioButtonInput}`);
+ for (let i = 0; i < radioButtonLabels.length; i++) {
+ const label = radioButtonLabels[i];
+ await label.scrollIntoView();
+ await label.click();
+ const ariaChecked = await radioButtonInputs[i].getAttribute('aria-checked');
+ await expect(ariaChecked).toBe('true');
}
});
diff --git a/libs/docs/core/list-byline/e2e/list-byline.po.ts b/libs/docs/core/list-byline/e2e/list-byline.po.ts
index ca1b0a19348..5b775d52648 100644
--- a/libs/docs/core/list-byline/e2e/list-byline.po.ts
+++ b/libs/docs/core/list-byline/e2e/list-byline.po.ts
@@ -8,7 +8,7 @@ export class ListBylinePo extends CoreBaseComponentPo {
button = ' button';
checkbox = ' fd-checkbox';
- radioButton = ' .fd-radio__label';
+ radioButtonLabel = '.fd-radio__label';
radioButtonInput = '.fd-radio';
listItem = ' .fd-list__item';
diff --git a/libs/docs/core/list/e2e/standard-list.e2e-spec.ts b/libs/docs/core/list/e2e/standard-list.e2e-spec.ts
index e07efa55559..58544674f88 100644
--- a/libs/docs/core/list/e2e/standard-list.e2e-spec.ts
+++ b/libs/docs/core/list/e2e/standard-list.e2e-spec.ts
@@ -4,7 +4,6 @@ import {
click,
clickAndDragElement,
doesItExist,
- executeScriptBeforeTagAttr,
getElementArrayLength,
getElementClass,
getElementLocation,
@@ -31,7 +30,6 @@ describe('Standard List test suite', () => {
cozySingleSelectList,
compactSingleSelectList,
selectedItems,
- keyboardSupportList,
dragAndDropList,
infiniteList,
deleteButton,
diff --git a/libs/docs/core/list/e2e/standard-list.po.ts b/libs/docs/core/list/e2e/standard-list.po.ts
index bdde44155f6..fa639ff828b 100644
--- a/libs/docs/core/list/e2e/standard-list.po.ts
+++ b/libs/docs/core/list/e2e/standard-list.po.ts
@@ -4,22 +4,13 @@ export class StandardListPo extends CoreBaseComponentPo {
url = '/list';
// example selectors
- simpleList = 'fd-list-example ';
- navigationList = 'fd-list-navigation-example ';
- navigationIndicatorList = 'fd-list-nav-indicator-example ';
actionList = 'fd-list-action-example ';
filterAndSortList = 'fd-list-data-example ';
- secondaryItemList = 'fd-list-secondary-example ';
- iconList = 'fd-list-icon-example ';
- borderlessList = 'fd-list-borderless-example ';
- interactiveList = 'fd-list-interactive-example ';
- complexList = 'fd-list-complex-example ';
selectionList = 'fd-list-selection-example ';
cozyMultiSelectList = this.selectionList + 'ul:first-of-type ';
compactMultiSelectList = this.selectionList + 'ul:nth-of-type(2) ';
cozySingleSelectList = this.selectionList + 'ul:nth-of-type(3) ';
compactSingleSelectList = this.selectionList + 'ul:nth-of-type(4) ';
- keyboardSupportList = 'fd-list-keyboard-example ';
dragAndDropList = 'fd-list-dnd-example ';
infiniteList = 'fd-list-infinite-scroll-example ';
@@ -30,9 +21,6 @@ export class StandardListPo extends CoreBaseComponentPo {
searchBar = 'fd-input-group input';
selectedItems = 'li[class~="is-selected"]';
checkbox = 'fd-checkbox';
- radioBtn = 'fd-radio-button';
- checkboxFocusElement = this.checkbox + ' input';
- radioBtnFocusElement = this.radioBtn + ' input';
deleteButton = 'button[glyph="delete"]';
listItemText = '.fd-list__title';
diff --git a/libs/docs/core/list/examples/list-secondary-example.component.html b/libs/docs/core/list/examples/list-secondary-example.component.html
index 60887113f09..7ad26f5c070 100644
--- a/libs/docs/core/list/examples/list-secondary-example.component.html
+++ b/libs/docs/core/list/examples/list-secondary-example.component.html
@@ -1,16 +1,28 @@
List item 1
- 1
+ 1
List item 2
- 2
+ 2
+
+
+ List item 3
+ 3
+
+
+ List item 4
+ 4
+
+
+ List item 5
+ 5
- List item 3 with Counter
+ List item 6 with Counter
- List item 4 with Counter
+ List item 7 with Counter
diff --git a/libs/docs/core/list/list-docs.component.html b/libs/docs/core/list/list-docs.component.html
index 9851e8ea0be..d885d9b9107 100644
--- a/libs/docs/core/list/list-docs.component.html
+++ b/libs/docs/core/list/list-docs.component.html
@@ -66,7 +66,17 @@
Secondary item on list
-The list component can be customized by adding additional information in additional columns.
+
+ The list component can be customized by adding additional information in additional columns.
+
+ Secondary items can have different types of visual appearance and can be set with
+ [fd-list-secondary][type]
property
+
+ Available types are
+
+ {{ secondaryListItemType }}
+
+
diff --git a/libs/docs/core/list/list-docs.component.ts b/libs/docs/core/list/list-docs.component.ts
index 9dd80e20485..daca5c0a079 100644
--- a/libs/docs/core/list/list-docs.component.ts
+++ b/libs/docs/core/list/list-docs.component.ts
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { ExampleFile, getAssetFromModuleAssets } from '@fundamental-ngx/docs/shared';
+import { _secondaryListItemTypes } from '@fundamental-ngx/core/list';
const listSortPipe = 'sort.pipe.ts';
const listSrc = 'list-example.component.html';
@@ -193,4 +194,5 @@ export class ListDocsComponent {
fileName: 'list-loading-example'
}
];
+ readonly _secondaryListItemTypes = _secondaryListItemTypes;
}
diff --git a/libs/docs/core/message-strip/examples/message-strip-custom-icon-example.component.ts b/libs/docs/core/message-strip/examples/message-strip-custom-icon-example.component.ts
new file mode 100644
index 00000000000..f592ab68385
--- /dev/null
+++ b/libs/docs/core/message-strip/examples/message-strip-custom-icon-example.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'fd-message-strip-custom-icon-example',
+ template: `
+
+
+ A dismissible normal message strip with custom icon.
+
+ `
+})
+export class MessageStripCustomIconExampleComponent {}
diff --git a/libs/docs/core/message-strip/examples/message-strip-indication-colors-example.component.ts b/libs/docs/core/message-strip/examples/message-strip-indication-colors-example.component.ts
new file mode 100644
index 00000000000..2123853b31b
--- /dev/null
+++ b/libs/docs/core/message-strip/examples/message-strip-indication-colors-example.component.ts
@@ -0,0 +1,24 @@
+import { Component } from '@angular/core';
+import { _messageStripIndicationColors } from '@fundamental-ngx/core/message-strip';
+
+@Component({
+ selector: 'fd-message-strip-indication-colors-example',
+ template: `
+
+
+ This is the message strip with indication color "{{ indicationColor }}"
+
+ `,
+ styles: [
+ `
+ :host {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ }
+ `
+ ]
+})
+export class MessageStripIndicationColorsExampleComponent {
+ indicationColors = _messageStripIndicationColors;
+}
diff --git a/libs/docs/core/message-strip/message-strip-docs.component.html b/libs/docs/core/message-strip/message-strip-docs.component.html
index 70adb930196..065eb02c914 100644
--- a/libs/docs/core/message-strip/message-strip-docs.component.html
+++ b/libs/docs/core/message-strip/message-strip-docs.component.html
@@ -1,9 +1,11 @@
Message Strip Types
-A number of message strip types are available. They offer preset styling for different contextual situations. Can
- be one of 'warning', 'success', 'information', 'error' or normal (default).
+
+
+ A number of message strip types are available. They offer preset styling for different contextual situations.
+ Can be one of 'warning', 'success', 'information', 'error' or normal (default).
+
@@ -12,6 +14,22 @@
+
+ Custom Icons
+
+
+
+ If you want to have a custom icon, that is also supported using the *fdMessageStripIcon
+ directive.
+
+
+
+
+
+
+
+
+
Message Strips Without Icons
@@ -40,6 +58,23 @@
+
+ Message Strips Indication Colors
+
+
+
+ If the application needs a custom Message Strip, other than the semantic variations, then the colours from
+ Inverted Object Status/Tag control should be used. Use the input [indicationColor]
with values
+ number from 1 to 10 for the first set, and 1b to 10b for the second set.
+
+
+
+
+
+
+
+
+
Message Strip Alerts
diff --git a/libs/docs/core/message-strip/message-strip-docs.component.ts b/libs/docs/core/message-strip/message-strip-docs.component.ts
index 593f87104f3..c1f2630ff72 100644
--- a/libs/docs/core/message-strip/message-strip-docs.component.ts
+++ b/libs/docs/core/message-strip/message-strip-docs.component.ts
@@ -53,6 +53,22 @@ export class MessageStripDocsComponent {
}
];
+ messageStripCustomIconExample: ExampleFile[] = [
+ {
+ language: 'ts',
+ fileName: 'message-strip-custom-icon-example',
+ code: getAssetFromModuleAssets('message-strip-custom-icon-example.component.ts')
+ }
+ ];
+
+ messageStripIndicationColorsExample: ExampleFile[] = [
+ {
+ language: 'ts',
+ fileName: 'message-strip-indication-colors-example',
+ code: getAssetFromModuleAssets('message-strip-indication-colors-example.component.ts')
+ }
+ ];
+
messageStripAlertExampleFiles: ExampleFile[] = [
{
language: 'ts',
diff --git a/libs/docs/core/message-strip/message-strip-docs.module.ts b/libs/docs/core/message-strip/message-strip-docs.module.ts
index 7e0e681e5d6..575fc79aa25 100644
--- a/libs/docs/core/message-strip/message-strip-docs.module.ts
+++ b/libs/docs/core/message-strip/message-strip-docs.module.ts
@@ -8,6 +8,8 @@ import { MessageStripNoIconExampleComponent } from './examples/message-strip-noi
import { MessageStripWidthExampleComponent } from './examples/message-strip-width-example.component';
import { MessageStripHeaderComponent } from './message-strip-header/message-strip-header.component';
import { MessageStripAlertExampleComponent } from './examples/message-strip-alert-example.component';
+import { MessageStripIndicationColorsExampleComponent } from './examples/message-strip-indication-colors-example.component';
+import { MessageStripCustomIconExampleComponent } from './examples/message-strip-custom-icon-example.component';
import { MessageStripAutoDismissExampleComponent } from './examples/message-strip-auto-dismiss-example.component';
const routes: Routes = [
@@ -31,6 +33,9 @@ const routes: Routes = [
MessageStripNoIconExampleComponent,
MessageStripWidthExampleComponent,
MessageStripAlertExampleComponent,
+ MessageStripIndicationColorsExampleComponent,
+ MessageStripCustomIconExampleComponent,
+ MessageStripAlertExampleComponent,
MessageStripAutoDismissExampleComponent
],
providers: [currentComponentProvider('message-strip')]
diff --git a/libs/docs/core/schema/src/lib/slider.schema.ts b/libs/docs/core/schema/src/lib/slider.schema.ts
index 15265810d05..ce4772eba58 100644
--- a/libs/docs/core/schema/src/lib/slider.schema.ts
+++ b/libs/docs/core/schema/src/lib/slider.schema.ts
@@ -30,6 +30,9 @@ export const sliderSchema: any = {
},
disabled: {
type: 'boolean'
+ },
+ vertical: {
+ type: 'boolean'
}
}
}
diff --git a/libs/docs/core/slider/examples/index.ts b/libs/docs/core/slider/examples/index.ts
index 96f8cd46faa..4f5bf7079e2 100644
--- a/libs/docs/core/slider/examples/index.ts
+++ b/libs/docs/core/slider/examples/index.ts
@@ -6,6 +6,7 @@ import { SliderRangeExampleComponent } from './range/slider-range-example.compon
import { SliderTicksAndLabelsExampleComponent } from './ticks-and-labels/slider-ticks-and-labels-example.component';
import { SliderTooltipExampleComponent } from './tooltip/slider-tooltip-example.component';
import { SliderFormExampleComponent } from './form/slider-form-example.component';
+import { VerticalSliderExampleComponent } from './vertical/vertical-slider-example.component';
export const COMPONENTS = [
SliderBasicExampleComponent,
@@ -15,5 +16,6 @@ export const COMPONENTS = [
SliderCustomValuesExampleComponent,
SliderTooltipExampleComponent,
SliderCozyExampleComponent,
- SliderFormExampleComponent
+ SliderFormExampleComponent,
+ VerticalSliderExampleComponent
];
diff --git a/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.html b/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.html
new file mode 100644
index 00000000000..a5ea568a955
--- /dev/null
+++ b/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.html
@@ -0,0 +1,43 @@
+
+
+ To use Range Slider need to set [mode]
as range
(by default [mode]
as
+ single
)
+
+
+
+
+
+
+ Min value: {{ value[0] }}
+
+ Max value: {{ value[1] }}
+
+
+
+
+
+
Range slided with Custom Values.
+
+
+
+
+
+
+ Min value: {{ value2[0] | json }}
+
+ Max value: {{ value2[1] | json }}
+
+
diff --git a/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.ts b/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.ts
new file mode 100644
index 00000000000..0eafc3c08d3
--- /dev/null
+++ b/libs/docs/core/slider/examples/vertical/vertical-slider-example.component.ts
@@ -0,0 +1,27 @@
+import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
+import { SliderCustomValue } from '@fundamental-ngx/core/slider';
+
+@Component({
+ selector: 'fd-vertical-slider-example',
+ templateUrl: './vertical-slider-example.component.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class VerticalSliderExampleComponent {
+ value = [20, 70];
+
+ customValues: SliderCustomValue[] = [
+ { value: 1609452000000, label: 'Jan 1' },
+ { value: 1609538400000, label: 'Jan 2' },
+ { value: 1609624800000, label: 'Jan 3' },
+ { value: 1609711200000, label: 'Jan 4' },
+ { value: 1609797600000, label: 'Jan 5' },
+ { value: 1609884000000, label: 'Jan 6' },
+ { value: 1609970400000, label: 'Jan 7' },
+ { value: 1610056800000, label: 'Jan 8' },
+ { value: 1610143200000, label: 'Jan 9' },
+ { value: 1610229600000, label: 'Jan 10' }
+ ];
+
+ value2 = [this.customValues[4], this.customValues[6]];
+}
diff --git a/libs/docs/core/slider/slider-docs.component.html b/libs/docs/core/slider/slider-docs.component.html
index da05ee0570f..3851e29b925 100644
--- a/libs/docs/core/slider/slider-docs.component.html
+++ b/libs/docs/core/slider/slider-docs.component.html
@@ -46,6 +46,12 @@
+Vertical slider
+
+
+
+
+
Playground Area
Value: {{ value | json }}
diff --git a/libs/docs/core/slider/slider-docs.component.ts b/libs/docs/core/slider/slider-docs.component.ts
index b828014992f..ca2119b058d 100644
--- a/libs/docs/core/slider/slider-docs.component.ts
+++ b/libs/docs/core/slider/slider-docs.component.ts
@@ -38,7 +38,8 @@ export class SliderDocsComponent {
showTicks: true,
showTicksLabels: true,
mode: 'single',
- disabled: false
+ disabled: false,
+ vertical: false
}
};
diff --git a/libs/docs/core/toolbar/examples/toolbar-overflow-grouping-example.component.html b/libs/docs/core/toolbar/examples/toolbar-overflow-grouping-example.component.html
index 73fb1e66c08..878c7d21d90 100644
--- a/libs/docs/core/toolbar/examples/toolbar-overflow-grouping-example.component.html
+++ b/libs/docs/core/toolbar/examples/toolbar-overflow-grouping-example.component.html
@@ -1,4 +1,4 @@
-
+
diff --git a/libs/docs/core/toolbar/examples/toolbar-overflow-priority-example.component.html b/libs/docs/core/toolbar/examples/toolbar-overflow-priority-example.component.html
index 4958cee8f07..7a90412e66f 100644
--- a/libs/docs/core/toolbar/examples/toolbar-overflow-priority-example.component.html
+++ b/libs/docs/core/toolbar/examples/toolbar-overflow-priority-example.component.html
@@ -1,4 +1,4 @@
-
+
diff --git a/libs/docs/core/toolbar/examples/toolbar-separator-example.component.html b/libs/docs/core/toolbar/examples/toolbar-separator-example.component.html
index 520e51159a8..b87bbae7070 100644
--- a/libs/docs/core/toolbar/examples/toolbar-separator-example.component.html
+++ b/libs/docs/core/toolbar/examples/toolbar-separator-example.component.html
@@ -1,4 +1,4 @@
-
+
text
text
diff --git a/libs/docs/core/toolbar/examples/toolbar-size-example.component.html b/libs/docs/core/toolbar/examples/toolbar-size-example.component.html
index 585e67d50a8..a76094a7cc7 100644
--- a/libs/docs/core/toolbar/examples/toolbar-size-example.component.html
+++ b/libs/docs/core/toolbar/examples/toolbar-size-example.component.html
@@ -1,9 +1,9 @@
-
+
Text
-
+
Text
diff --git a/libs/docs/platform/approval-flow/e2e/approval-flow.e2e-spec.ts b/libs/docs/platform/approval-flow/e2e/approval-flow.e2e-spec.ts
index ee294a6d20b..0e124bfd1f6 100644
--- a/libs/docs/platform/approval-flow/e2e/approval-flow.e2e-spec.ts
+++ b/libs/docs/platform/approval-flow/e2e/approval-flow.e2e-spec.ts
@@ -272,6 +272,7 @@ describe('Approval flow', () => {
await click(afDefaultExample + editExampleButton);
await waitForElDisplayed(addNode);
await click(addNode, 1);
+ await waitForElDisplayed(detailsDialogParallelSerialSelect);
await click(detailsDialogParallelSerialSelect);
await click(detailsDialogParallelSerialSelectOption);
await click(detailsDialogUserTeamButton);
@@ -295,6 +296,7 @@ describe('Approval flow', () => {
(await browserIsFirefox()) ? await click(addNode, 2) : await click(addNode, 1);
await click(detailsDialogParallelSerialSelect);
await click(detailsDialogParallelSerialSelectOption, 1);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await waitForElDisplayed(detailsDialogTeamMemberCheckBox);
@@ -308,7 +310,7 @@ describe('Approval flow', () => {
await expect(approvalFlowNodeCountBefore).toBe(approvalFlowNodeCountAfter - 1);
});
- it('should be able to add node in serial using top bar action menu', async () => {
+ xit('should be able to add node in serial using top bar action menu', async () => {
await scrollIntoView(afDefaultExample);
const approvalFlowNodeCountBefore = await getElementArrayLength(afDefaultExample + approvalFlowNode);
await click(afDefaultExample + editExampleButton);
@@ -317,6 +319,7 @@ describe('Approval flow', () => {
await click(approvalFlowNodeCheckbox, 3);
await waitForElDisplayed(topActionButtons);
await click(topActionButtons);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await waitForElDisplayed(detailsDialogTeamMemberCheckBox);
@@ -337,6 +340,7 @@ describe('Approval flow', () => {
await click(approvalFlowNodeActionMenu, 3);
await waitForElDisplayed(approvalFlowNodeActionMenuItem);
await click(approvalFlowNodeActionMenuItem);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await waitForElDisplayed(detailsDialogTeamMemberCheckBox);
@@ -360,6 +364,7 @@ describe('Approval flow', () => {
await pause(500);
await waitForElDisplayed(approverOptionListItem);
await click(approverOptionListItem, 2);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await click(radioButton);
@@ -392,6 +397,7 @@ describe('Approval flow', () => {
await pause(500);
await waitForElDisplayed(approverOptionListItem);
await click(approverOptionListItem, 1);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await click(radioButton);
@@ -413,7 +419,7 @@ describe('Approval flow', () => {
}
});
- it('should be able to remove node by button', async () => {
+ xit('should be able to remove node by button', async () => {
await scrollIntoView(afDefaultExample);
await waitForElDisplayed(afDefaultExample + approvalFlowNode);
const approvalFlowNodeCountBefore = await getElementArrayLength(afDefaultExample + approvalFlowNode);
@@ -459,6 +465,7 @@ describe('Approval flow', () => {
await waitForElDisplayed(approvalFlowNodeActionMenuItem);
await click(approvalFlowNodeActionMenuItem);
await waitForElDisplayed(detailsDialog);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await waitForElDisplayed(dialogCheckbox);
@@ -479,6 +486,7 @@ describe('Approval flow', () => {
await waitForElDisplayed(approvalFlowNodeActionMenuItem);
await click(approvalFlowNodeActionMenuItem, 1);
await waitForElDisplayed(detailsDialog);
+ await waitForElDisplayed(detailsDialogUserTeamButton);
await click(detailsDialogUserTeamButton);
await pause(500);
await waitForElDisplayed(dialogCheckbox);
diff --git a/libs/docs/platform/checkbox-group/e2e/checkbox-group-page-content.ts b/libs/docs/platform/checkbox-group/e2e/checkbox-group-page-content.ts
index e464ddb3177..addf471b6a2 100644
--- a/libs/docs/platform/checkbox-group/e2e/checkbox-group-page-content.ts
+++ b/libs/docs/platform/checkbox-group/e2e/checkbox-group-page-content.ts
@@ -15,7 +15,6 @@ export const errorTooltipMessage = 'Value is required.';
export const graduationErrorMessage = 'Graduation is mandatory';
export const engineeringErrorMessage = 'Engineering is mandatory';
export const workExpierenceErrorMessage = 'Minimum 5 years of work experience required';
-export const markingsStyle = 'flex';
-export const seasonsOutputLabel = 'Seasons: ';
+export const markingsStyle = 'block';
export const currencies = ['AUD', 'INR', 'USD'];
export const purchasedItemsArr = ['coffee', 'pen', 'chair'];
diff --git a/libs/docs/platform/checkbox-group/e2e/checkbox-group.po.ts b/libs/docs/platform/checkbox-group/e2e/checkbox-group.po.ts
index bac171f96d9..b6d8aa310fb 100644
--- a/libs/docs/platform/checkbox-group/e2e/checkbox-group.po.ts
+++ b/libs/docs/platform/checkbox-group/e2e/checkbox-group.po.ts
@@ -5,30 +5,21 @@ export class CheckboxGroupPO extends PlatformBaseComponentPo {
stringValueCheckboxesArr = 'fdp-platform-checkbox-group-list input';
stringValueCheckboxLabelArr = 'fdp-platform-checkbox-group-list fd-checkbox label';
- stringValuecheckboxGroupLabelsArr = 'fdp-platform-checkbox-group-list .fd-form-label';
- stringValuecheckboxGroupsArr = 'fdp-platform-checkbox-group-list fd-form-group';
stringValueoutputLabelsArr = 'fdp-platform-checkbox-group-list > span';
- winterCheckbox = '.fd-checkbox__label[for=seasons0]';
+ winterCheckbox = '.fd-checkbox__label[for=seasons0] span.fd-checkbox__checkmark';
objectValueCheckboxesArr = 'fdp-platform-checkbox-group-list-object input';
objectValueCheckboxLabelArr = 'fdp-platform-checkbox-group-list-object fd-checkbox label';
- objectValuecheckboxGroupLabelsArr = 'fdp-platform-checkbox-group-list-object .fd-form-label';
- objectValuecheckboxGroupsArr = 'fdp-platform-checkbox-group-list-object fd-form-group';
objectValueoutputLabelsArr = 'fdp-platform-checkbox-group-list-object > span';
projectedValueCheckboxesArr = 'fdp-platform-checkbox-group-content-checkbox input';
projectedValueCheckboxLabelArr = 'fdp-platform-checkbox-group-content-checkbox fd-checkbox label';
- projectedValuecheckboxGroupLabelsArr = 'fdp-platform-checkbox-group-content-checkbox .fd-form-label';
- projectedValuecheckboxGroupsArr = 'fdp-platform-checkbox-group-content-checkbox fd-form-group';
projectValueoutputLabelsArr = 'fdp-platform-checkbox-group-content-checkbox > span';
formValidationCheckboxesArr = 'fdp-platform-checkbox-group-examples input';
formValidationCheckboxLabelArr = 'fdp-platform-checkbox-group-examples fd-checkbox label';
- formValidationcheckboxGroupLabelsArr = 'fdp-platform-checkbox-group-examples .fd-form-label';
- formValidationcheckboxGroupsArr = 'fdp-platform-checkbox-group-examples fd-form-group';
formvalidationValueoutputLabelsArr = 'fdp-platform-checkbox-group-examples > span';
errorTooltip = '.fd-form-message span';
- sectiontitle = 'fdp-platform-checkbox-group-examples h3';
async open(): Promise {
await super.open(this.url);
diff --git a/libs/docs/platform/checkbox/e2e/checkbox-page-contents.ts b/libs/docs/platform/checkbox/e2e/checkbox-page-contents.ts
index 0b16068560f..1265b8f32e8 100644
--- a/libs/docs/platform/checkbox/e2e/checkbox-page-contents.ts
+++ b/libs/docs/platform/checkbox/e2e/checkbox-page-contents.ts
@@ -2,4 +2,4 @@ export const disabledCheckboxTitle = 'It is a disabled checkbox';
export const a11yCheckboxAriaLabel = 'checkbox using aria-label';
export const a11yCheckboxAriaLabelledBy = 'checkboxLable';
export const checkboxErrorTooltip = 'Value is required';
-export const markingDisplayStyle = 'flex';
+export const markingDisplayStyle = 'block';
diff --git a/libs/docs/platform/checkbox/e2e/checkbox.po.ts b/libs/docs/platform/checkbox/e2e/checkbox.po.ts
index de555ec4772..865138f0f04 100644
--- a/libs/docs/platform/checkbox/e2e/checkbox.po.ts
+++ b/libs/docs/platform/checkbox/e2e/checkbox.po.ts
@@ -4,20 +4,14 @@ export class CheckboxPO extends PlatformBaseComponentPo {
url = '/checkbox';
binaryTempCheckbox = 'fdp-platform-binary-checkbox input';
- binaryTempCheckboxLable = 'fdp-platform-binary-checkbox label.fd-checkbox__label';
disabledBinaryCheckbox = 'fdp-platform-binary-checkbox input#disabled';
checkboxWithoutForm = 'fdp-platform-binary-checkbox-no-form input';
disabledCheckboxWithoutForm = 'fdp-platform-binary-checkbox-no-form fdp-checkbox:nth-of-type(5) input';
checkboxWithValue = 'fdp-platform-multiselect-checkbox input';
tristateCheckboxes = 'fdp-platform-tristate-checkbox input';
- tristateCheckboxParis = '.fd-checkbox__label[for=paris]';
- acceptAllCheckbox = 'fdp-platform-tristate-checkbox #acceptAll';
- termsAndConditionsCheckbox = 'fdp-platform-tristate-checkbox #termsAndConditions';
- marketingCheckbox = 'fdp-platform-tristate-checkbox #marketing';
- newsletterCheckbox = 'fdp-platform-tristate-checkbox #newsletter';
+ tristateCheckboxParis = '.fd-checkbox__label[for=paris] span.fd-checkbox__checkmark';
errorCheckboxes = 'fdp-platform-checkbox-error-handling .fd-checkbox__label';
presenceCheckbox = 'fdp-platform-checkbox-error-handling #presence';
- errorExampleTitle = 'fdp-platform-checkbox-error-handling h3';
submitBtn = 'fdp-platform-checkbox-error-handling button';
errorTooltip = '[type="error"] span';
accessibilityCheckboxes = 'fdp-platform-checkbox-a11y input';
diff --git a/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.html b/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.html
index 6bd0f9ee988..792a5f71471 100644
--- a/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.html
+++ b/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.html
@@ -6,6 +6,7 @@
@@ -17,6 +18,7 @@
type="email"
email
[(ngModel)]="templateFormValue.input2"
+ [errorTypes]="{ required: { heading: 'Required field empty', type: 'information' } }"
[required]="true"
name="input2"
>
diff --git a/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.ts b/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.ts
index e35019ca138..f36ab558011 100644
--- a/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.ts
+++ b/libs/docs/platform/message-popover/examples/default/message-popover-default-example.component.ts
@@ -1,4 +1,4 @@
-import { Component, ChangeDetectionStrategy, ViewChild } from '@angular/core';
+import { Component, ChangeDetectionStrategy, ViewChild, ViewEncapsulation } from '@angular/core';
import {
AbstractControl,
AsyncValidatorFn,
@@ -13,7 +13,8 @@ import { delay, Observable, of } from 'rxjs';
@Component({
selector: 'fdp-message-popover-default-example',
templateUrl: './message-popover-default-example.component.html',
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None
})
export class MessagePopoverDefaultExampleComponent {
templateFormValue = {
diff --git a/libs/docs/platform/message-popover/examples/form-generator/form-generator-component-example.component.ts b/libs/docs/platform/message-popover/examples/form-generator/form-generator-component-example.component.ts
index 51611b698b6..3004805f5fa 100644
--- a/libs/docs/platform/message-popover/examples/form-generator/form-generator-component-example.component.ts
+++ b/libs/docs/platform/message-popover/examples/form-generator/form-generator-component-example.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild } from '@angular/core';
+import { ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { Validators } from '@angular/forms';
import {
DATE_TIME_FORMATS,
@@ -24,6 +24,8 @@ export const dummyAwaitablePromise = (timeout = 200): Promise =>
@Component({
selector: 'fdp-message-popover-form-generator-example',
templateUrl: './form-generator-component-example.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None,
providers: [
// Note that this is usually provided in the root of your application.
// Due to the limit of this example we must provide it on this level.
diff --git a/libs/docs/platform/schema/schemas/slider-schema.ts b/libs/docs/platform/schema/schemas/slider-schema.ts
index baee51cc445..68e8be9459c 100644
--- a/libs/docs/platform/schema/schemas/slider-schema.ts
+++ b/libs/docs/platform/schema/schemas/slider-schema.ts
@@ -30,6 +30,9 @@ export const sliderSchema = {
},
disabled: {
type: 'boolean'
+ },
+ vertical: {
+ type: 'boolean'
}
}
}
diff --git a/libs/docs/platform/slider/slider-docs.component.html b/libs/docs/platform/slider/slider-docs.component.html
index 84fa83e7331..2aa691f02f7 100644
--- a/libs/docs/platform/slider/slider-docs.component.html
+++ b/libs/docs/platform/slider/slider-docs.component.html
@@ -61,6 +61,7 @@
[showTicksLabels]="data.properties.showTicksLabels"
[mode]="data.properties.mode"
[hideProgressBar]="data.properties.hideProgressBar"
+ [vertical]="data.properties.vertical"
>
Value: {{ value | json }}
diff --git a/libs/docs/platform/slider/slider-docs.component.ts b/libs/docs/platform/slider/slider-docs.component.ts
index 597b5919306..a5a20dc2141 100644
--- a/libs/docs/platform/slider/slider-docs.component.ts
+++ b/libs/docs/platform/slider/slider-docs.component.ts
@@ -37,7 +37,8 @@ export class PlatformSliderDocsComponent {
showTicks: true,
showTicksLabels: true,
mode: 'single',
- disabled: false
+ disabled: false,
+ vertical: false
}
};
diff --git a/libs/fn/src/lib/list/list-item/list-item.component.ts b/libs/fn/src/lib/list/list-item/list-item.component.ts
new file mode 100644
index 00000000000..cc0497002d2
--- /dev/null
+++ b/libs/fn/src/lib/list/list-item/list-item.component.ts
@@ -0,0 +1,112 @@
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ContentChild,
+ ElementRef,
+ HostBinding,
+ Inject,
+ Input,
+ Optional,
+ TemplateRef,
+ ViewEncapsulation
+} from '@angular/core';
+import {
+ FdkDisabledProvider,
+ FdkReadonlyProvider,
+ FocusableItemDirective,
+ SelectableItemToken,
+ SelectionService
+} from '@fundamental-ngx/cdk/utils';
+import {
+ FN_LIST_ACTIONS,
+ FN_LIST_BYLINE,
+ FN_LIST_CHECKBOX,
+ FN_LIST_ICON,
+ FN_LIST_POSTFIX,
+ FN_LIST_PREFIX,
+ FN_LIST_TITLE
+} from '../list.tokens';
+import { coerceBoolean, TemplateRefProviderToken } from '@fundamental-ngx/fn/utils';
+import { CheckboxContext } from '../list-item-checkbox.directive';
+import { ListComponent } from '../list/list.component';
+import { distinctUntilChanged, map, Observable } from 'rxjs';
+import { BooleanInput, coerceArray } from '@angular/cdk/coercion';
+
+@Component({
+ selector: 'fn-list-item, [fn-list-item]',
+ templateUrl: './list-item.component.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: {
+ '[class.fn-list__item]': 'true'
+ },
+ providers: [FdkDisabledProvider, FdkReadonlyProvider],
+ hostDirectives: [FocusableItemDirective]
+})
+export class ListItemComponent {
+ @Input()
+ @HostBinding('class.fn-list__item--info-bar')
+ @coerceBoolean
+ infoBar!: BooleanInput;
+
+ @ContentChild(FN_LIST_CHECKBOX)
+ checkboxProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_PREFIX)
+ prefixProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_ICON)
+ iconProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_TITLE)
+ titleProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_BYLINE)
+ bylineProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_ACTIONS)
+ actionsProvider?: TemplateRefProviderToken;
+ @ContentChild(FN_LIST_POSTFIX)
+ postfixProvider?: TemplateRefProviderToken;
+
+ checkboxContext$!: Observable;
+
+ readonly!: boolean;
+ disabled!: boolean;
+
+ constructor(
+ private _cd: ChangeDetectorRef,
+ @Optional() private _selectionService: SelectionService,
+ @Optional() @Inject(SelectableItemToken) private _selectableItem: SelectableItemToken,
+ @Optional() @Inject(ListComponent) private _listComponent: ListComponent | null,
+ private _elementRef: ElementRef,
+ private _disabledProvider: FdkDisabledProvider,
+ private _readonlyProvider: FdkReadonlyProvider
+ ) {
+ if (this._selectionService && this._selectableItem) {
+ this.checkboxContext$ = this._selectionService.value$.pipe(
+ map((v) => coerceArray(v)),
+ map((value: any[]) => value.includes(this._selectableItem.value)),
+ distinctUntilChanged(),
+ map((selected) => ({
+ $implicit: selected,
+ update: this.toggleItemSelection
+ }))
+ );
+ }
+ }
+
+ get byline(): boolean {
+ return !!this._listComponent?.byline;
+ }
+
+ $templateRef = (template: any): TemplateRef => template;
+
+ public elementRef(): ElementRef {
+ return this._elementRef;
+ }
+
+ private toggleItemSelection = (isSelected: boolean): void => {
+ if (isSelected) {
+ this._selectionService?.selectItem(this._selectableItem);
+ } else {
+ this._selectionService?.deselectItem(this._selectableItem);
+ }
+ };
+}
diff --git a/libs/platform/src/lib/form/checkbox-group/checkbox-group.component.ts b/libs/platform/src/lib/form/checkbox-group/checkbox-group.component.ts
index 2b06c83968c..3ca53f79cc1 100644
--- a/libs/platform/src/lib/form/checkbox-group/checkbox-group.component.ts
+++ b/libs/platform/src/lib/form/checkbox-group/checkbox-group.component.ts
@@ -17,7 +17,7 @@ import {
ViewChildren,
ViewEncapsulation
} from '@angular/core';
-import { ControlContainer, NgControl, NgForm } from '@angular/forms';
+import { ControlContainer, NgControl, NgForm, FormsModule } from '@angular/forms';
import { FD_FORM_FIELD, FD_FORM_FIELD_CONTROL } from '@fundamental-ngx/cdk/forms';
import { RangeSelector } from '@fundamental-ngx/cdk/utils';
import { SelectionModel } from '@angular/cdk/collections';
@@ -33,6 +33,8 @@ import {
PlatformFormFieldControl
} from '@fundamental-ngx/platform/shared';
import { CheckboxComponent } from '../checkbox/checkbox.component';
+import { NgIf, NgFor, NgTemplateOutlet } from '@angular/common';
+import { FormGroupModule } from '@fundamental-ngx/core/form';
/**
* Checkbox group implementation based on the
@@ -44,7 +46,9 @@ import { CheckboxComponent } from '../checkbox/checkbox.component';
templateUrl: './checkbox-group.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
- providers: [{ provide: FD_FORM_FIELD_CONTROL, useExisting: forwardRef(() => CheckboxGroupComponent), multi: true }]
+ providers: [{ provide: FD_FORM_FIELD_CONTROL, useExisting: forwardRef(() => CheckboxGroupComponent), multi: true }],
+ standalone: true,
+ imports: [FormGroupModule, NgIf, NgFor, NgTemplateOutlet, CheckboxComponent, FormsModule]
})
export class CheckboxGroupComponent extends InLineLayoutCollectionBaseInput {
/**
diff --git a/libs/platform/src/lib/form/checkbox-group/checkbox-group.module.ts b/libs/platform/src/lib/form/checkbox-group/checkbox-group.module.ts
index 60177afe36a..f6858260595 100644
--- a/libs/platform/src/lib/form/checkbox-group/checkbox-group.module.ts
+++ b/libs/platform/src/lib/form/checkbox-group/checkbox-group.module.ts
@@ -1,15 +1,11 @@
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { FormsModule } from '@angular/forms';
import { FormGroupModule } from '@fundamental-ngx/core/form';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
import { CheckboxGroupComponent } from './checkbox-group.component';
-import { PlatformCheckboxModule } from '../checkbox/checkbox.module';
@NgModule({
- imports: [CommonModule, PlatformCheckboxModule, FormsModule, FormGroupModule, ContentDensityModule],
- exports: [CheckboxGroupComponent, ContentDensityModule],
- declarations: [CheckboxGroupComponent]
+ imports: [FormGroupModule, ContentDensityModule, CheckboxGroupComponent],
+ exports: [CheckboxGroupComponent, ContentDensityModule]
})
export class PlatformCheckboxGroupModule {}
diff --git a/libs/platform/src/lib/form/checkbox/checkbox.component.html b/libs/platform/src/lib/form/checkbox/checkbox.component.html
index 9b1b163327e..e5bd2a84d3a 100644
--- a/libs/platform/src/lib/form/checkbox/checkbox.component.html
+++ b/libs/platform/src/lib/form/checkbox/checkbox.component.html
@@ -15,6 +15,7 @@
[ariaDescribedBy]="ariaDescribedBy"
[ngModel]="value"
[standalone]="standalone"
+ [displayOnly]="displayOnly"
(ngModelChange)="onModelChange($event)"
(focusChange)="_onFocusChanged($event)"
>
diff --git a/libs/platform/src/lib/form/checkbox/checkbox.component.ts b/libs/platform/src/lib/form/checkbox/checkbox.component.ts
index 86e656b6758..e10e69faa16 100644
--- a/libs/platform/src/lib/form/checkbox/checkbox.component.ts
+++ b/libs/platform/src/lib/form/checkbox/checkbox.component.ts
@@ -17,11 +17,13 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
-import { ControlContainer, NgControl, NgForm } from '@angular/forms';
+import { ControlContainer, NgControl, NgForm, FormsModule } from '@angular/forms';
import { FD_FORM_FIELD, FD_FORM_FIELD_CONTROL } from '@fundamental-ngx/cdk/forms';
import { FdCheckboxValues, CheckboxComponent as FdCheckboxComponent } from '@fundamental-ngx/core/checkbox';
import { BaseInput, PlatformFormFieldControl, PlatformFormField } from '@fundamental-ngx/platform/shared';
+import { CheckboxComponent as CoreCheckboxComponent } from '@fundamental-ngx/core/checkbox';
+import { FormItemModule } from '@fundamental-ngx/core/form';
/** Change event object emitted by Platform Checkbox. */
export class PlatformCheckboxChange {
@@ -41,7 +43,9 @@ let nextUniqueId = 0;
templateUrl: './checkbox.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
- providers: [{ provide: FD_FORM_FIELD_CONTROL, useExisting: forwardRef(() => CheckboxComponent), multi: true }]
+ providers: [{ provide: FD_FORM_FIELD_CONTROL, useExisting: forwardRef(() => CheckboxComponent), multi: true }],
+ standalone: true,
+ imports: [FormItemModule, CoreCheckboxComponent, FormsModule]
})
export class CheckboxComponent extends BaseInput implements AfterViewInit {
/**
@@ -84,6 +88,10 @@ export class CheckboxComponent extends BaseInput implements AfterViewInit {
@Input()
standalone = false;
+ /** Whether the checkbox should be rendered in display-only mode. */
+ @Input()
+ displayOnly = false;
+
/**
* Emitting checked event for non-form checkbox
*/
diff --git a/libs/platform/src/lib/form/checkbox/checkbox.module.ts b/libs/platform/src/lib/form/checkbox/checkbox.module.ts
index ac1dd07279a..64f85187157 100644
--- a/libs/platform/src/lib/form/checkbox/checkbox.module.ts
+++ b/libs/platform/src/lib/form/checkbox/checkbox.module.ts
@@ -1,16 +1,11 @@
-import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-
-import { CheckboxModule } from '@fundamental-ngx/core/checkbox';
import { PipeModule } from '@fundamental-ngx/cdk/utils';
import { CheckboxComponent } from './checkbox.component';
import { FormItemModule } from '@fundamental-ngx/core/form';
import { ContentDensityModule } from '@fundamental-ngx/core/content-density';
@NgModule({
- declarations: [CheckboxComponent],
- imports: [CommonModule, FormsModule, CheckboxModule, PipeModule, FormItemModule, ContentDensityModule],
+ imports: [PipeModule, FormItemModule, ContentDensityModule, CheckboxComponent],
exports: [CheckboxComponent, ContentDensityModule]
})
export class PlatformCheckboxModule {}
diff --git a/libs/platform/src/lib/message-popover/components/message-popover-form-wrapper/message-popover-form-wrapper.component.ts b/libs/platform/src/lib/message-popover/components/message-popover-form-wrapper/message-popover-form-wrapper.component.ts
index 7a23168bc3c..986b70d1392 100644
--- a/libs/platform/src/lib/message-popover/components/message-popover-form-wrapper/message-popover-form-wrapper.component.ts
+++ b/libs/platform/src/lib/message-popover/components/message-popover-form-wrapper/message-popover-form-wrapper.component.ts
@@ -10,8 +10,8 @@ import {
QueryList,
ViewEncapsulation
} from '@angular/core';
-import { AbstractControl, ControlContainer, FormGroup, FormGroupDirective, NgForm, NgModel } from '@angular/forms';
-import { FormStates } from '@fundamental-ngx/cdk/forms';
+import { AbstractControl, ControlContainer, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
+import { FD_FORM_FIELD_CONTROL, FormStates } from '@fundamental-ngx/cdk/forms';
import { Nullable } from '@fundamental-ngx/cdk/utils';
import {
FormFieldErrorDirectiveContext,
@@ -38,18 +38,16 @@ export type MessagePopoverForm = NgForm | FormGroupDirective;
templateUrl: './message-popover-form-wrapper.component.html',
exportAs: 'messagePopoverWrapper',
changeDetection: ChangeDetectionStrategy.OnPush,
- encapsulation: ViewEncapsulation.None
+ encapsulation: ViewEncapsulation.None,
+ standalone: true
})
export class MessagePopoverFormWrapperComponent implements MessagePopoverWrapper, AfterViewInit, OnDestroy {
/** @hidden */
@ContentChildren(ControlContainer, { descendants: true })
private readonly _projectedForm: QueryList;
- /** @hidden */
- @ContentChildren(NgModel, { descendants: true })
- private readonly _projectedFormItems!: QueryList;
/** @hidden */
- @ContentChildren(PlatformFormFieldControl, { descendants: true })
+ @ContentChildren(FD_FORM_FIELD_CONTROL, { descendants: true })
private readonly _projectedFormFieldControls!: QueryList;
/** @hidden */
@@ -121,9 +119,7 @@ export class MessagePopoverFormWrapperComponent implements MessagePopoverWrapper
if (this._ngForms.length > 0) {
return;
}
- this._ngForms = this._projectedForm?.toArray();
- this._startListeningForErrors();
- this._projectedForm?.changes.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => {
+ this._projectedForm?.changes.pipe(startWith(null), takeUntilDestroyed(this._destroyRef)).subscribe(() => {
this._ngForms = this._projectedForm.toArray();
this._startListeningForErrors();
});
@@ -248,11 +244,16 @@ export class MessagePopoverFormWrapperComponent implements MessagePopoverWrapper
.forEach((errorKey) => {
const errorObj = control.errors![errorKey];
- const errorTextModel = this._getConfigErrorModel(errorKey);
+ const errorTextModel = this._getConfigErrorModel(errorKey, field.errorTypes);
+ const errorConfig = field?.errorTypes ? field?.errorTypes[errorKey] : null;
+ const errorState =
+ errorConfig && this._isAdvancedError(errorConfig) && errorConfig.type
+ ? errorConfig.type
+ : 'error';
const error: MessagePopoverEntry = {
name: controlName,
type: errorTextModel.type,
- state: convertFormState('error'),
+ state: convertFormState(errorState),
fieldName: field?.label ?? '',
element: field?.elementRef,
heading: {
@@ -435,8 +436,12 @@ export class MessagePopoverFormWrapperComponent implements MessagePopoverWrapper
}
/** @hidden */
- private _getConfigErrorModel(errorKey: string): MessagePopoverErrorConfig {
- const configError = this._config.errors[errorKey];
+ private _getConfigErrorModel(
+ errorKey: string,
+ customErrorTypes?: MessagePopoverConfig['errors']
+ ): MessagePopoverErrorConfig {
+ const configError =
+ customErrorTypes && customErrorTypes[errorKey] ? customErrorTypes[errorKey] : this._config.errors[errorKey];
const isPlainError = !this._isAdvancedError(configError);
const errorType = isPlainError ? 'error' : configError.type;
const headingMessage = isPlainError ? configError : configError.heading;
diff --git a/libs/platform/src/lib/message-popover/components/message-view/message-view.component.ts b/libs/platform/src/lib/message-popover/components/message-view/message-view.component.ts
index 8a0dd77b357..c703283de50 100644
--- a/libs/platform/src/lib/message-popover/components/message-view/message-view.component.ts
+++ b/libs/platform/src/lib/message-popover/components/message-view/message-view.component.ts
@@ -1,5 +1,5 @@
import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
-import { DOCUMENT } from '@angular/common';
+import { DOCUMENT, NgTemplateOutlet, NgFor, NgIf } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
@@ -18,6 +18,12 @@ import { Nullable, resizeObservable, TabbableElementService } from '@fundamental
import { debounceTime } from 'rxjs';
import { MessagePopoverEntry, MessagePopoverErrorGroup } from '../../models/message-popover-entry.interface';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { LinkComponent } from '@fundamental-ngx/core/link';
+import { ObjectStatusModule } from '@fundamental-ngx/core/object-status';
+import { ListModule } from '@fundamental-ngx/core/list';
+import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';
+import { CdkScrollable } from '@angular/cdk/overlay';
@Component({
selector: 'fdp-message-view',
@@ -85,6 +91,18 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
animate('0.1s .1s cubic-bezier(0, 0, 0.2, 1)')
])
])
+ ],
+ standalone: true,
+ imports: [
+ NgTemplateOutlet,
+ CdkScrollable,
+ ScrollbarDirective,
+ ListModule,
+ NgFor,
+ NgIf,
+ ObjectStatusModule,
+ LinkComponent,
+ FdTranslatePipe
]
})
export class MessageViewComponent implements AfterViewInit {
diff --git a/libs/platform/src/lib/message-popover/directives/message-popover-form-item.directive.ts b/libs/platform/src/lib/message-popover/directives/message-popover-form-item.directive.ts
index 3438e8498bf..405ce1f8de4 100644
--- a/libs/platform/src/lib/message-popover/directives/message-popover-form-item.directive.ts
+++ b/libs/platform/src/lib/message-popover/directives/message-popover-form-item.directive.ts
@@ -1,14 +1,20 @@
import { Directive, ElementRef, Input, Optional } from '@angular/core';
import { NgControl } from '@angular/forms';
+import { MessagePopoverConfig } from '../default-config';
@Directive({
- selector: '[fdpMessagePopoverFormItem]'
+ selector: '[fdpMessagePopoverFormItem]',
+ standalone: true
})
export class MessagePopoverFormItemDirective {
/** Form item name. */
@Input('fdpMessagePopoverFormItem')
label: string;
+ /** Error type definition. */
+ @Input()
+ errorTypes: MessagePopoverConfig['errors'];
+
/** @hidden */
- constructor(public elementRef: ElementRef, @Optional() public control: NgControl) {}
+ constructor(public readonly elementRef: ElementRef, @Optional() public readonly control: NgControl) {}
}
diff --git a/libs/platform/src/lib/message-popover/message-popover.component.html b/libs/platform/src/lib/message-popover/message-popover.component.html
index d94d3cace7b..8ab75237bf7 100644
--- a/libs/platform/src/lib/message-popover/message-popover.component.html
+++ b/libs/platform/src/lib/message-popover/message-popover.component.html
@@ -38,7 +38,7 @@
{
beforeEach(async () => {
await TestBed.configureTestingModule({
- imports: [PopoverModule, I18nModule],
- declarations: [MessagePopoverComponent],
+ imports: [MessagePopoverComponent, NoopAnimationsModule],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
diff --git a/libs/platform/src/lib/message-popover/message-popover.component.ts b/libs/platform/src/lib/message-popover/message-popover.component.ts
index 0df8474297f..518e1a1efaa 100644
--- a/libs/platform/src/lib/message-popover/message-popover.component.ts
+++ b/libs/platform/src/lib/message-popover/message-popover.component.ts
@@ -10,7 +10,6 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
-import { ObjectStatus } from '@fundamental-ngx/core/object-status';
import { PopoverComponent } from '@fundamental-ngx/core/popover';
import { FormStates } from '@fundamental-ngx/cdk/forms';
import { Nullable } from '@fundamental-ngx/cdk/utils';
@@ -22,16 +21,41 @@ import {
MessagePopoverErrorGroup
} from './models/message-popover-entry.interface';
import { MessagePopoverWrapper } from './models/message-popover-wrapper.interface';
-import { convertFormState } from './utils';
-import { MessagePopover } from './models/message-popover.interface';
+import { convertFormState, convertFormStateToMessagePopoverState } from './utils';
+import { MessagePopover, MessagePopoverState } from './models/message-popover.interface';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { FdTranslatePipe } from '@fundamental-ngx/i18n';
+import { MessageViewComponent } from './components/message-view/message-view.component';
+import { InitialFocusDirective } from '@fundamental-ngx/cdk/utils';
+import { ObjectStatusModule } from '@fundamental-ngx/core/object-status';
+import { FormsModule } from '@angular/forms';
+import { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';
+import { BarModule } from '@fundamental-ngx/core/bar';
+import { ButtonModule } from '@fundamental-ngx/core/button';
+import { PopoverModule } from '@fundamental-ngx/core/popover';
+import { NgIf, NgClass, NgFor } from '@angular/common';
@Component({
selector: 'fdp-message-popover',
templateUrl: './message-popover.component.html',
styleUrls: ['./message-popover.component.scss'],
encapsulation: ViewEncapsulation.None,
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [
+ NgIf,
+ PopoverModule,
+ ButtonModule,
+ NgClass,
+ BarModule,
+ SegmentedButtonModule,
+ FormsModule,
+ NgFor,
+ ObjectStatusModule,
+ InitialFocusDirective,
+ MessageViewComponent,
+ FdTranslatePipe
+ ]
})
export class MessagePopoverComponent implements MessagePopover, OnInit {
/** @hidden */
@@ -65,7 +89,7 @@ export class MessagePopoverComponent implements MessagePopover, OnInit {
_priorityFormState: FormStates;
/** @hidden */
- _priorityState: ObjectStatus;
+ _priorityState: MessagePopoverState;
/** @hidden */
_filteredErrors: MessagePopoverErrorGroup[] = [];
@@ -96,7 +120,7 @@ export class MessagePopoverComponent implements MessagePopover, OnInit {
});
this._priorityFormState = getFormState(errorTypes);
- this._priorityState = convertFormState(this._priorityFormState);
+ this._priorityState = convertFormStateToMessagePopoverState(this._priorityFormState);
this._priorityStateItemsCount = countedErrors[this._priorityFormState];
this._filterErrors();
diff --git a/libs/platform/src/lib/message-popover/models/message-popover.interface.ts b/libs/platform/src/lib/message-popover/models/message-popover.interface.ts
index 8ae1c1bd450..420f0b3452b 100644
--- a/libs/platform/src/lib/message-popover/models/message-popover.interface.ts
+++ b/libs/platform/src/lib/message-popover/models/message-popover.interface.ts
@@ -1,5 +1,12 @@
import { EventEmitter } from '@angular/core';
import { MessagePopoverEntry } from './message-popover-entry.interface';
+import { ObjectStatus } from '@fundamental-ngx/core/object-status';
+
+export type MessagePopoverState =
+ | Omit
+ | 'information'
+ | 'success'
+ | 'neutral';
export interface MessagePopover {
focusItem: EventEmitter;
diff --git a/libs/platform/src/lib/message-popover/platform-message-popover.module.ts b/libs/platform/src/lib/message-popover/platform-message-popover.module.ts
index ae4c950f238..6afa18379ed 100644
--- a/libs/platform/src/lib/message-popover/platform-message-popover.module.ts
+++ b/libs/platform/src/lib/message-popover/platform-message-popover.module.ts
@@ -1,19 +1,4 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { FormsModule } from '@angular/forms';
-import { BarModule } from '@fundamental-ngx/core/bar';
-import { ButtonModule } from '@fundamental-ngx/core/button';
-import { IconModule } from '@fundamental-ngx/core/icon';
-import { LinkModule } from '@fundamental-ngx/core/link';
-import { ListModule } from '@fundamental-ngx/core/list';
-import { ObjectStatusModule } from '@fundamental-ngx/core/object-status';
-import { PopoverModule } from '@fundamental-ngx/core/popover';
-import { ScrollbarModule } from '@fundamental-ngx/core/scrollbar';
-import { SegmentedButtonModule } from '@fundamental-ngx/core/segmented-button';
-import { InitialFocusModule } from '@fundamental-ngx/cdk/utils';
-import { I18nModule } from '@fundamental-ngx/i18n';
-import { PlatformButtonModule } from '@fundamental-ngx/platform/button';
-import { PlatformObjectStatusModule } from '@fundamental-ngx/platform/object-status';
import { mergeWith } from 'lodash-es';
import { FDP_MESSAGE_POPOVER_CONFIG, FDP_MESSAGE_POPOVER_DEFAULT_CONFIG, MessagePopoverConfig } from './default-config';
import { MessagePopoverComponent } from './message-popover.component';
@@ -23,29 +8,12 @@ import { MessagePopoverFormItemDirective } from './directives/message-popover-fo
@NgModule({
imports: [
- CommonModule,
- IconModule,
- PopoverModule,
- BarModule,
- ListModule,
- SegmentedButtonModule,
- FormsModule,
- ButtonModule,
- ObjectStatusModule,
- ScrollbarModule,
- LinkModule,
- PlatformObjectStatusModule,
- PlatformButtonModule,
- I18nModule,
- InitialFocusModule
- ],
- exports: [
MessagePopoverComponent,
MessagePopoverFormWrapperComponent,
MessageViewComponent,
MessagePopoverFormItemDirective
],
- declarations: [
+ exports: [
MessagePopoverComponent,
MessagePopoverFormWrapperComponent,
MessageViewComponent,
diff --git a/libs/platform/src/lib/message-popover/utils.ts b/libs/platform/src/lib/message-popover/utils.ts
index 7712f1f2c37..fc21a40f570 100644
--- a/libs/platform/src/lib/message-popover/utils.ts
+++ b/libs/platform/src/lib/message-popover/utils.ts
@@ -1,5 +1,24 @@
import { ObjectStatus } from '@fundamental-ngx/core/object-status';
import { FormStates } from '@fundamental-ngx/cdk/forms';
+import { MessagePopoverState } from './models/message-popover.interface';
+
+/**
+ * Converts Object Status into Message Popover State
+ * @param status Object status
+ * @returns Message Popover State.
+ */
+export function convertFormStateToMessagePopoverState(state: FormStates): MessagePopoverState {
+ switch (state) {
+ case 'error':
+ return 'negative';
+ case 'warning':
+ return 'critical';
+ case 'default':
+ return 'neutral';
+ default:
+ return state;
+ }
+}
/**
* Converts Form State into Object status type.
diff --git a/libs/platform/src/lib/search-field/search-field.component.html b/libs/platform/src/lib/search-field/search-field.component.html
index 7b19a2c74f8..2da2600843a 100644
--- a/libs/platform/src/lib/search-field/search-field.component.html
+++ b/libs/platform/src/lib/search-field/search-field.component.html
@@ -124,6 +124,7 @@
+
diff --git a/libs/platform/src/lib/slider/jest.config.ts b/libs/platform/src/lib/slider/jest.config.ts
new file mode 100644
index 00000000000..b768606ca3f
--- /dev/null
+++ b/libs/platform/src/lib/slider/jest.config.ts
@@ -0,0 +1,9 @@
+import baseConfig from '../../../../../jest.config.base';
+
+export default {
+ ...baseConfig,
+ displayName: 'platform-slider',
+ preset: '../../../../../jest.preset.js',
+ setupFilesAfterEnv: ['