mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
Flow cell
This commit is contained in:
parent
209ab25ab0
commit
603e78b5ba
7 changed files with 130 additions and 72 deletions
|
@ -1,44 +1,52 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC, useState, useCallback } from 'react';
|
||||||
|
import { INode } from '~/redux/types';
|
||||||
import * as styles from './styles.scss';
|
import * as styles from './styles.scss';
|
||||||
import { TEXTS } from '~/constants/texts';
|
import { getImageSize } from '~/utils/dom';
|
||||||
|
|
||||||
import classNames = require('classnames');
|
import classNames = require('classnames');
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
height?: number;
|
node: INode;
|
||||||
width?: number;
|
// height?: number;
|
||||||
title?: string;
|
// width?: number;
|
||||||
is_hero?: boolean;
|
// title?: string;
|
||||||
is_stamp?: boolean;
|
// is_hero?: boolean;
|
||||||
|
// is_stamp?: boolean;
|
||||||
is_text?: boolean;
|
is_text?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cell: FC<IProps> = ({
|
const Cell: FC<IProps> = ({ node: { title, brief }, is_text = false }) => {
|
||||||
width = 1,
|
const [is_loaded, setIsLoaded] = useState(false);
|
||||||
height = 1,
|
|
||||||
title,
|
const onImageLoad = useCallback(() => {
|
||||||
is_hero,
|
setIsLoaded(true);
|
||||||
is_text = (Math.random() > 0.8),
|
}, [setIsLoaded]);
|
||||||
}) => (
|
|
||||||
<div
|
return (
|
||||||
className={
|
<div className={classNames(styles.cell, 'vert-1', 'hor-1', { is_text: false })}>
|
||||||
classNames(
|
<div className={styles.face}>{title && <div className={styles.title}>{title}</div>}</div>
|
||||||
styles.cell,
|
|
||||||
`vert-${height}`,
|
{brief && brief.thumbnail && (
|
||||||
`hor-${width}`,
|
<div
|
||||||
{ is_text },
|
className={styles.thumbnail}
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url("${getImageSize(brief.thumbnail, 'medium')}")`,
|
||||||
|
opacity: is_loaded ? 1 : 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src={getImageSize(brief.thumbnail, 'medium')} onLoad={onImageLoad} alt="" />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
style={{
|
</div>
|
||||||
// gridRowEnd: `span ${height}`,
|
);
|
||||||
// gridColumnEnd: `span ${width}`,
|
};
|
||||||
}}
|
|
||||||
>
|
|
||||||
{is_text && <div className={styles.text}>
|
|
||||||
<div className={styles.text_title}>{title}</div>
|
|
||||||
{TEXTS.LOREM_IPSUM}
|
|
||||||
</div>}
|
|
||||||
{title && <div className={styles.title}>{title}</div>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export { Cell };
|
export { Cell };
|
||||||
|
|
||||||
|
/*
|
||||||
|
{is_text && (
|
||||||
|
<div className={styles.text}>
|
||||||
|
<div className={styles.text_title}>{node.title}</div>
|
||||||
|
{TEXTS.LOREM_IPSUM}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
*/
|
||||||
|
|
|
@ -50,7 +50,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title, .text_title {
|
.title,
|
||||||
|
.text_title {
|
||||||
font: $font_cell_title;
|
font: $font_cell_title;
|
||||||
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
@ -58,16 +59,11 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
padding: 0 $gap;
|
max-height: 2em;
|
||||||
position: absolute;
|
|
||||||
bottom: $gap;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text_title {
|
.text_title {
|
||||||
|
@ -97,3 +93,36 @@
|
||||||
box-shadow: inset #444 0 0 0 1px;
|
box-shadow: inset #444 0 0 0 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: 50% 50% no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: $cell_radius + 2px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
|
||||||
|
& > img {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.face {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient($content_bg, transparentize($content_bg, 1));
|
||||||
|
z-index: 2;
|
||||||
|
border-radius: $cell_radius;
|
||||||
|
padding: $gap;
|
||||||
|
}
|
||||||
|
|
31
src/components/flow/FlowGrid/index.tsx
Normal file
31
src/components/flow/FlowGrid/index.tsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import React, { FC } from 'react';
|
||||||
|
import { Cell } from '~/components/flow/Cell';
|
||||||
|
|
||||||
|
import * as styles from './styles.scss';
|
||||||
|
import { IFlowState } from '~/redux/flow/reducer';
|
||||||
|
|
||||||
|
type IProps = Partial<IFlowState> & {};
|
||||||
|
|
||||||
|
export const FlowGrid: FC<IProps> = ({ nodes }) => (
|
||||||
|
<div>
|
||||||
|
<div className={styles.grid_test}>
|
||||||
|
<div className={styles.hero}>HERO</div>
|
||||||
|
<div className={styles.stamp}>STAMP</div>
|
||||||
|
|
||||||
|
{nodes.map(node => (
|
||||||
|
<Cell key={node.id} node={node} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// {
|
||||||
|
// range(1, 20).map(el => (
|
||||||
|
// <Cell
|
||||||
|
// width={Math.floor(Math.random() * 2 + 1)}
|
||||||
|
// height={Math.floor(Math.random() * 2 + 1)}
|
||||||
|
// title={`Cell ${el}`}
|
||||||
|
// key={el}
|
||||||
|
// />
|
||||||
|
// ));
|
||||||
|
// }
|
|
@ -1,24 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { range } from 'ramda';
|
|
||||||
import { Cell } from '~/components/flow/Cell';
|
|
||||||
|
|
||||||
import * as styles from './styles.scss';
|
|
||||||
|
|
||||||
export const TestGrid = () => (
|
|
||||||
<div>
|
|
||||||
<div className={styles.grid_test}>
|
|
||||||
<div className={styles.hero}>HERO</div>
|
|
||||||
|
|
||||||
<div className={styles.stamp}>STAMP</div>
|
|
||||||
|
|
||||||
{range(1, 20).map(el => (
|
|
||||||
<Cell
|
|
||||||
width={Math.floor(Math.random() * 2 + 1)}
|
|
||||||
height={Math.floor(Math.random() * 2 + 1)}
|
|
||||||
title={`Cell ${el}`}
|
|
||||||
key={el}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
|
@ -1,8 +1,19 @@
|
||||||
import * as React from 'react';
|
import React, { FC } from 'react';
|
||||||
import { TestGrid } from '~/components/flow/TestGrid';
|
import { connect } from 'react-redux';
|
||||||
import * as styles from './styles.scss';
|
import { FlowGrid } from '~/components/flow/FlowGrid';
|
||||||
import { Header } from '~/components/main/Header';
|
import { selectFlow } from '~/redux/flow/selectors';
|
||||||
|
|
||||||
export const FlowLayout = () => (
|
const mapStateToProps = selectFlow;
|
||||||
<TestGrid />
|
|
||||||
);
|
const mapDispatchToProps = {};
|
||||||
|
|
||||||
|
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
|
const FlowLayoutUnconnected: FC<IProps> = ({ nodes }) => <FlowGrid nodes={nodes} />;
|
||||||
|
|
||||||
|
const FlowLayout = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(FlowLayoutUnconnected);
|
||||||
|
|
||||||
|
export { FlowLayout, FlowLayoutUnconnected };
|
||||||
|
|
|
@ -53,3 +53,6 @@ export const describeArc = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getURL = url => `${process.env.API_HOST}${url}`;
|
export const getURL = url => `${process.env.API_HOST}${url}`;
|
||||||
|
|
||||||
|
export const getImageSize = (image: string, size?: string): string =>
|
||||||
|
`${process.env.API_HOST}${image}`;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue