Skip to content

Commit 0f4df7b

Browse files
feat: Mediaco Listview in both table and gallery (#603)
* feat: Mediaco Listview in both table and gallery * chore: update @pega/angular-sdk-components and @pega/angular-sdk-overrides to version 0.25.3 --------- Co-authored-by: Siva Rama Krishna <[email protected]>
1 parent a72cd03 commit 0f4df7b

17 files changed

+947
-14
lines changed

package-lock.json

Lines changed: 8 additions & 4 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
@@ -61,7 +61,7 @@
6161
"@angular/platform-browser": "^19.2.14",
6262
"@angular/platform-browser-dynamic": "^19.2.14",
6363
"@angular/router": "^19.2.14",
64-
"@pega/angular-sdk-components": "~0.25.1",
64+
"@pega/angular-sdk-components": "~0.25.3",
6565
"@pega/auth": "~0.2.33",
6666
"@pega/cosmos-react-condition-builder": "^7.0.4",
6767
"@pega/cosmos-react-core": "^7.0.4",
@@ -86,7 +86,7 @@
8686
"@angular/compiler-cli": "^19.2.14",
8787
"@angular/language-service": "^19.2.14",
8888
"@chromatic-com/storybook": "^3.2.7",
89-
"@pega/angular-sdk-overrides": "~0.25.1",
89+
"@pega/angular-sdk-overrides": "~0.25.3",
9090
"@pega/configs": "^0.16.3",
9191
"@pega/constellationjs": "~0.25.1",
9292
"@pega/dx-component-builder-sdk": "~24.2.14",

src/app/_samples/mediaco/components/banner/banner.component.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.psdk-grid-filter-1 {
22
display: grid;
3-
grid-template-columns: repeat(3, minmax(0, 1fr));
3+
grid-template-columns: repeat(2, minmax(0, 1fr));
44
column-gap: calc(2 * 0.5rem);
55
row-gap: calc(2 * 0.5rem);
66
align-items: start;
@@ -21,6 +21,10 @@
2121
column-gap: calc(2 * 0.5rem);
2222
row-gap: calc(2 * 0.5rem);
2323
align-items: start;
24+
25+
& > *:nth-child(2) {
26+
min-width: 0;
27+
}
2428
}
2529

2630
.background-image-style {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<div class="carousel-host-container">
2+
<div class="carousel-frame">
3+
<div class="carousel-scroll-area" #scrollContainer>
4+
<div class="card-wrapper" *ngFor="let item of displayItems" #cardItem>
5+
<mat-card class="inner-material-card">
6+
<img [src]="item.img" alt="Card Image" />
7+
<div class="card-overlay">
8+
<h3>{{ item.title }}</h3>
9+
</div>
10+
</mat-card>
11+
</div>
12+
</div>
13+
</div>
14+
<div class="carousel-footer"></div>
15+
</div>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
:host {
2+
display: block;
3+
width: 100%;
4+
min-width: 0;
5+
max-width: 100vw;
6+
overflow: hidden;
7+
contain: content;
8+
}
9+
10+
.carousel-host-container {
11+
width: 100%;
12+
position: relative;
13+
overflow: hidden;
14+
display: flex;
15+
flex-direction: column;
16+
}
17+
18+
.header {
19+
display: flex;
20+
justify-content: space-between;
21+
align-items: center;
22+
margin-bottom: 10px;
23+
padding: 0 16px;
24+
25+
h2 {
26+
margin: 0;
27+
font-size: 20px;
28+
font-weight: 500;
29+
}
30+
}
31+
32+
.carousel-scroll-area {
33+
display: flex;
34+
align-items: center;
35+
width: 100%;
36+
max-width: 100%;
37+
height: 400px;
38+
padding: 0;
39+
overflow-x: auto;
40+
overflow-y: hidden;
41+
scroll-behavior: auto;
42+
box-sizing: border-box;
43+
box-sizing: border-box;
44+
45+
&::-webkit-scrollbar {
46+
display: none;
47+
}
48+
scrollbar-width: none;
49+
}
50+
51+
.card-wrapper {
52+
flex: 0 0 200px;
53+
height: 350px;
54+
margin: 0 10px;
55+
transition:
56+
flex-basis 0.1s linear,
57+
min-width 0.1s linear;
58+
will-change: flex-basis, min-width;
59+
min-width: 0;
60+
}
61+
62+
.inner-material-card {
63+
width: 100%;
64+
height: 100%;
65+
padding: 0 !important;
66+
overflow: hidden;
67+
position: relative;
68+
background: #000;
69+
border-radius: 8px;
70+
71+
img {
72+
width: 100%;
73+
height: 100%;
74+
object-fit: cover;
75+
display: block;
76+
}
77+
78+
.card-overlay {
79+
position: absolute;
80+
bottom: 0;
81+
left: 0;
82+
width: 100%;
83+
padding: 16px;
84+
background: linear-gradient(transparent, rgba(0, 0, 0, 0.9));
85+
color: white;
86+
87+
h3 {
88+
margin: 0;
89+
font-size: 16px;
90+
white-space: nowrap;
91+
overflow: hidden;
92+
text-overflow: ellipsis;
93+
}
94+
}
95+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import {
2+
Component,
3+
ElementRef,
4+
ViewChildren,
5+
QueryList,
6+
AfterViewInit,
7+
OnDestroy,
8+
NgZone,
9+
Input,
10+
OnChanges,
11+
SimpleChanges,
12+
ViewChild
13+
} from '@angular/core';
14+
import { CommonModule } from '@angular/common';
15+
import { MatButtonModule } from '@angular/material/button';
16+
import { MatCardModule } from '@angular/material/card';
17+
import { MatDialog } from '@angular/material/dialog';
18+
import { MatIconModule } from '@angular/material/icon';
19+
// import { GalleryGridComponent } from '../gallery-grid/gallery-grid.component';
20+
21+
@Component({
22+
selector: 'app-carousel',
23+
standalone: true,
24+
imports: [CommonModule, MatButtonModule, MatCardModule, MatIconModule],
25+
templateUrl: './carousel.component.html',
26+
styleUrls: ['./carousel.component.scss']
27+
})
28+
export class CarouselComponent implements AfterViewInit, OnDestroy, OnChanges {
29+
@Input() data: any[] = [];
30+
@ViewChildren('cardItem') cardItems!: QueryList<ElementRef>;
31+
@ViewChild('scrollContainer') scrollContainer!: ElementRef<HTMLElement>;
32+
33+
originalItems: any[] = [];
34+
displayItems: any[] = [];
35+
36+
constructor(
37+
private ngZone: NgZone,
38+
private dialog: MatDialog
39+
) {}
40+
41+
ngOnChanges(changes: SimpleChanges) {
42+
if (changes['data'] && this.data) {
43+
this.buildCarouselItems();
44+
}
45+
}
46+
47+
buildCarouselItems() {
48+
const mappedData = this.data.map(item => {
49+
return {
50+
title: item.Carouselheading || item.Description || 'Untitled',
51+
img: item.ImageURL,
52+
...item
53+
};
54+
});
55+
this.originalItems = mappedData;
56+
let loopList = [...mappedData];
57+
// If you have 2 items, we duplicate them until we have at least 12.
58+
const MIN_ITEMS = 12;
59+
if (loopList.length > 0) {
60+
while (loopList.length < MIN_ITEMS) {
61+
loopList = [...loopList, ...loopList];
62+
}
63+
}
64+
//CREATE 3 SETS: [Left Buffer] [Middle (Active)] [Right Buffer]
65+
this.displayItems = [...loopList, ...loopList, ...loopList];
66+
}
67+
68+
ngAfterViewInit() {
69+
this.ngZone.runOutsideAngular(() => {
70+
const container = this.scrollContainer?.nativeElement;
71+
if (container) {
72+
container.addEventListener('scroll', this.onScroll.bind(this));
73+
setTimeout(() => {
74+
if (container.scrollWidth > 0) {
75+
const singleSetWidth = container.scrollWidth / 3;
76+
container.scrollLeft = singleSetWidth;
77+
this.onScroll({ target: container } as any);
78+
}
79+
}, 50);
80+
}
81+
});
82+
}
83+
84+
ngOnDestroy() {
85+
const container = this.scrollContainer?.nativeElement;
86+
if (container) {
87+
container.removeEventListener('scroll', this.onScroll.bind(this));
88+
}
89+
}
90+
91+
onScroll(event: Event) {
92+
const container = event.target as HTMLElement;
93+
if (!container) return;
94+
95+
requestAnimationFrame(() => {
96+
const totalWidth = container.scrollWidth;
97+
const singleSetWidth = totalWidth / 3;
98+
const currentScroll = container.scrollLeft;
99+
100+
if (currentScroll < 100) {
101+
container.scrollLeft = currentScroll + singleSetWidth;
102+
} else if (currentScroll >= singleSetWidth * 2 - 100) {
103+
container.scrollLeft = currentScroll - singleSetWidth;
104+
}
105+
const containerRect = container.getBoundingClientRect();
106+
if (containerRect.width === 0) return;
107+
108+
this.cardItems.forEach(item => {
109+
const el = item.nativeElement;
110+
const rect = el.getBoundingClientRect();
111+
const cardCenter = rect.left - containerRect.left + rect.width / 2;
112+
const containerCenter = containerRect.width / 2;
113+
const distance = Math.abs(containerCenter - cardCenter);
114+
115+
const activeZone = 400;
116+
const minWidth = 200;
117+
const maxWidth = 500;
118+
let currentWidth = minWidth;
119+
let opacity = 0.7;
120+
121+
if (distance < activeZone) {
122+
const factor = 1 - distance / activeZone;
123+
currentWidth = minWidth + (maxWidth - minWidth) * factor;
124+
opacity = 0.7 + 0.3 * factor;
125+
}
126+
127+
el.style.flexBasis = `${currentWidth}px`;
128+
el.style.minWidth = `${currentWidth}px`;
129+
el.style.opacity = `${opacity}`;
130+
});
131+
});
132+
}
133+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<div class="dialog-content">
2+
<div class="dialog-header">
3+
<h2 mat-dialog-title>All Content</h2>
4+
<button mat-icon-button (click)="close()">
5+
<mat-icon>close</mat-icon>
6+
</button>
7+
</div>
8+
9+
<div *ngIf="data.dataPage === 'D_CarouselitemList'" mat-dialog-content class="grid-container">
10+
<div class="grid-item" *ngFor="let item of data.items">
11+
<img [src]="item.ImageURL" alt="Item Image" />
12+
<p>{{ item.Carouselheading }}</p>
13+
</div>
14+
</div>
15+
16+
<div *ngIf="data.dataPage === 'D_AccountHistoryList'" class="grid">
17+
<table-template-card *ngFor="let item of data.items; trackBy: trackByTitle; index as i" [data]="item" [index]="i"> </table-template-card>
18+
</div>
19+
</div>

0 commit comments

Comments
 (0)