Skip to content

Commit 831e597

Browse files
committed
Merge branch 'v4' into v4-feat-placeholder
2 parents 19a5583 + 27b8e08 commit 831e597

17 files changed

+1534
-426
lines changed

package-lock.json

Lines changed: 1243 additions & 363 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "coreui-angular-dev",
3-
"version": "4.0.0-alpha.9",
3+
"version": "4.0.0-alpha.13",
44
"description": "CoreUI Components Library for Angular",
55
"license": "MIT",
66
"author": "The CoreUI Team (https://github.com/orgs/coreui/people)",
@@ -39,7 +39,7 @@
3939
"@coreui/chartjs": "^3.0.0",
4040
"@coreui/icons-angular": "^3.0.0-alpha.4",
4141
"@popperjs/core": "^2.11.0",
42-
"chart.js": "~3.6.0",
42+
"chart.js": "~3.7.1",
4343
"rxjs": "~7.5.0",
4444
"tslib": "^2.3.0",
4545
"zone.js": "~0.11.4"

projects/coreui-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@coreui/angular",
3-
"version": "4.0.0-alpha.9",
3+
"version": "4.0.0-alpha.13",
44
"description": "CoreUI for Angular UI components library",
55
"license": "MIT",
66
"homepage": "https://coreui.io/angular",

projects/coreui-angular/src/lib/accordion/accordion-item/accordion-item.component.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<ng-container>
22
<div class="accordion-header">
3-
<ng-container *ngTemplateOutlet="templates?.accordionHeaderTemplate || defaultAccordionHeaderTemplate; context: itemContext"></ng-container>
3+
<ng-container *ngTemplateOutlet="templates['accordionHeaderTemplate'] || defaultAccordionHeaderTemplate; context: itemContext"></ng-container>
44
</div>
5-
<div class="accordion-collapse" cCollapse [visible]="visible" [attr.aria-expanded]="open" [id]="contentId">
6-
<ng-container *ngTemplateOutlet="templates?.accordionBodyTemplate || defaultAccordionBodyTemplate; context: itemContext"></ng-container>
5+
<div class="accordion-collapse" cCollapse [visible]="visible" [attr.aria-expanded]="visible" [id]="contentId">
6+
<ng-container *ngTemplateOutlet="templates['accordionBodyTemplate'] || defaultAccordionBodyTemplate; context: itemContext"></ng-container>
77
</div>
88
</ng-container>
99

1010
<ng-template #defaultAccordionHeaderTemplate>
11-
<button cAccordionButton [collapsed]="!open" [attr.aria-controls]="contentId" (click)="toggleItem()">
11+
<button cAccordionButton [collapsed]="!visible" [attr.aria-controls]="contentId" (click)="toggleItem()">
1212
<ng-container
13-
*ngTemplateOutlet="templates?.accordionHeader || defaultAccordionHeaderContentTemplate; context: itemContext">
13+
*ngTemplateOutlet="templates['accordionHeader'] || defaultAccordionHeaderContentTemplate; context: itemContext">
1414
</ng-container>
1515
</button>
1616
</ng-template>
@@ -22,7 +22,7 @@
2222
<ng-template #defaultAccordionBodyTemplate>
2323
<div class="accordion-body">
2424
<ng-container
25-
*ngTemplateOutlet="templates?.accordionBody || defaultAccordionBodyContentTemplate; context: itemContext">
25+
*ngTemplateOutlet="templates['accordionBody'] || defaultAccordionBodyContentTemplate; context: itemContext">
2626
</ng-container>
2727
</div>
2828
</ng-template>

projects/coreui-angular/src/lib/accordion/accordion-item/accordion-item.component.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010

1111
import { AccordionService } from '../accordion.service';
1212
import { TemplateIdDirective } from '../../shared';
13+
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
1314

1415
let nextId = 0;
1516

