Added components
parent
0389469982
commit
32daeef1b2
|
@ -0,0 +1,43 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
FontIcon = require "./font_icon"
|
||||
Ripple = require "./ripple"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
type : React.PropTypes.string
|
||||
caption : React.PropTypes.string
|
||||
icon : React.PropTypes.string
|
||||
style : React.PropTypes.string
|
||||
disabled : React.PropTypes.bool
|
||||
|
||||
getDefaultProps: ->
|
||||
type : "square"
|
||||
disabled : false
|
||||
|
||||
getInitialState: ->
|
||||
ripple : undefined
|
||||
|
||||
# -- Events
|
||||
onClick: (event) ->
|
||||
event.preventDefault()
|
||||
@setState ripple:
|
||||
left : event.pageX - event.target.offsetLeft
|
||||
top : event.pageY - event.target.offsetTop
|
||||
@props.onClick? event, @
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<button data-component-button={@props.type}
|
||||
onClick={@onClick}
|
||||
className={@props.style}
|
||||
disabled={@props.disabled}
|
||||
data-flex="horizontal center">
|
||||
{ <FontIcon value={@props.icon} /> if @props.icon }
|
||||
{ <abbr>{@props.caption}</abbr> if @props.caption }
|
||||
<Ripple origin={@state.ripple} />
|
||||
</button>
|
|
@ -0,0 +1,14 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
value : React.PropTypes.array.required
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<span data-component-fonticon className="icon #{@props.value}" />
|
|
@ -24,34 +24,27 @@ module.exports = React.createClass
|
|||
# -- Events
|
||||
onSubmit: (event) ->
|
||||
event.preventDefault()
|
||||
@props.onSubmit? event, @getValue()
|
||||
@props.onSubmit? event, @
|
||||
|
||||
onChange: (event) ->
|
||||
console.log "form.onChange"
|
||||
is_valid = true
|
||||
values = @getValue()
|
||||
# for attr in @props.attributes when attr.required and values[attr.ref].trim() is ""
|
||||
# console.log attr.ref
|
||||
# is_valid = false
|
||||
# break
|
||||
|
||||
console.log "is_valid", is_valid
|
||||
# @TODO: Handler if have errors
|
||||
# @props.onChange? event, @getValue()
|
||||
value = @getValue()
|
||||
for attr in @props.attributes when attr.required and value[attr.ref]?.trim() is ""
|
||||
is_valid = false
|
||||
@refs[attr.ref].setError?()
|
||||
break
|
||||
@props[if is_valid then "onValid" else "onError"]? event, @
|
||||
@props.onChange? event, @
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<form onSubmit={@onSubmit} onChange={@onChange}>
|
||||
<form data-component-form
|
||||
onSubmit={@onSubmit}
|
||||
onChange={@onChange}>
|
||||
{
|
||||
for attribute, index in @props.attributes
|
||||
<Input ref={attribute.ref}
|
||||
type={attribute.type}
|
||||
value={attribute.value}
|
||||
label={attribute.label}
|
||||
required={attribute.required}
|
||||
disabled={attribute.disabled}/>
|
||||
<Input {...attribute} />
|
||||
}
|
||||
<button>submit</button>
|
||||
</form>
|
||||
|
||||
# -- Extends
|
||||
|
@ -60,5 +53,5 @@ module.exports = React.createClass
|
|||
value[ref] = el.getValue() for ref, el of @refs
|
||||
value
|
||||
|
||||
setValue: ->
|
||||
@
|
||||
setValue: (data) ->
|
||||
@setState attributes: data
|
|
@ -6,49 +6,41 @@ module.exports = React.createClass
|
|||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
type : React.PropTypes.string.required
|
||||
label : React.PropTypes.string
|
||||
value : React.PropTypes.string
|
||||
type : React.PropTypes.string
|
||||
error : React.PropTypes.string
|
||||
required : React.PropTypes.bool
|
||||
disabled : React.PropTypes.bool
|
||||
# -- Events
|
||||
multiline : React.PropTypes.bool
|
||||
onChange : React.PropTypes.func
|
||||
onBlur : React.PropTypes.func
|
||||
onFocus : React.PropTypes.func
|
||||
|
||||
getDefaultProps: ->
|
||||
type : "text"
|
||||
disabled : false
|
||||
multiline : false
|
||||
|
||||
getInitialState: ->
|
||||
value : @props.value
|
||||
|
||||
# -- Events
|
||||
onChange: (event) ->
|
||||
value = event.target.value
|
||||
@setState value: value
|
||||
@props.onChange? event, value
|
||||
|
||||
onBlur: (event) ->
|
||||
console.log "onBlur"
|
||||
@props.onBlur? event, value
|
||||
|
||||
onFocus: (event) ->
|
||||
console.log "onFocus"
|
||||
@props.onFocus? event, value
|
||||
@setState value: event.target.value
|
||||
@props.onChange? event, @
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<div data-component-input={@props.type}>
|
||||
<input
|
||||
type={@props.type}
|
||||
value={@state.value}
|
||||
placeholder={@props.hint}
|
||||
disabled={@props.disabled}
|
||||
required={@props.required}
|
||||
onBlur={@onBlur}
|
||||
onFocus={@onFocus}
|
||||
onChange={@onChange}/>
|
||||
# -- styles
|
||||
style = ""
|
||||
style += " error" if @props.error
|
||||
# -- tag
|
||||
<div data-component-input={@props.type} className={style}>
|
||||
{
|
||||
if @props.multiline
|
||||
<textarea {...@props} onChange={@onChange}>{@state.value}</textarea>
|
||||
else
|
||||
<input {...@props} value={@state.value} onChange={@onChange} />
|
||||
}
|
||||
<span className="bar"></span>
|
||||
{ <label>{@props.label}</label> if @props.label }
|
||||
{ <span className="error">{@props.error}</span> if @props.error }
|
||||
|
@ -61,5 +53,5 @@ module.exports = React.createClass
|
|||
setValue: (data) ->
|
||||
@setState value: data
|
||||
|
||||
clearValue: ->
|
||||
@setState ""
|
||||
setError: (data = "Unknown error") ->
|
||||
@setState error: data
|
|
@ -0,0 +1,30 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
origin : React.PropTypes.object
|
||||
colour : React.PropTypes.string
|
||||
|
||||
getDefaultProps: ->
|
||||
origin : undefined
|
||||
colour : "#ffffff"
|
||||
|
||||
# -- Lifecycle
|
||||
componentDidMount: ->
|
||||
el = @getDOMNode()
|
||||
for key in ["animationend", "webkitAnimationEnd", "oAnimationEnd", "MSAnimationEnd"]
|
||||
el.addEventListener key, =>
|
||||
el.classList.remove "active"
|
||||
, false
|
||||
|
||||
componentDidUpdate: ->
|
||||
@getDOMNode().classList.add "active"
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<div data-component-ripple
|
||||
style={left: @props.origin?.left, top: @props.origin?.top} />
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
|
@ -1,23 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Material Console</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width">
|
||||
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1" media="(device-height: 568px)">
|
||||
<meta name="apple-mobile-web-app-title" content="Material Console">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta http-equiv="cleartype" content="on">
|
||||
|
||||
<link rel="stylesheet" href="./assets/css/material-console.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="./assets/js/material-console.dependencies.js"></script>
|
||||
<script src="./assets/js/material-console.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
"use strict"
|
||||
|
||||
SPArouter = require "spa-router"
|
||||
# -- components
|
||||
|
||||
Router = require "./components/router"
|
||||
# -- forms
|
||||
FormSession = require "./forms/form.session"
|
||||
# -- Screens
|
||||
ScreenConsole = require "./screens/console"
|
||||
ScreenForm = require "./screens/form"
|
||||
# -- Modules
|
||||
C = require "./modules/constants"
|
||||
|
||||
App = React.createClass
|
||||
|
||||
# -- Lifecycle
|
||||
componentWillMount: ->
|
||||
SPArouter.listen
|
||||
"/session/:context" : (context) =>
|
||||
@setState session: false, context: context
|
||||
"/:context/:area" : (context, area) =>
|
||||
@setState session: true, context: context, area: area
|
||||
|
||||
# -- Events
|
||||
onSessionSuccess: (data) ->
|
||||
header_style = @refs.header.getDOMNode().classList
|
||||
header_style.add "disabled"
|
||||
header_style.remove "expanded"
|
||||
setTimeout =>
|
||||
SPArouter.path "campaigns/list"
|
||||
, C.ANIMATION.DURATION
|
||||
setTimeout =>
|
||||
header_style.remove "disabled"
|
||||
, (C.ANIMATION.DURATION * 2)
|
||||
|
||||
onConsoleScroll: (value) -> @setState scrolling: value
|
||||
|
||||
onLogout: -> SPArouter.path "session/login"
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
# return <ScreenForm />
|
||||
|
||||
if @state.session
|
||||
avatar = "http://soyjavi.com/assets/img/soyjavi.hat.jpg"
|
||||
else
|
||||
avatar = "./assets/img/avatar.jpg"
|
||||
|
||||
<app className={"scrolling" if @state.scrolling}>
|
||||
<header ref="header"
|
||||
data-flex="horizontal center grow"
|
||||
data-flex-justify="start"
|
||||
className={"expanded" unless @state.session}>
|
||||
<img src={avatar} data-flex-grow="min" onClick={@onLogout}/>
|
||||
{
|
||||
if @state.session
|
||||
<Router context={@state.context} area={@state.area} />
|
||||
else
|
||||
<FormSession context={@state.context} onSuccess={@onSessionSuccess}/>
|
||||
}
|
||||
</header>
|
||||
{ <ScreenConsole context={@state.context} onScroll={@onConsoleScroll}/> if @state.session }
|
||||
</app>
|
||||
|
||||
React.render <App />, document.body
|
|
@ -1,28 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
caption : React.PropTypes.string
|
||||
icon : React.PropTypes.string
|
||||
|
||||
getDefaultProps: ->
|
||||
icon : undefined
|
||||
|
||||
# -- Events
|
||||
onClick: (event) ->
|
||||
event.preventDefault()
|
||||
@props.onClick.call @, event
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<button data-component="button"
|
||||
onClick={@onClick}
|
||||
className={@props.style}
|
||||
disabled={@props.disabled}>
|
||||
{ <span className="icon {{@props.icon}}"></span> if @props.icon }
|
||||
<abbr>{@props.caption}</abbr>
|
||||
</button>
|
|
@ -1,49 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
Button = require './button'
|
||||
Navigation = require './navigation'
|
||||
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
title : React.PropTypes.string.required
|
||||
routes : React.PropTypes.array.required
|
||||
subroutes : React.PropTypes.array
|
||||
|
||||
getDefaultProps: ->
|
||||
routes : []
|
||||
title : undefined
|
||||
subroutes : []
|
||||
|
||||
getInitialState: ->
|
||||
expanded : @props.expanded
|
||||
|
||||
# -- Lifecycle
|
||||
componentDidUpdate: (nextProps) ->
|
||||
@refs.header.getDOMNode().classList.remove "expanded"
|
||||
|
||||
# -- Events
|
||||
onProfile: (event) ->
|
||||
event.preventDefault()
|
||||
@refs.header.getDOMNode().classList.toggle "expanded"
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<header ref="header" data-component="header" data-flex="horizontal center grow">
|
||||
<img src="http://soyjavi.com/assets/img/soyjavi.hat.jpg" data-flex-grow="min"/>
|
||||
<div data-flex-grow="max">
|
||||
<Navigation routes={@props.routes} role="text"/>
|
||||
<div>
|
||||
<h1>{@props.title}</h1>
|
||||
</div>
|
||||
{ <Navigation routes={@props.subroutes} role="text"/> if @props.subroutes }
|
||||
</div>
|
||||
<nav data-role="circle">
|
||||
<Button caption="+" style="circle primary"/>
|
||||
<Button caption="?" style="circle secondary"/>
|
||||
</nav>
|
||||
</header>
|
|
@ -1,39 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
itemFactory : React.PropTypes.func.isRequired
|
||||
dataSource : React.PropTypes.array.isRequired
|
||||
|
||||
getDefaultProps: ->
|
||||
itemFactory : (index) -> <div key={index}></div>
|
||||
dataSource : []
|
||||
|
||||
getInitialState: ->
|
||||
scrolling : false
|
||||
scroll : 0
|
||||
|
||||
# -- Lifecycle
|
||||
componentDidMount: ->
|
||||
@setState clientHeight: @getDOMNode().clientHeight
|
||||
|
||||
# -- Events
|
||||
onScroll: (event) ->
|
||||
scroll = @refs.section.getDOMNode().scrollTop
|
||||
@props.onScroll? scroll > @state.scroll
|
||||
@setState scroll: scroll
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<section ref="section" onScroll={@onScroll} className="scroll">
|
||||
<ul>
|
||||
{
|
||||
for item, index in @props.dataSource
|
||||
<li key={index}>{@props.itemFactory item}</li>
|
||||
}
|
||||
</ul>
|
||||
</section>
|
|
@ -1,13 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports = (data) ->
|
||||
<a href="#/campaigns/{id}" data-flex="horizontal center" className="activity">
|
||||
<figure style={backgroundImage: "url()"} />
|
||||
<div data-flex="vertical" data-flex-grow="max">
|
||||
<strong data-flex-grow="max">text</strong>
|
||||
<small>lorem ipsum...</small>
|
||||
</div>
|
||||
<small>moment</small>
|
||||
</a>
|
|
@ -1,30 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
routes : React.PropTypes.array
|
||||
|
||||
getDefaultProps: ->
|
||||
routes : []
|
||||
|
||||
# -- Events
|
||||
onBack: (event) ->
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
window.history.back()
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
<nav data-role={@props.role}>
|
||||
{
|
||||
for route, index in @props.routes
|
||||
method = if route.back is true then @onBack
|
||||
<a href={"#" + route.route} key={index} className={route.className} onClick={method}>
|
||||
{route.label}
|
||||
</a>
|
||||
}
|
||||
</nav>
|
|
@ -1,44 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
Button = require "./button"
|
||||
Navigation = require "./navigation"
|
||||
C = require "../modules/constants"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
routes : React.PropTypes.array.required
|
||||
|
||||
getDefaultProps: ->
|
||||
routes : [
|
||||
label: "Campaigns", route: "/campaigns/list"
|
||||
,
|
||||
label: "Creatives", route: "/creatives/list"
|
||||
,
|
||||
label: "Users", route: "/users/list"
|
||||
,
|
||||
label: "Deals", route: "/deals/list"
|
||||
,
|
||||
label: "Analytics", route: "/analytics"
|
||||
]
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
for route in @props.routes
|
||||
route.className = if route.label.toLowerCase() is @props.context then "active" else ""
|
||||
for route in subroutes = C.SUBROUTES[@props.context.toUpperCase()]
|
||||
route.className = if route.label.toLowerCase() is @props.area then "active" else ""
|
||||
<div>
|
||||
<div data-flex-grow="max">
|
||||
<Navigation routes={@props.routes} role="text"/>
|
||||
<h1>Console</h1>
|
||||
<Navigation routes={subroutes} role="text"/>
|
||||
</div>
|
||||
<nav data-role="circle">
|
||||
<Button caption="+" style="circle primary"/>
|
||||
<Button caption="?" style="circle secondary"/>
|
||||
</nav>
|
||||
</div>
|
|
@ -1,55 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
# -- components
|
||||
Button = require "../components/button"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
active : React.PropTypes.boolean
|
||||
context : React.PropTypes.string
|
||||
onSuccess : React.PropTypes.function
|
||||
|
||||
getInitialState: ->
|
||||
disabled : true
|
||||
|
||||
# -- Events
|
||||
onKeyUp: (event) ->
|
||||
values = @_getFormValues()
|
||||
@setState disabled: not(values.mail and values.password)
|
||||
|
||||
onSign: (event) ->
|
||||
event.preventDefault()
|
||||
button = @refs.button.getDOMNode().classList
|
||||
button.add "loading"
|
||||
@props.onSuccess.call @props.onSuccess, token: "1"
|
||||
|
||||
|
||||
componentDidMount: ->
|
||||
setTimeout =>
|
||||
@setState active: true
|
||||
, 450
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
label = if @props.context is "login" then "Sign In" else "Sign Up"
|
||||
<form data-flex="vertical" className="session">
|
||||
<h1>Welcome...</h1>
|
||||
<input ref="mail" type="text" placeholder="mail" onKeyUp={@onKeyUp} className="transparent"/>
|
||||
<input ref="password" type="password" placeholder="password" onKeyUp={@onKeyUp} className="transparent"/>
|
||||
<Button ref="button" caption={label} onClick={@onSign} disabled={@state.disabled} style="primary" />
|
||||
{
|
||||
if @props.context is "login"
|
||||
<a href="#/session/signup">Dont have an account? <strong>Sign Up</strong></a>
|
||||
else
|
||||
<a href="#/session/login">You have an account, <strong>Sign In</strong></a>
|
||||
}
|
||||
</form>
|
||||
|
||||
# -- Private methods
|
||||
_getFormValues: ->
|
||||
mail : @refs.mail.getDOMNode().value.trim()
|
||||
password : @refs.password.getDOMNode().value.trim()
|
|
@ -1,33 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
storage = require "../modules/storage"
|
||||
|
||||
module.exports = class Session extends Hamsa
|
||||
|
||||
@define
|
||||
id : type: String
|
||||
mail : type: String
|
||||
token : type: String
|
||||
username : type: String
|
||||
name : type: String
|
||||
bio : type: String
|
||||
image : type: String
|
||||
wallet : type: Number, default: 0
|
||||
|
||||
secrets : type: Array
|
||||
purchases : type: Array
|
||||
tips : type: Array
|
||||
|
||||
followers : type: Array
|
||||
following : type: Array
|
||||
|
||||
updated_at : type: Date
|
||||
created_at : type: Date, default: new Date()
|
||||
|
||||
@update = ->
|
||||
promise = new Hope.Promise()
|
||||
@destroyAll()
|
||||
|
||||
@instance = -> @find()[0]
|
|
@ -1,26 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
module.exports =
|
||||
STORAGE :
|
||||
SESSION : "material-console-session"
|
||||
|
||||
SUBROUTES:
|
||||
CAMPAIGNS: [
|
||||
label: "list", route: "/campaigns/list"
|
||||
,
|
||||
label: "reports", route: "/campaigns/reports"
|
||||
]
|
||||
CREATIVES: [
|
||||
label: "list", route: "/creatives/list"
|
||||
]
|
||||
USERS: []
|
||||
DEALS: []
|
||||
ANALYTICS: []
|
||||
|
||||
HEIGHT:
|
||||
LI : 80
|
||||
|
||||
ANIMATION:
|
||||
DURATION : 450
|
|
@ -1,12 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
C = require "constants"
|
||||
|
||||
module.exports = (value) ->
|
||||
if value or value is null
|
||||
window.localStorage.setItem C.STORAGE.SESSION, JSON.stringify value
|
||||
value
|
||||
else
|
||||
JSON.parse window.localStorage.getItem C.STORAGE.SESSION
|
|
@ -1,14 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
List = require "../components/list"
|
||||
ListItem = require "../components/list_item"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
render: ->
|
||||
mock = (id: i, title: "Title #{i}" for i in [1..200])
|
||||
<article data-screen="console">
|
||||
<List dataSource={mock} itemFactory={ListItem} onScroll={@props.onScroll} />
|
||||
</article>
|
|
@ -1,39 +0,0 @@
|
|||
###
|
||||
@todo
|
||||
###
|
||||
|
||||
# -- Components
|
||||
Form = require "../components/form"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- Events
|
||||
onFormSubmit: (event, value) ->
|
||||
console.log "onFormSubmit", value
|
||||
|
||||
onFormError: (event, value) ->
|
||||
console.log "onFormChange", arguments
|
||||
|
||||
onFormValid: (event, value) ->
|
||||
console.log "onFormChange", arguments
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
attributes = [
|
||||
ref: "name", label: "Your Name", required: true
|
||||
,
|
||||
ref: "description", type: "textarea", label: "Description", value: "Doer"
|
||||
,
|
||||
ref: "years", type: "number", label: "Years"
|
||||
,
|
||||
ref: "twitter", label: "Nickname", disabled: true
|
||||
,
|
||||
type: "Button"
|
||||
]
|
||||
<section data-screen="form">
|
||||
<Form attributes={attributes}
|
||||
onSubmit={@onFormSubmit}
|
||||
onError={@onFormError}
|
||||
onValid={@onFormValid}
|
||||
/>
|
||||
</section>
|
|
@ -1,42 +0,0 @@
|
|||
@import url("http://fonts.googleapis.com/css?family=Roboto:200,300,700")
|
||||
|
||||
// -- Colors
|
||||
COLOR = #222222
|
||||
BACKGROUND = #F5F5F5
|
||||
THEME = #00bcd4
|
||||
|
||||
WHITE = #ffffff
|
||||
PRIMARY = rgb(255, 64, 129)
|
||||
CANCEL = #f44336
|
||||
|
||||
// -- Fonts
|
||||
FONT_FAMILY = "Roboto", "Helvetica Neue", "Helvetica", "sans-serif"
|
||||
FONT_SIZE = 16px
|
||||
FONT_SIZE_TINY = 80%
|
||||
FONT_SIZE_SMALL = 90%
|
||||
FONT_SIZE_NORMAL = 100%
|
||||
FONT_SIZE_BIG = 120%
|
||||
FONT_WEIGHT_THIN = 200
|
||||
FONT_WEIGHT_NORMAL = 300
|
||||
FONT_WEIGHT_BOLD = 700
|
||||
|
||||
// -- Sizes
|
||||
UNIT = 4rem
|
||||
SPACE = (UNIT * 0.29)
|
||||
OFFSET = (UNIT * 1.35)
|
||||
HEADER_HEIGHT = 33vh
|
||||
|
||||
BUTTON_HEIGHT = (2.5 * SPACE)
|
||||
BUTTON_CIRCLE_HEIGHT = (2.75 * SPACE)
|
||||
BORDER_RADIUS = (SPACE / 2)
|
||||
H1_SHADOW = (SPACE / 6) (SPACE / 6) rgba(0,0,0,0.2)
|
||||
|
||||
// -- Shadows
|
||||
HEADER_SHADOW = 0 2px 5px rgba(0,0,0,0.26)
|
||||
BUTTON_SHADOW = 0 1px 6px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.24)
|
||||
|
||||
|
||||
// -- Animations
|
||||
ANIMATION_DURATION = 450ms
|
||||
ANIMATION_EASE = cubic-bezier(.55,0,.1,1)
|
||||
ANIMATION_DELAY = (ANIMATION_DURATION / 5)
|
|
@ -1,21 +0,0 @@
|
|||
body
|
||||
font-family : FONT_FAMILY
|
||||
font-size : FONT_SIZE
|
||||
font-weight : FONT_WEIGHT_NORMAL
|
||||
color : COLOR
|
||||
background-color : BACKGROUND
|
||||
a
|
||||
color : WHITE
|
||||
h1, h2, h3, h4, h5, h6
|
||||
font-weight : FONT_WEIGHT_NORMAL
|
||||
h1
|
||||
font-size : SIZE = (1.75 * FONT_SIZE_NORMAL)
|
||||
line-height : SIZE
|
||||
h2
|
||||
font-size : (1.5 * FONT_SIZE_NORMAL)
|
||||
|
||||
// -- Classes
|
||||
.scroll
|
||||
overflow-x : hidden
|
||||
overflow-y : scroll
|
||||
-webkit-overflow-scrolling : touch
|
|
@ -1,30 +0,0 @@
|
|||
button, .button
|
||||
font-size : FONT_SIZE_BIG
|
||||
font-weight : FONT_WEIGHT_BOLD
|
||||
line-height : BUTTON_HEIGHT
|
||||
text-align : center
|
||||
border : none
|
||||
overflow : hidden
|
||||
transition-property opacity, background-color, box-shadow
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
|
||||
&:not(.circle)
|
||||
height : BUTTON_HEIGHT
|
||||
max-height : BUTTON_HEIGHT
|
||||
width : auto
|
||||
|
||||
&.circle
|
||||
width : SIZE = BUTTON_CIRCLE_HEIGHT
|
||||
height : SIZE
|
||||
font-size : FONT_SIZE_BIG
|
||||
line-height : SIZE
|
||||
border-radius : SIZE
|
||||
box-shadow BUTTON_SHADOW
|
||||
&:hover, &:active
|
||||
box-shadow BUTTON_SHADOW, inset 0 0 0 UNIT alpha(WHITE, 15%)
|
||||
|
||||
// -- Colors
|
||||
&:not([disabled])
|
||||
&.primary
|
||||
background-color : PRIMARY
|
|
@ -1,16 +0,0 @@
|
|||
form
|
||||
background-color : WHITE
|
||||
padding : SPACE
|
||||
// -- Classes
|
||||
&.session
|
||||
max-width : 25vw
|
||||
> *
|
||||
margin-bottom : (SPACE / 2)
|
||||
|
||||
h1
|
||||
padding : 0
|
||||
input
|
||||
font-size : FONT_SIZE_BIG !important
|
||||
a
|
||||
text-align : center
|
||||
font-size : FONT_SIZE_TINY
|
|
@ -1,60 +0,0 @@
|
|||
header
|
||||
z-index : 2
|
||||
position : fixed
|
||||
height : HEADER_HEIGHT
|
||||
width : 100vw
|
||||
color : WHITE
|
||||
background-color : THEME
|
||||
transition-property height, transform, box-shadow
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
> img
|
||||
width : SIZE = (UNIT / 1.5)
|
||||
height : SIZE
|
||||
margin : 0 ((OFFSET - SIZE) / 2)
|
||||
border-radius : SIZE
|
||||
background-color : alpha(WHITE, 25%)
|
||||
box-shadow 0 0 0 (SIZE / 10) alpha(WHITE, 15%)
|
||||
h1
|
||||
padding : (UNIT / 2) 0
|
||||
text-transform : Capitalize
|
||||
transition all ANIMATION_DURATION ANIMATION_EASE
|
||||
nav
|
||||
&[data-role="text"]
|
||||
&:first-child
|
||||
display : block
|
||||
font-size : FONT_SIZE_TINY
|
||||
transition all ANIMATION_DURATION ANIMATION_EASE
|
||||
|
||||
&[data-role="circle"]
|
||||
position : absolute
|
||||
right : OFFSET
|
||||
bottom : -(BUTTON_CIRCLE_HEIGHT / 2)
|
||||
> *
|
||||
margin-left : SPACE
|
||||
|
||||
// -- States
|
||||
> *
|
||||
transition all ANIMATION_DURATION ANIMATION_EASE
|
||||
&.expanded
|
||||
height : 100vh
|
||||
&.disabled
|
||||
delayChild index, 2 for index in (0..3)
|
||||
|
||||
> *
|
||||
opacity : 0
|
||||
transform translateY(-10vh)
|
||||
|
||||
// -- Effects
|
||||
|
||||
.scrolling &
|
||||
height : (HEADER_HEIGHT / 2)
|
||||
box-shadow : HEADER_SHADOW
|
||||
transform translateY(-(SPACE))
|
||||
h1
|
||||
padding : 0
|
||||
nav
|
||||
&[data-role="text"]
|
||||
&:first-child
|
||||
transform translateY(-10vh)
|
||||
opacity : 0
|
|
@ -1,65 +0,0 @@
|
|||
[data-component-input]
|
||||
position : relative
|
||||
margin-bottom : SPACE
|
||||
|
||||
input, label
|
||||
font-size : FONT_SIZE_NORMAL
|
||||
font-weight : FONT_WEIGHT_NORMAL
|
||||
|
||||
input
|
||||
display : block
|
||||
padding : (SPACE / 2) 0
|
||||
width : 100%
|
||||
color : COLOR
|
||||
border : none
|
||||
border-bottom : 1px solid lighten(COLOR, 75%)
|
||||
// -- Attributes
|
||||
&:focus
|
||||
outline : none
|
||||
~ .bar:before, ~ .bar:after
|
||||
width : 50%
|
||||
&:focus ~ label, &:valid ~ label
|
||||
top : -(SPACE / 2)
|
||||
font-size : FONT_SIZE_TINY
|
||||
color : THEME
|
||||
&:disabled
|
||||
border-bottom-style : dotted
|
||||
&:invalid
|
||||
border-bottom-color : CANCEL
|
||||
~ .bar:before, ~ .bar:after
|
||||
background-color : CANCEL
|
||||
|
||||
label
|
||||
position : absolute
|
||||
left : 0
|
||||
top : (SPACE / 2)
|
||||
color : lighten(COLOR, 75%)
|
||||
pointer-events : none
|
||||
transition-property top, font-size, color
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
|
||||
.bar
|
||||
position : relative
|
||||
display : block
|
||||
width : 100%
|
||||
&:before, &:after
|
||||
content : ''
|
||||
position : absolute
|
||||
height : 2px
|
||||
width : 0
|
||||
bottom : 0
|
||||
background-color : THEME
|
||||
transition-property width, background-color
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
&:before
|
||||
left : 50%
|
||||
&:after
|
||||
right : 50%
|
||||
|
||||
.error
|
||||
position : absolute
|
||||
bottom : -(SPACE)
|
||||
font-size : FONT_SIZE_TINY
|
||||
color : CANCEL
|
|
@ -1,2 +0,0 @@
|
|||
ul
|
||||
list-style: none
|
|
@ -1,16 +0,0 @@
|
|||
li
|
||||
margin-bottom : SPACE
|
||||
padding : (SPACE * 1.25)
|
||||
background-color : white
|
||||
box-shadow : HEADER_SHADOW
|
||||
&, & a
|
||||
color: COLOR
|
||||
img
|
||||
width : SIZE = (2.5 * SPACE)
|
||||
height : SIZE
|
||||
background-color : #dddddd
|
||||
border-radius : SIZE
|
||||
margin-right : SPACE
|
||||
|
||||
strong
|
||||
font-size : (1.25 * FONT_SIZE_NORMAL)
|
|
@ -1,35 +0,0 @@
|
|||
[data-loading]
|
||||
z-index : 2
|
||||
> div
|
||||
width : SIZE = (1.5 * UNIT)
|
||||
height : SIZE
|
||||
border-radius : SIZE
|
||||
&::after
|
||||
content : ""
|
||||
position : absolute
|
||||
width : SIZE
|
||||
height : SIZE
|
||||
transform scale(0.0)
|
||||
border-radius : SIZE
|
||||
background-color : THEME
|
||||
|
||||
SPEED = (3 * ANIMATION_DURATION)
|
||||
&::after
|
||||
animation LOADING SPEED infinite
|
||||
&:nth-child(n+1)
|
||||
margin-top : -(SIZE)
|
||||
&:nth-child(1)::after
|
||||
animation-delay (SPEED / 2.5)
|
||||
&:nth-child(2)::after
|
||||
animation-delay (SPEED / 5)
|
||||
|
||||
article &
|
||||
margin-top : HEADER_HEIGHT
|
||||
|
||||
// -- Classes
|
||||
&.absolute
|
||||
height : 100vh
|
||||
width : 100vw
|
||||
|
||||
&.relative
|
||||
position : relative
|
|
@ -1,15 +0,0 @@
|
|||
nav
|
||||
&[data-role="text"]
|
||||
font-size : FONT_SIZE_NORMAL
|
||||
> *
|
||||
text-transform : Capitalize
|
||||
transition opacity ANIMATION_DURATION ANIMATION_EASE
|
||||
&:not(.active)
|
||||
font-weight : FONT_WEIGHT_THIN
|
||||
opacity : 0.5
|
||||
&:hover, &:active, &.active
|
||||
opacity : 1
|
||||
&.active
|
||||
font-weight : FONT_WEIGHT_NORMAL
|
||||
&:not(:last-child)
|
||||
margin-right : SPACE
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
@todo
|
||||
*/
|
||||
|
||||
// -- KEYFRAMES
|
||||
@keyframes LOADING
|
||||
0%
|
||||
transform scale(0.0)
|
||||
100%
|
||||
transform scale(1.0)
|
||||
opacity: 0.1
|
||||
|
||||
// -- FUNCTIONS
|
||||
delayChild(child, increment)
|
||||
&:nth-child({child})
|
||||
transition-delay ((child + increment) * ANIMATION_DELAY)
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
@todo
|
||||
*/
|
||||
|
||||
[data-flex]
|
||||
display-flex()
|
||||
body&
|
||||
position : absolute
|
||||
left : 0
|
||||
top : 0
|
||||
bottom : 0
|
||||
width : 100%
|
||||
overflow : hidden
|
||||
|
||||
// -- Direction
|
||||
[data-flex^="horizontal"]
|
||||
flex-direction row
|
||||
[data-flex^="vertical"]
|
||||
flex-direction column
|
||||
|
||||
// -- Size
|
||||
[data-flex*="grow"]
|
||||
> *:not([data-column]):not([data-flex-grow])
|
||||
flex-grow 1
|
||||
[data-flex-grow="min"]
|
||||
flex-grow 0
|
||||
[data-flex-grow="max"]
|
||||
flex-grow 2
|
||||
|
||||
// -- Container properties
|
||||
[data-flex*="wrap"]
|
||||
flex-wrap wrap
|
||||
[data-flex*="center"]
|
||||
justify-content center
|
||||
align-content center
|
||||
align-items center
|
||||
[data-flex-justify="start"]
|
||||
justify-content flex-start
|
||||
[data-flex-justify="center"]
|
||||
justify-content center
|
||||
[data-flex-justify="end"]
|
||||
justify-content flex-end
|
||||
[data-flex-content="start"]
|
||||
align-content flex-start
|
||||
[data-flex-content="center"]
|
||||
align-content center
|
||||
[data-flex-content="end"]
|
||||
align-content flex-end
|
||||
[data-flex-items="center"]
|
||||
align-items center
|
||||
[data-flex-items="start"]
|
||||
align-items flex-start
|
||||
[data-flex-items="end"]
|
||||
align-items flex-end
|
||||
|
||||
// -- Children properties
|
||||
[data-flex-order="first"]
|
||||
order: -1
|
||||
|
||||
[data-flex-order="last"]
|
||||
order: 999999
|
|
@ -1,211 +0,0 @@
|
|||
// normalize v3.0.2 | MIT License | git.io/normalize
|
||||
|
||||
html
|
||||
font-family sans-serif
|
||||
-ms-text-size-adjust 100%
|
||||
-webkit-text-size-adjust 100%
|
||||
|
||||
body
|
||||
margin 0
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
|
||||
nav, section, summary
|
||||
display block
|
||||
|
||||
audio, canvas, progress, video
|
||||
display inline-block
|
||||
vertical-align baseline
|
||||
|
||||
audio
|
||||
&:not([controls])
|
||||
display none
|
||||
height 0
|
||||
|
||||
[hidden], template
|
||||
display none
|
||||
|
||||
a
|
||||
background-color transparent
|
||||
&:active, &:hover
|
||||
outline 0
|
||||
|
||||
abbr[title]
|
||||
border-bottom 1px dotted
|
||||
|
||||
b, strong
|
||||
font-weight bold
|
||||
|
||||
dfn
|
||||
font-style italic
|
||||
|
||||
h1
|
||||
font-size 2em
|
||||
margin 0.67em 0
|
||||
|
||||
mark
|
||||
background #ff0
|
||||
color #000
|
||||
|
||||
small
|
||||
font-size 80%
|
||||
|
||||
sub, sup
|
||||
font-size 75%
|
||||
line-height 0
|
||||
position relative
|
||||
vertical-align baseline
|
||||
|
||||
sup
|
||||
top -0.5em
|
||||
|
||||
sub
|
||||
bottom -0.25em
|
||||
|
||||
img
|
||||
border: 0
|
||||
|
||||
svg
|
||||
&:not(:root)
|
||||
overflow hidden
|
||||
|
||||
figure
|
||||
border: 0
|
||||
|
||||
hr
|
||||
-moz-box-sizing content-box
|
||||
box-sizing content-box
|
||||
height 0
|
||||
|
||||
pre
|
||||
overflow auto
|
||||
|
||||
code, kbd, pre, samp
|
||||
font-family monospace, monospace
|
||||
font-size 1em
|
||||
|
||||
button, input, optgroup, select, textarea
|
||||
color inherit
|
||||
font inherit
|
||||
margin 0
|
||||
|
||||
button
|
||||
overflow visible
|
||||
|
||||
button, select
|
||||
text-transform none
|
||||
|
||||
button, html input[type="button"], input[type="reset"], input[type="submit"]
|
||||
-webkit-appearance button
|
||||
cursor pointer
|
||||
|
||||
button[disabled], html input[disabled]
|
||||
cursor default
|
||||
|
||||
button::-moz-focus-inner, input::-moz-focus-inner
|
||||
border 0
|
||||
padding 0
|
||||
|
||||
input
|
||||
line-height normal
|
||||
|
||||
input[type="checkbox"], input[type="radio"]
|
||||
box-sizing border-box
|
||||
padding 0
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button
|
||||
height auto
|
||||
|
||||
input[type="search"]
|
||||
-webkit-appearance textfield
|
||||
-moz-box-sizing content-box
|
||||
-webkit-box-sizing content-box
|
||||
box-sizing content-box
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration
|
||||
-webkit-appearance none
|
||||
|
||||
fieldset
|
||||
border 1px solid #c0c0c0
|
||||
margin 0 2px
|
||||
padding 0.35em 0.625em 0.75em
|
||||
|
||||
legend
|
||||
border 0
|
||||
padding 0
|
||||
|
||||
textarea
|
||||
overflow auto
|
||||
|
||||
optgroup
|
||||
font-weight bold
|
||||
|
||||
table
|
||||
border-collapse collapse
|
||||
border-spacing 0
|
||||
|
||||
td, th
|
||||
padding 0
|
||||
|
||||
|
||||
// -- App ----------------------------------------------------------------------
|
||||
a,abbr,address,article,aside,audio,b,blockquote,body,caption,cite,code,dd,del,dfn,dialog,div,dl,dt,em,fieldset,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video
|
||||
border: 0
|
||||
margin: 0
|
||||
outline: 0
|
||||
padding: 0
|
||||
|
||||
*, *:before, *:after
|
||||
margin: 0
|
||||
padding: 0
|
||||
box-sizing: border-box
|
||||
|
||||
html
|
||||
position: absolute
|
||||
height: 100%
|
||||
width: 100%
|
||||
margin: 0
|
||||
padding: 0
|
||||
overflow: hidden
|
||||
|
||||
body
|
||||
width: 100%
|
||||
height: 100%
|
||||
margin: 0
|
||||
padding: 0
|
||||
-webkit-touch-callout: none
|
||||
-webkit-user-select: none
|
||||
-moz-user-select: moz-none
|
||||
user-select: none
|
||||
overflow: hidden
|
||||
|
||||
*
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
|
||||
|
||||
h1, h2, h3, h4, h5, h6, label, p, button, abbr, a
|
||||
-webkit-font-smoothing: subpixel-antialiased
|
||||
font-smoothing: subpixel-antialiased
|
||||
-webkit-text-size-adjust: 100%
|
||||
-ms-text-size-adjust: 100%
|
||||
text-size-adjust: 100%
|
||||
|
||||
span
|
||||
-webkit-font-smoothing: antialiased
|
||||
font-smoothing: antialiased
|
||||
|
||||
a
|
||||
text-decoration: none
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0)
|
||||
|
||||
::-webkit-scrollbar
|
||||
width: 0px
|
||||
height: 0px
|
||||
|
||||
input, button
|
||||
-webkit-appearance: none
|
||||
-moz-appearance: none
|
||||
appearance: none
|
||||
-webkit-touch-callout: none
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0)
|
||||
outline: none
|
|
@ -1,12 +0,0 @@
|
|||
[data-screen]
|
||||
position : absolute
|
||||
left : 0
|
||||
top : 0
|
||||
height : 100vh
|
||||
width : 100vw
|
||||
transition transform ANIMATION_DURATION ANIMATION_EASE
|
||||
|
||||
> section
|
||||
height : 100vh
|
||||
padding : (HEADER_HEIGHT + (2 * OFFSET)) OFFSET OFFSET OFFSET
|
||||
padding : (HEADER_HEIGHT + (UNIT + SPACE)) UNIT UNIT UNIT
|
|
@ -1 +0,0 @@
|
|||
[data-screen="console"]
|
|
@ -1,2 +0,0 @@
|
|||
[data-screen="session"]
|
||||
height : 100vh
|
Loading…
Reference in New Issue