Skip to content
Permalink
Browse files

feat(Block): implement init parent and child behaviour

  • Loading branch information...
wengkhing
wengkhing committed Jan 15, 2018
1 parent c52e078 commit 6c10653dd547a3ef4129407d269904b5229346af
Showing with 310 additions and 42 deletions.
  1. +0 −28 src/App.css
  2. +16 −14 src/App.js
  3. +191 −0 src/Block/index.js
  4. +103 −0 src/Block/style.css
@@ -1,28 +0,0 @@
.App {
text-align: center;
}

.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}

.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}

.App-title {
font-size: 1.5em;
}

.App-intro {
font-size: large;
}

@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@@ -1,21 +1,23 @@
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import React, { Component } from 'react'
import './App.css'

import Block from './Block'

class App extends Component {
render() {
render () {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<div className='App'>
<Block layout='row' gutter='8px'>
<div>Col 1</div>
<Block layout='column' basis='grow'>
<div basis='grow'>Nest 1</div>
<div>Nest 2</div>
</Block>
<div>Col 2</div>
</Block>
</div>
);
)
}
}

export default App;
export default App
@@ -0,0 +1,191 @@
import React from 'react'
import './style.css'

// === <Configurations> ===
// Default Block props
const defaultBlockProps = {
layout: 'row',
basis: 'auto',
xBasis: 'auto',
wrap: true,
align: 'start start',
gutter: '0px'
}

// Default child props
const defaultChildProps = {
basis: 'auto',
xBasis: 'auto',
alignSelf: 'auto',
order: 0
}
// =========================
const validBasisValue = /^[0-9]*(vw|px|vh|%)$/
const validGutterValue = /^[0-9]*px$/

const Block = (props) => {
const { blockClassNames, blockStyle } = generateBlockClasses(props)
return (
<div className={blockClassNames}
style={blockStyle}>
{props.children.map((child, i) => {
const { childClassNames, childStyle } = generateChildClasses(child.props, props.layout, props.gutter)
return (
<div key={i} className={childClassNames}
style={childStyle}>
{child}
</div>
)
})}
</div>
)
}

function generateBlockClasses (props) {
const blockProps = { ...defaultBlockProps, ...props }
const style = {}
let classNames = 'awe-block'
// Validate 'layout' props and assign className accordingly
switch (blockProps.layout) {
case 'row':
case 'column':
case 'row-reverse':
case 'column-reverse':
classNames += ` ${blockProps.layout}`
break
default:
console.warn(`'${blockProps.layout}' is not a valid value for property 'layout'.\nDefault value 'row' will be used instead.`)
classNames += ' row'
}

// Validate 'wrap' props and assign className accordingly
switch (blockProps.wrap) {
case true:
case 'down':
classNames += ' down'
break
case 'up':
case 'reverse':
classNames += ' up'
break
default:
console.warn(`'${blockProps.layout}' is not a valid value for property 'wrap'.\nDefault value 'down' will be used instead.`)
classNames += ' down'
}

// Validate 'align' props and assign className accordingly
const alignArr = blockProps.align.split(' ')
const baseAlign = alignArr[0] || 'start'
const crossAlign = alignArr[1] || 'start'
switch (baseAlign) {
case 'start':
case 'end':
case 'center':
case 'between':
case 'around':
classNames += ` base-${baseAlign}`
break
default:
console.warn(`'${baseAlign}' is not a valid value for first argument of property 'align'.\nDefault value 'start' will be used instead.`)
classNames += ' base-start'
}

switch (crossAlign) {
case 'start':
case 'end':
case 'center':
case 'baseline':
case 'stretch':
classNames += ` cross-${crossAlign}`
break
default:
console.warn(`'${crossAlign}' is not a valid value for second argument of property 'align'.\nDefault value 'start' will be used instead.`)
classNames += ' cross-start'
}

// Assign 'basis' and 'xBasis' value to style according to layout direction
// assign 'basis' value to height and 'xBasis' value to width if layout direction is 'row' or 'row-reverse' or default
// vice versa for layout 'column' or 'column-reverse'
if (blockProps.basis) {
switch (blockProps.layout) {
// case 'row':
// case 'row-reverse':
// style.width = blockProps.basis
// style.height = childProps.xBasis
// break
case 'column':
case 'column-reverse':
style.height = blockProps.basis
style.width = blockProps.xBasis
break
default:
style.width = blockProps.basis
style.height = blockProps.xBasis
}
}

return { blockClassNames: classNames, blockStyle: style }
}

function generateChildClasses (props, parentLayout, gutter) {
const childProps = { ...defaultChildProps, ...props }
const style = {}
let classNames = 'awe-child'
// Validate 'alignSelf' props and assign className accordingly
switch (childProps.alignSelf) {
case 'start':
case 'end':
case 'center':
case 'baseline':
case 'stretch':
classNames += ` self-${childProps.alignSelf}`
break
case 'auto':
break
default:
console.warn(`'${childProps.alignSelf}' is not a valid value for property 'alignSelf'.\nDefault value 'auto' will be used instead.`)
}

// Validate 'basis' props and assign className and style accordingly
switch (childProps.basis) {
case 'grow':
classNames += ' grow'
break
case 'auto':
classNames += ' no-grow'
break
default:
if (!validBasisValue.test(childProps.basis)) {
console.warn(`'${childProps.basis}' is not a valid value for property 'basis'.\nPlease use numerical value postfix with 'px', 'vw', 'vh' or '%'. Example: '30%', '23vw', '100px'`)
}
style.flexBasis = childProps.basis
}

// Assign 'xBasis' value to style according to parent layout direction
// assign value to height if parent layout direction is 'row' or 'row-reverse' or default
// assign value to width if parent layout direction is 'column' or 'column-reverse'
if (childProps.xBasis) {
switch (parentLayout) {
// case 'row':
// case 'row-reverse':
// style.height = childProps.xBasis
// break
case 'column':
case 'column-reverse':
style.width = childProps.xBasis
break
default:
style.height = childProps.xBasis
}
}

if (validGutterValue.test(gutter)) {
style.margin = `${parseInt(gutter.replace('px', '')) / 2}px`
} else {
console.warn(`'${gutter}' is not a valid value for property 'gutter'.\nPlease use numerical value postfix with 'px'. Example: 8px'`)
}

return { childClassNames: classNames, childStyle: style }
}

export default Block
@@ -0,0 +1,103 @@
.awe-block {
display: flex;
width: 100%;
}

.awe-block.row {
flex-direction: row;
}

.awe-block.row-reverse {
flex-direction: row-reverse;
}

.awe-block.column {
flex-direction: column;
}

.awe-block.column-reverse {
flex-direction: column-reverse;
}

.awe-block.down {
flex-wrap: wrap;
}

.awe-block.up {
flex-wrap: wrap-reverse;
}

.awe-block.base-start {
justify-content: flex-start;
}

.awe-block.base-end {
justify-content: flex-end;
}

.awe-block.base-center {
justify-content: center;
}

.awe-block.base-between {
justify-content: space-between;
}

.awe-block.base-around {
justify-content: space-around;
}

.awe-block.cross-start {
align-items: flex-start;
}

.awe-block.cross-end {
align-items: flex-end;
}

.awe-block.cross-center {
align-items: center;
}

.awe-block.cross-baseline {
align-items: baseline;
}

.awe-block.cross-stretch {
align-items: stretch;
}

.awe-child {
flex-shrink: 1;
}

.awe-child.grow {
flex-grow: 1;
flex-basis: auto;
}

.awe-child.no-grow {
flex-grow: 0;
flex-basis: auto;
}

.awe-child.self-start {
align-self: flex-start;
}

.awe-child.self-end {
align-self: flex-end;
}

.awe-child.self-center {
align-self: center;
}

.awe-child.self-baseline {
align-self: baseline;
}

.awe-child.self-stretch {
align-self: stretch;
}

0 comments on commit 6c10653

Please sign in to comment.
You can’t perform that action at this time.