252 lines
7.4 KiB
TypeScript
252 lines
7.4 KiB
TypeScript
|
import { DeesElement, property, state, html, customElement, type TemplateResult, cssManager, css } from '@design.estate/dees-element';
|
||
|
|
||
|
import { ExtendedDate } from '@push.rocks/smarttime';
|
||
|
|
||
|
import * as belliniApi from '@bellini/api';
|
||
|
|
||
|
import * as helpers from '../helpers/index.js';
|
||
|
|
||
|
import * as domtools from '@design.estate/dees-domtools';
|
||
|
import '@design.estate/dees-catalog';
|
||
|
|
||
|
@customElement('bellini-articlegrid')
|
||
|
export class BelliniArticleGrid extends DeesElement {
|
||
|
public static demo = () => html`<bellini-articlegrid publicationName="central.eu"></bellini-articlegrid>`;
|
||
|
|
||
|
@property({type: Array})
|
||
|
public articles: belliniApi.IBelliniClientState['articles'] = [];
|
||
|
|
||
|
@property({type: Object})
|
||
|
public selectedArticle: belliniApi.IBelliniClientState['articles'][0];
|
||
|
|
||
|
@property()
|
||
|
publicationName: string;
|
||
|
|
||
|
constructor() {
|
||
|
super();
|
||
|
}
|
||
|
|
||
|
public static styles = [
|
||
|
cssManager.defaultStyles,
|
||
|
css`
|
||
|
:host {
|
||
|
display: block;
|
||
|
position: relative;
|
||
|
}
|
||
|
.articleGrid {
|
||
|
position: relative;
|
||
|
transition: all 0.3s;
|
||
|
display: grid;
|
||
|
grid-template-columns: ${cssManager.cssGridColumns(4, 15)};
|
||
|
grid-gap: 15px;
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
.articleGrid.hidden {
|
||
|
opacity: 0;
|
||
|
}
|
||
|
|
||
|
.articleGrid a {
|
||
|
color: ${cssManager.bdTheme('#222', '#eee')};
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
|
||
|
.articleitem {
|
||
|
min-height: 400px;
|
||
|
transition: box-shadow 0.3s;
|
||
|
width: 100%;
|
||
|
overflow: hidden;
|
||
|
border-radius: 3px;
|
||
|
box-shadow: 0px 0px 5px ${cssManager.bdTheme('rgba(0, 0, 0, 0.2)', 'rgba(0, 0, 0, 0.5)')};
|
||
|
position: relative;
|
||
|
cursor: pointer;
|
||
|
border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#555555')};
|
||
|
}
|
||
|
|
||
|
.articleitem * {
|
||
|
user-select: none;
|
||
|
}
|
||
|
|
||
|
.articleitem:hover {
|
||
|
box-shadow: 0px 3px 10px ${cssManager.bdTheme('rgba(0, 0, 0, 0.2)', 'rgba(0, 0, 0, 0.5)')};
|
||
|
}
|
||
|
|
||
|
.articleitem .image {
|
||
|
background: ${cssManager.bdTheme('#eeeeeb', '#2f2f2f')};;
|
||
|
top: 0px;
|
||
|
position: absolute;
|
||
|
width: 100%;
|
||
|
height: 220px;
|
||
|
}
|
||
|
|
||
|
.articleitem .image img {
|
||
|
border-radius: 3px;
|
||
|
display: block;
|
||
|
width: calc(100% - 10px);
|
||
|
height: calc(100% - 10px);
|
||
|
margin: 5px;
|
||
|
object-fit: cover;
|
||
|
}
|
||
|
|
||
|
.articleitem .image img:after {
|
||
|
content: ' ';
|
||
|
position: absolute;
|
||
|
top: 10;
|
||
|
left: 10;
|
||
|
bottom: 10;
|
||
|
right: 10;
|
||
|
box-shadow: inset 0px 0px 100px ${cssManager.bdTheme('rgba(0, 0, 0, 0.5)', 'rgba(0, 0, 0, 0.8)')};
|
||
|
}
|
||
|
|
||
|
.articleitem .preslant {
|
||
|
transform: skewY(8deg);
|
||
|
transform-origin: 0%;
|
||
|
background: ${cssManager.bdTheme('#eeeeeb', '#333333')};
|
||
|
height: 250px;
|
||
|
position: absolute;
|
||
|
top: 161px;
|
||
|
width: 100%;
|
||
|
left: 0px;
|
||
|
}
|
||
|
|
||
|
.articleitem .slant {
|
||
|
transform: skewY(8deg);
|
||
|
transform-origin: 0%;
|
||
|
background: ${cssManager.bdTheme('#fafafa', '#1d1d1d')};
|
||
|
border-top: 1px solid ${cssManager.bdTheme('#fafafa', '#444444')};
|
||
|
height: 400px;
|
||
|
position: absolute;
|
||
|
top: 165px;
|
||
|
width: 100%;
|
||
|
left: 0px;
|
||
|
box-shadow: 0px 0px 5px ${cssManager.bdTheme('rgba(0,0,0,0.1)', 'rgba(0,0,0,0.5)')};
|
||
|
}
|
||
|
.articleitem .text {
|
||
|
z-index: 2;
|
||
|
position: relative;
|
||
|
left: 0px;
|
||
|
margin-top: 175px;
|
||
|
padding: 20px;
|
||
|
font-family: 'Roboto Mono', monospace;
|
||
|
}
|
||
|
|
||
|
.articleitem .text .timestamp {
|
||
|
color: ${cssManager.bdTheme('#333', '#aaa')};
|
||
|
font-size: 15px;
|
||
|
font-weight: 100;
|
||
|
font-family: 'Roboto Mono', monospace;
|
||
|
margin-bottom: 5px;
|
||
|
}
|
||
|
|
||
|
.articleitem .text .title {}
|
||
|
|
||
|
.articleitem .text .title h1 {
|
||
|
display: block;
|
||
|
margin: 0px;
|
||
|
font-size: 18px;
|
||
|
font-family: 'Roboto Slab';
|
||
|
font-weight: 400;
|
||
|
}
|
||
|
|
||
|
.articleitem .text .title h2 {
|
||
|
display: block;
|
||
|
color: ${cssManager.bdTheme('#444', '#CCC')};
|
||
|
margin-top: 8px;
|
||
|
font-size: 16px;
|
||
|
font-weight: 300;
|
||
|
font-family: 'Roboto', monospace;
|
||
|
padding-left: 10px;
|
||
|
border-left: 4px dotted ${cssManager.bdTheme('#00000020', '#ffffff20')};
|
||
|
}
|
||
|
|
||
|
${cssManager.cssForTablet(css`
|
||
|
.articleGrid {
|
||
|
grid-template-columns: ${cssManager.cssGridColumns(3, 15)};
|
||
|
}
|
||
|
`)}
|
||
|
|
||
|
${cssManager.cssForPhablet(css`
|
||
|
.articleGrid {
|
||
|
grid-template-columns: repeat(2, calc(50% - 10px));
|
||
|
grid-row-gap: 20px;
|
||
|
}
|
||
|
#articlebox {
|
||
|
margin-right: -50px;
|
||
|
margin-left: -50px;
|
||
|
width: calc(100% + 100px);
|
||
|
border-radius: 0px;
|
||
|
}
|
||
|
#articlebox #articleMeta {
|
||
|
margin-left: 0px;
|
||
|
}
|
||
|
|
||
|
#articlebox #articleMeta #metaDeco {
|
||
|
height: 240px;
|
||
|
}
|
||
|
#articlebox #articleContent {
|
||
|
padding: 22px 20px;
|
||
|
}
|
||
|
`)}
|
||
|
|
||
|
${cssManager.cssForPhone(css`
|
||
|
.articleGrid {
|
||
|
grid-template-columns: repeat(1, calc(100% - 0px));
|
||
|
grid-row-gap: 20px;
|
||
|
}
|
||
|
`)}
|
||
|
`
|
||
|
]
|
||
|
|
||
|
public render(): TemplateResult {
|
||
|
return html`
|
||
|
<style>
|
||
|
|
||
|
</style>
|
||
|
<div class="articleGrid">
|
||
|
${this.articles.map((articleItem) => {
|
||
|
const extendedDate = new ExtendedDate(articleItem.timestamp);
|
||
|
return html`
|
||
|
<a
|
||
|
href="${helpers.articlehelpers.getArticleUrl(articleItem)}"
|
||
|
@click="${(eventArg: MouseEvent) => {
|
||
|
this.handleArticleClick(eventArg, articleItem);
|
||
|
}}"
|
||
|
>
|
||
|
<div class="articleitem">
|
||
|
<div class="image"><img loading="lazy" src="${articleItem.featuredImageUrl.replace('q=80', 'q=50').replace('w=2000', 'w=800')}" /></div>
|
||
|
<div class="preslant"></div>
|
||
|
<div class="slant"></div>
|
||
|
<div class="text">
|
||
|
<div class="timestamp">
|
||
|
${extendedDate.format('HH:mm')}<br />${extendedDate.isToday()
|
||
|
? `${extendedDate.format('YYYY-MM-DD')} (Today)`
|
||
|
: extendedDate.format('YYYY-MM-DD')}
|
||
|
</div>
|
||
|
<div class="title"><h1>${articleItem.title}</h1><h2>${articleItem.content.split('.')[0]}.</h2></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</a>
|
||
|
`;
|
||
|
})}
|
||
|
</div>
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
private async handleArticleClick (eventArg: MouseEvent, articleArg: belliniApi.IBelliniClientState['articles'][0]) {
|
||
|
eventArg.preventDefault();
|
||
|
const domtoolsInstance = await this.domtoolsPromise;
|
||
|
domtoolsInstance.router.pushUrl(helpers.articlehelpers.getArticleUrl(articleArg));
|
||
|
}
|
||
|
|
||
|
public async show(boolArg: boolean) {
|
||
|
const domtoolsInstance = await this.domtoolsPromise;
|
||
|
const articleGrid = this.shadowRoot.querySelector('.articleGrid');
|
||
|
if(!boolArg) {
|
||
|
articleGrid.classList.add('hidden');
|
||
|
} else {
|
||
|
articleGrid.classList.remove('hidden');
|
||
|
}
|
||
|
await domtoolsInstance.convenience.smartdelay.delayFor(300);
|
||
|
}
|
||
|
}
|