@@ -20,15 +21,30 @@ let nextId = 0;
2021
exportAs: 'cAccordionItem',
2122
})
2223
export class AccordionItemComponent implements OnInit, OnDestroy, AfterContentInit {
24+
25+
static ngAcceptInputType_visible: BooleanInput;
26+
2327
/**
2428
* Toggle an accordion item programmatically
2529
* @type boolean
2630
* @default false
2731
*/
28-
@Input() visible: boolean = false;
29-
@Input() set open(value: boolean) {
32+
@Input()
33+
set visible(value: boolean){
34+
this._visible = coerceBooleanProperty(value);
35+
}
36+
get visible() {
37+
return this._visible;
38+
}
39+
private _visible: boolean = false;
40+
41+
@Input()
42+
set open(value: boolean) {
3043
console.warn('c-accordion-item "open" prop is deprecated, use "visible" prop instead.')
31-
this.visible = value ?? false;
44+
this.visible = value || this.visible;
45+
}
46+
get open() {
47+
return this.visible;
3248
}
3349

3450
@HostBinding('class')
@@ -56,7 +72,7 @@ export class AccordionItemComponent implements OnInit, OnDestroy, AfterContentIn
5672
}
5773

5874
toggleItem(): void {
59-
this.accordionService.toggelItem(this);
75+
this.accordionService.toggleItem(this);
6076
}
6177

6278
ngAfterContentInit(): void {

projects/coreui-angular/src/lib/accordion/accordion.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class AccordionService {
2020
}
2121
}
2222

23-
toggelItem(item: AccordionItemComponent): void {
23+
toggleItem(item: AccordionItemComponent): void {
2424
item.visible = !item.visible;
2525
this.closeOtherItems(item);
2626
}

projects/coreui-angular/src/lib/alert/alert.component.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ export class AlertComponent implements AfterContentInit {
8383
}
8484
private _fade = false;
8585

86+
/**
87+
* Default role for alert. [docs]
88+
* @type string
89+
* @default 'alert'
90+
*/
91+
@HostBinding('attr.role')
92+
@Input() role = 'alert';
93+
8694
/**
8795
* Set the alert variant to a solid.
8896
* @type string

projects/coreui-angular/src/lib/carousel/carousel-item/carousel-item.component.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
88
@Component({
99
selector: 'c-carousel-item',
1010
templateUrl: './carousel-item.component.html',
11-
styleUrls: ['./carousel-item.component.scss'],
11+
styleUrls: ['./carousel-item.component.scss']
1212
})
1313
export class CarouselItemComponent implements OnDestroy, AfterViewInit {
1414

1515
static ngAcceptInputType_active: BooleanInput;
16-
private _active = false;
1716

1817
index?: number;
1918
private carouselIndexSubscription?: Subscription;
@@ -29,12 +28,20 @@ export class CarouselItemComponent implements OnDestroy, AfterViewInit {
2928
get active(): boolean {
3029
return this._active;
3130
}
31+
private _active = false;
32+
33+
/**
34+
* Time delay before cycling to next item. If -1, uses carousel interval value.
35+
* @type number
36+
* @default -1
37+
*/
38+
@Input() interval: number = -1;
3239

3340
@HostBinding('class')
3441
get hostClasses(): any {
3542
return {
3643
'carousel-item': true,
37-
active: this.active,
44+
active: this.active
3845
};
3946
}
4047

projects/coreui-angular/src/lib/carousel/carousel-state.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ export class CarouselState {
2424
const nextState = { ...this._state, ...state };
2525
this._state = nextState;
2626
if (prevState.activeItemIndex !== nextState.activeItemIndex) {
27-
this.carouselService.setIndex({active: nextState.activeItemIndex});
27+
const activeItemIndex = this.state.activeItemIndex || 0;
28+
const itemInterval = this.state.items && this.state.items[activeItemIndex]?.interval || -1;
29+
this.carouselService.setIndex({
30+
active: nextState.activeItemIndex,
31+
interval: itemInterval,
32+
lastItemIndex: (nextState.items?.length ?? 0) - 1
33+
});
2834
}
2935
}
3036

@@ -35,7 +41,7 @@ export class CarouselState {
3541
item.index = i;
3642
});
3743
this.state = {
38-
items: itemsArray,
44+
items: itemsArray
3945
};
4046
} else {
4147
this.reset();
@@ -46,7 +52,7 @@ export class CarouselState {
4652
this.carouselService.setIndex(nextIndex);
4753
}
4854

49-
direction(direction: 'next' | 'prev' = 'next' ): number {
55+
direction(direction: 'next' | 'prev' = 'next'): number {
5056
this.state = { direction };
5157
const { activeItemIndex = -1, items } = this.state;
5258
const itemsCount = items?.length ?? 0;

projects/coreui-angular/src/lib/carousel/carousel.service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { BehaviorSubject } from 'rxjs';
33

44
export interface ICarouselIndex {
55
active?: number;
6+
interval?: number;
7+
lastItemIndex?: number;
68
}
79

810
@Injectable()

projects/coreui-angular/src/lib/carousel/carousel/carousel.component.ts

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {
22
AfterContentInit,
33
Component,
4+
ElementRef,
45
EventEmitter,
56
HostBinding,
6-
HostListener,
77
Inject,
88
Input,
99
OnDestroy,
@@ -12,15 +12,19 @@ import {
1212
} from '@angular/core';
1313
import { Subscription } from 'rxjs';
1414

15+
import { IntersectionService } from '../../services/intersection.service';
16+
import { IListenersConfig, ListenersService } from '../../services/listeners.service';
17+
1518
import { CarouselState } from '../carousel-state';
1619
import { CarouselService } from '../carousel.service';
1720
import { CarouselConfig } from '../carousel.config';
21+
import { Triggers } from '../../coreui.types';
1822

1923
@Component({
2024
selector: 'c-carousel',
21-
template: `<ng-content></ng-content>`,
25+
template: '<ng-content></ng-content>',
2226
styleUrls: ['./carousel.component.scss'],
23-
providers: [CarouselService, CarouselState, CarouselConfig]
27+
providers: [CarouselService, CarouselState, CarouselConfig, IntersectionService, ListenersService]
2428
})
2529
export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
2630
/**
@@ -46,14 +50,26 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
4650
/**
4751
* The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle.
4852
* @type number
53+
* @default 0
4954
*/
5055
@Input() interval = 0;
56+
/**
57+
* Sets which event handlers you’d like provided to your pause prop. You can specify one trigger or an array of them.
58+
* @type {'hover' | 'focus' | 'click'}
59+
*/
60+
@Input() pause: Triggers | Triggers[] | false = 'hover';
5161
/**
5262
* Set type of the transition.
5363
* @type {'slide' | 'crossfade'}
5464
* @default 'slide'
5565
*/
5666
@Input() transition: 'slide' | 'crossfade' = 'slide';
67+
/**
68+
* Set whether the carousel should cycle continuously or have hard stops.
69+
* @type boolean
70+
* @default true
71+
*/
72+
@Input() wrap = true;
5773
/**
5874
* Event emitted on carousel item change. [docs]
5975
* @type number
@@ -72,23 +88,16 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
7288

7389
private carouselIndexSubscription?: Subscription;
7490
private timerId!: any;
75-
76-
@HostListener('mouseenter', ['$event'])
77-
@HostListener('mousedown', ['$event'])
78-
public onMouseenter($event: MouseEvent): void {
79-
this.resetTimer();
80-
}
81-
82-
@HostListener('mouseleave', ['$event'])
83-
@HostListener('mouseup', ['$event'])
84-
public onMouseleave($event: MouseEvent): void {
85-
this.setTimer();
86-
}
91+
private intersectingSubscription?: Subscription;
92+
private activeItemInterval = 0;
8793

8894
constructor(
8995
@Inject(CarouselConfig) private config: CarouselConfig,
96+
private hostElement: ElementRef,
9097
private carouselService: CarouselService,
91-
private carouselState: CarouselState
98+
private carouselState: CarouselState,
99+
private intersectionService: IntersectionService,
100+
private listenersService: ListenersService
92101
) {
93102
Object.assign(this, config);
94103
}
@@ -98,21 +107,52 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
98107
}
99108

100109
ngOnDestroy(): void {
110+
this.clearListeners();
101111
this.carouselStateSubscribe(false);
112+
this.intersectionServiceSubscribe(false);
102113
}
103114

104115
ngAfterContentInit(): void {
116+
this.intersectionService.createIntersectionObserver(this.hostElement);
117+
this.intersectionServiceSubscribe();
105118
this.carouselState.state = { activeItemIndex: this.activeIndex, animate: this.animate };
106-
this.setTimer();
119+
this.setListeners();
107120
}
108121

122+
private setListeners(): void {
123+
const config: IListenersConfig = {
124+
hostElement: this.hostElement,
125+
trigger: this.pause || [],
126+
callbackOff: () => {
127+
this.setTimer();
128+
},
129+
callbackOn: () => {
130+
this.resetTimer();
131+
}
132+
};
133+
this.listenersService.setListeners(config);
134+
}
135+
136+
private clearListeners(): void {
137+
this.listenersService.clearListeners();
138+
}
139+
140+
set visible(value) {
141+
this._visible = value;
142+
}
143+
get visible() {
144+
return this._visible;
145+
}
146+
private _visible: boolean = true;
147+
109148
setTimer(): void {
149+
const interval = this.activeItemInterval || 0;
110150
this.resetTimer();
111-
if (this.interval > 0) {
151+
if (interval > 0) {
112152
this.timerId = setTimeout(() => {
113153
const nextIndex = this.carouselState.direction(this.direction);
114154
this.carouselState.state = { activeItemIndex: nextIndex };
115-
}, this.interval);
155+
}, interval);
116156
}
117157
}
118158

@@ -122,13 +162,27 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
122162

123163
private carouselStateSubscribe(subscribe: boolean = true): void {
124164
if (subscribe) {
125-
this.carouselIndexSubscription = this.carouselService.carouselIndex$.subscribe((nextIndex) => {
126-
if ('active' in nextIndex) {
127-
this.setTimer();
165+
this.carouselIndexSubscription = this.carouselService.carouselIndex$.subscribe((nextItem) => {
166+
if ('active' in nextItem) {
167+
this.itemChange.emit(nextItem.active);
128168
}
169+
this.activeItemInterval = typeof nextItem.interval === 'number' && nextItem.interval > -1 ? nextItem.interval : this.interval;
170+
const isLastItem = ((nextItem.active === nextItem.lastItemIndex) && this.direction === 'next') || ((nextItem.active === 0) && this.direction === 'prev');
171+
!this.wrap && isLastItem ? this.resetTimer() : this.setTimer();
129172
});
130173
} else {
131174
this.carouselIndexSubscription?.unsubscribe();
132175
}
133176
}
177+
178+
private intersectionServiceSubscribe(subscribe: boolean = true): void {
179+
if (subscribe) {
180+
this.intersectingSubscription = this.intersectionService.intersecting$.subscribe(isIntersecting => {
181+
this.visible = isIntersecting;
182+
isIntersecting ? this.setTimer() : this.resetTimer();
183+
});
184+
} else {
185+
this.intersectingSubscription?.unsubscribe();
186+
}
187+
}
134188
}

0 commit comments

Comments
 (0)