140 lines
5.4 KiB
TypeScript
140 lines
5.4 KiB
TypeScript
import * as _ from 'lodash';
|
|
import * as React from 'react';
|
|
import styled from 'styled-components';
|
|
|
|
import { addFadeInAnimation } from 'ts/constants/animations';
|
|
import { ExploreGridTile } from 'ts/pages/explore/explore_grid_tile';
|
|
import { ExploreTile, ExploreTileGridWidth, ExploreTileVisibility, ExploreTileWidth } from 'ts/types';
|
|
|
|
const EXPLORE_TILE_COL_WIDTH: { [ExploreTileWidth: string]: { [ExploreTileGridWidth: number]: number } } = {
|
|
[ExploreTileWidth.OneThird]: {
|
|
[ExploreTileGridWidth.ThreeColumn]: 2,
|
|
[ExploreTileGridWidth.TwoColumn]: 2,
|
|
[ExploreTileGridWidth.OneColumn]: 2,
|
|
},
|
|
[ExploreTileWidth.FullWidth]: {
|
|
[ExploreTileGridWidth.ThreeColumn]: 6,
|
|
[ExploreTileGridWidth.TwoColumn]: 4,
|
|
[ExploreTileGridWidth.OneColumn]: 2,
|
|
},
|
|
[ExploreTileWidth.Half]: {
|
|
[ExploreTileGridWidth.ThreeColumn]: 3,
|
|
[ExploreTileGridWidth.TwoColumn]: 4,
|
|
[ExploreTileGridWidth.OneColumn]: 2,
|
|
},
|
|
[ExploreTileWidth.TwoThirds]: {
|
|
[ExploreTileGridWidth.ThreeColumn]: 4,
|
|
[ExploreTileGridWidth.TwoColumn]: 4,
|
|
[ExploreTileGridWidth.OneColumn]: 2,
|
|
},
|
|
};
|
|
|
|
export interface ExptoreGridProps {
|
|
tiles: ExploreTile[];
|
|
}
|
|
|
|
interface ExploreGridTilePosition {
|
|
gridStart: number;
|
|
gridEnd: number;
|
|
}
|
|
|
|
interface RicherExploreGridListTile extends ExploreTile {
|
|
tilePositions: { [ExploreTileGridWidth: number]: ExploreGridTilePosition };
|
|
}
|
|
|
|
export class ExploreGrid extends React.Component<ExptoreGridProps> {
|
|
public render(): React.ReactNode {
|
|
return (
|
|
<ExploreGridList>
|
|
{this._prepareTiles().map(t => {
|
|
if (!!t.exploreProject) {
|
|
return (
|
|
<ExploreGridTileWrapper key={t.name} tilePositions={t.tilePositions}>
|
|
<ExploreGridTile {...t.exploreProject} />
|
|
</ExploreGridTileWrapper>
|
|
);
|
|
} else {
|
|
return (
|
|
<ExploreGridTileWrapper key={t.name} tilePositions={t.tilePositions}>
|
|
{!!t.component && t.component}
|
|
</ExploreGridTileWrapper>
|
|
);
|
|
}
|
|
})}
|
|
</ExploreGridList>
|
|
);
|
|
}
|
|
|
|
private readonly _prepareTiles = (): RicherExploreGridListTile[] => {
|
|
const visibleTiles = this.props.tiles.filter(t => t.visibility !== ExploreTileVisibility.Hidden);
|
|
return this._generateGridValues(visibleTiles);
|
|
};
|
|
|
|
private readonly _generateGridPositions = (
|
|
tiles: RicherExploreGridListTile[],
|
|
width: ExploreTileGridWidth,
|
|
): RicherExploreGridListTile[] => {
|
|
let gridEndCounter = 1;
|
|
const newTiles = tiles.map(t => {
|
|
if (gridEndCounter + EXPLORE_TILE_COL_WIDTH[t.width][width] > width + 1) {
|
|
gridEndCounter = 1;
|
|
}
|
|
const gridStart = gridEndCounter;
|
|
const gridEnd = gridEndCounter + EXPLORE_TILE_COL_WIDTH[t.width][width];
|
|
gridEndCounter = gridEnd;
|
|
const newTilePositions = _.assign({}, t.tilePositions);
|
|
newTilePositions[width] = { gridStart, gridEnd };
|
|
return _.assign({}, t, { tilePositions: newTilePositions }) as RicherExploreGridListTile;
|
|
});
|
|
return newTiles;
|
|
};
|
|
|
|
private readonly _generateGridValues = (tiles: ExploreTile[]): RicherExploreGridListTile[] => {
|
|
let richerTiles = tiles.map(t => {
|
|
return _.assign({ tilePositions: {} }, t) as RicherExploreGridListTile;
|
|
});
|
|
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.ThreeColumn);
|
|
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.TwoColumn);
|
|
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.OneColumn);
|
|
return richerTiles;
|
|
};
|
|
}
|
|
|
|
interface ExploreGridListProps {}
|
|
|
|
interface ExploreGridTileWrapperProps {
|
|
tilePositions: { [ExploreTileGridWidth: number]: ExploreGridTilePosition };
|
|
}
|
|
|
|
const ExploreGridTileWrapper = styled.div<ExploreGridTileWrapperProps>`
|
|
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.ThreeColumn].gridStart};
|
|
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.ThreeColumn].gridEnd};
|
|
@media (max-width: 56rem) {
|
|
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.TwoColumn].gridStart};
|
|
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.TwoColumn].gridEnd};
|
|
}
|
|
@media (max-width: 36rem) {
|
|
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.OneColumn].gridStart};
|
|
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.OneColumn].gridEnd};
|
|
}
|
|
`;
|
|
|
|
const ExploreGridList = styled.div<ExploreGridListProps>`
|
|
display: grid;
|
|
grid-template-columns: repeat(${ExploreTileGridWidth.ThreeColumn}, 1fr);
|
|
grid-column-gap: 1.5rem;
|
|
grid-row-gap: 1.5rem;
|
|
z-index: 0;
|
|
position: relative;
|
|
${addFadeInAnimation('0.5s', '0.25s')}
|
|
& > * {
|
|
align-self: stretch;
|
|
}
|
|
@media (max-width: 56rem) {
|
|
grid-template-columns: repeat(${ExploreTileGridWidth.TwoColumn}, 1fr);
|
|
}
|
|
@media (max-width: 36rem) {
|
|
grid-template-columns: repeat(${ExploreTileGridWidth.OneColumn}, 1fr);
|
|
}
|
|
`;
|