Skip to content

Instantly share code, notes, and snippets.

@Stradivario
Last active September 18, 2019 06:08
Show Gist options
  • Save Stradivario/0a45703a6609ddcd7ecb9e14d903064f to your computer and use it in GitHub Desktop.
Save Stradivario/0a45703a6609ddcd7ecb9e14d903064f to your computer and use it in GitHub Desktop.
Reactive flex grid lit component
import { html, Component, LitElement, css, property, async, TemplateResult } from '@rxdi/lit-html';
import { Inject } from '@rxdi/core';
import { map, switchMap } from 'rxjs/operators';
import { combineLatest, of, Observable, isObservable, from } from 'rxjs';
import { ResponsiveService } from '@rxdi/ui-components/services';
/**
* @customElement flex-grid
*/
@Component({
selector: 'flex-grid',
style: css`
.flex {
display: flex;
}
.spacer {
flex: 1 3 auto;
}
.center {
margin: 0 auto
}
`,
template(this: GridComponent) {
return html`
${async(
from(isObservable(this.$items) ? this.$items : of(this.$items))
.pipe(
map(items => (items.length ? items : Array.from(Array(this.fill).keys()))),
switchMap(c =>
combineLatest(of(c), this.responsive.width.pipe(map(width => this.calculateColumns(width))))
),
switchMap(([c, columns]) => combineLatest([of(c), of(this.calculateRows(c.length, columns)), of(columns)]))
)
.pipe(
map(
([components, rows, columns]) => html`
${Array.from(Array(rows).keys()).map(
i => html`
<div class="flex" style="margin-bottom: 30px;">
${this.calculateTemplateColumns(components, i, columns)}
</div>
`
)}
`
)
)
)}
`;
},
})
export class GridComponent extends LitElement {
@Inject(ResponsiveService)
private responsive: ResponsiveService;
@property({ type: Number })
fill: number;
@property({ attribute: false })
$items: Observable<any[]> | any[] = of([]);
@property()
template: (item: any) => TemplateResult;
private calculateColumns(width: number) {
let columns: number;
if (width < 700) {
columns = 1;
} else if (width < 1000) {
columns = 2;
} else if (width < 1450) {
columns = 3;
} else if (width > 1450) {
columns = 4;
}
return columns;
}
private calculateRows(itemsLength: number, columns: number) {
return Math.round(itemsLength / columns) + 2;
}
private calculateTemplateColumns(items: any[], index: number, columns: number) {
const calculated = index * columns;
const offset = calculated - columns;
return html`
<div class="flex center">
${items.length
? html`
${items.slice(offset, calculated).map(item => this.getTemplate(item))}
`
: 'No components found'}
</div>
`;
}
private getTemplate(item: any) {
return html`
${this.template ? this.template(item) : html`${item}`}
<span class="spacer"></span>
`;
}
}
// Usage
import { html, Component, LitElement, css } from '@rxdi/lit-html';
import { MainView } from '../shared/styles/margin-top';
import { Inject } from '@rxdi/core';
import { UIComponentsService } from '../core/services/ui-components/ui-components.service';
import { IComponentsType } from '../app.interface';
import { COMPONENTS_DATA } from '../shared/grid/data';
import { of } from 'rxjs';
/**
* @customElement ui-components-component
*/
@Component({
selector: 'ui-components-component',
style: css`
${MainView}
h4 {
color: black;
margin-bottom: 0px;
}
`,
template(this: UiComponentsComponent) {
return html`
<div style="color: #324044;width: 100%; height: 100%;background-color: #f1f5f7">
<div class="container">
<div style="margin: 75px auto; padding: 25px; ">
<h1>Browse collections</h1>
<h3>72 Collections</h3>
<flex-grid
.$items=${[
html`<p>2222</p>`
]}
></flex-grid>
<flex-grid
.$items=${this.uiComponentsService.$components}
.template=${(component: IComponentsType) => html`
<div style="margin-right: 15px;">
<card-component style="cursor: pointer">
<div style="width: 280px; height: 250px; text-align: center; padding: 15px; ">
<h4>${component.namespace}</h4>
<p>${component.items} Items</p>
<p>
${component.description}
</p>
<spacer-component></spacer-component>
<div class="flex">
<span class="spacer"></span>
<div>
<p style=" margin: 0px;">
<img style="width: 40px;" src="https://graphql-server.com/assets/images/logo.png" />
</p>
</div>
<div>
<p style="margin: 10px 0 0 0; font-size: 13px; color: #027cb1">${component.owner}</p>
</div>
<span class="spacer"></span>
</div>
</div>
</card-component>
</div>
`}
>
</flex-grid>
</div>
</div>
</div>
`;
},
})
export class UiComponentsComponent extends LitElement {
@Inject(UIComponentsService)
private uiComponentsService: UIComponentsService;
interval;
OnInit() {
this.interval = setInterval(() => {
COMPONENTS_DATA.push({
description: `
An evolving set of free, open source web components for building mobile and desktop web
applications in modern browsers.
`,
id: '1',
items: 51,
namespace: '2',
owner: 'HTMLELements',
});
this.uiComponentsService.loadComponents(COMPONENTS_DATA);
}, 2000);
}
OnDestroy() {
clearInterval(this.interval);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment