Typescript definitions validation (#1163)

* initial attempt to validate ts definitions

* ignore .vscode

* Add other spect & some fixes:

- Add target prop to Button
- Add value prop to MenuItem
- Make label optional in Tab
- Improve Tooltip types

* Add tsc validation to travis

* fix typo in travis build step
old
Panjie Setiawan Wicaksono 2017-09-01 22:51:41 +07:00 committed by Javi Velasco
parent 8b7fc07f82
commit 91cb46db84
37 changed files with 1801 additions and 8 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ node_modules
npm-debug.log
.idea
.DS_Store
.vscode

View File

@ -8,4 +8,5 @@ node_js:
script:
- npm run lint
- npm run ts
- npm test

View File

@ -1,8 +1,9 @@
import * as React from "react";
import ReactToolbox from "../index";
import { RippleProps } from '../ripple/index';
import { ButtonBaseProps, ButtonTheme } from './base';
export interface ButtonProps extends ButtonBaseProps {
export interface ButtonProps extends ButtonBaseProps, RippleProps {
/**
* If true, the button will have a flat look.
* @default false
@ -31,6 +32,10 @@ export interface ButtonProps extends ButtonBaseProps {
* @default false
*/
raised?: boolean;
/**
* Passed down to the root element
*/
target?: string;
/**
* Classnames object defining the component style.
*/

View File

@ -132,7 +132,7 @@ export interface InputProps extends ReactToolbox.Props {
/**
* The number of rows the multiline input field has.
*/
rows?:number;
rows?: number;
/**
* Classnames object defining the component style.
*/

View File

@ -59,6 +59,10 @@ export interface MenuItemProps extends ReactToolbox.Props {
* Classnames object defining the component style.
*/
theme?: MenuItemTheme;
/**
* Passed down to the root element
*/
value?: any;
}
export class MenuItem extends React.Component<MenuItemProps, {}> { }

View File

@ -52,9 +52,9 @@ export interface TabProps extends ReactToolbox.Props {
*/
icon?: React.ReactNode;
/**
* Label text for navigation header. Required.
* Label text for navigation header.
*/
label: string;
label?: string;
/**
* Callback function that is fired when the tab is activated.
*/

View File

@ -70,10 +70,21 @@ declare class TooltipComponent<P, S> extends React.Component<P, S> {
props: P & TooltipProps;
}
interface TooltippedComponentClass<P> extends TooltipProps {
declare interface TooltippedComponentClass<P> extends TooltipProps {
new (props?: P, context?: any): TooltipComponent<P, any>;
}
export function Tooltip<P>(componentClass: React.ComponentClass<P>): TooltippedComponentClass<P>;
declare interface TooltipOptions {
className?: string;
delay?: number;
hideOnClick?: boolean;
passthrough?: boolean;
showOnClick?: boolean;
position?: 'bottom' | 'horizontal' | 'left' | 'right' | 'top' | 'vertical'
}
export default Tooltip;
declare type tooltipHOC<P> = (componentClass: React.ComponentClass<P>) => TooltippedComponentClass<P>
export function tooltipFactory<P>(options?: TooltipOptions): tooltipHOC<P>;
export default function Tooltip<P>(component: React.ReactType): TooltippedComponentClass<P>;

View File

@ -34,6 +34,8 @@
"react-transition-group": "^1.1.3"
},
"devDependencies": {
"@types/node": "^7.0.4",
"@types/react": "^15.0.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-eslint": "^7.2.3",
@ -86,13 +88,15 @@
"react-transform-hmr": "^1.0.4",
"redbox-react": "^1.3.6",
"rimraf": "^2.6.1",
"sinon": "^2.0.0-pre.2",
"style-loader": "^0.18.1",
"stylelint": "^7.10.1",
"stylelint-config-standard": "^16.0.0",
"stylelint-order": "^0.4.4",
"typescript": "^2.1.5",
"webpack": "^2.6.0",
"webpack-dev-middleware": "^1.10.2",
"webpack-hot-middleware": "^2.18.0"
"webpack-hot-middleware": "^2.18.0"
},
"engines": {
"node": ">= 6"
@ -111,6 +115,8 @@
"prepublish": "npm run build",
"release": "bumped release",
"start": "cross-env NODE_ENV=development UV_THREADPOOL_SIZE=100 node ./server",
"ts": "tsc",
"tsd": "cpx \"./components/**/*.d.ts\" ./lib"
"test": "jest",
"test:watch": "jest --watch --no-watchman"
},

22
spec/ts/app_bar.tsx Normal file
View File

@ -0,0 +1,22 @@
import * as React from 'react';
import AppBar, {AppBar as NamedAppBar} from 'components/app_bar';
const AppBarTest: React.SFC<any> = () => (
<section>
<h5>AppBar</h5>
<br />
<AppBar title='Title' />
<br />
<AppBar leftIcon='menu' title='Title' />
<br />
<AppBar leftIcon='arrow_back' title='Title' rightIcon='close' />
<br />
<AppBar>
Custom content
</AppBar>
<br/>
<NamedAppBar title='NamedAppBar' />
</section>
)
export default AppBarTest;

96
spec/ts/autocomplete.tsx Normal file
View File

@ -0,0 +1,96 @@
import * as React from 'react';
import Autocomplete from 'components/autocomplete';
class AutocompleteTest extends React.Component<any, any> {
state: any = {
simple: 'Spain',
simpleShowAll: 'England',
multipleArray: ['ES-es', 'TH-th'],
multipleObject: {'ES-es': 'Spain', 'TH-th': 'Thailand'},
countriesArray: ['Spain', 'England', 'USA', 'Thailand', 'Tongo', 'Slovenia'],
countriesObject: {
'EN-gb': 'England',
'EN-en': 'United States of America', 'EN-nz': 'New Zealand'
}
};
handleFocus = (event: React.MouseEvent<any>) => {
console.log('This is focused');
console.log(event);
};
handleMultipleArrayChange = (value: any) => {
this.setState({
multipleArray: value,
countriesObject: {
...this.state.countriesObject,
...(value[0] && !this.state.countriesObject[value[0]]) ? {[value[0]]: value[0]} : {}
}
});
};
handleMultipleObjectChange = (value: any) => {
this.setState({
multipleObject: value
});
};
handleSimpleChange = (value: any) => {
this.setState({simple: value});
};
handleSimpleShowAllChange = (value: any) => {
this.setState({simpleShowAll: value});
};
render () {
return (
<section>
<h5>Autocomplete</h5>
<p>You can have a multiple or simple autocomplete.</p>
<Autocomplete
allowCreate
keepFocusOnChange
label="Pick multiple elements..."
onFocus={this.handleFocus}
onChange={this.handleMultipleArrayChange}
source={this.state.countriesObject}
suggestionMatch="anywhere"
value={this.state.multipleArray}
/>
<Autocomplete
allowCreate
label="Pick multiple elements with object value..."
onChange={this.handleMultipleObjectChange}
showSelectedWhenNotInSource
source={this.state.countriesObject}
suggestionMatch="anywhere"
value={this.state.multipleObject}
/>
<Autocomplete
hint="Elements up to you..."
label="Choose a country"
multiple={false}
onChange={this.handleSimpleChange}
source={this.state.countriesArray}
value={this.state.simple}
/>
<Autocomplete
hint="Elements up to you..."
label="Choose a country (showing all suggestions)"
multiple={false}
onChange={this.handleSimpleShowAllChange}
showSuggestionsWhenValueIsSet
source={this.state.countriesArray}
value={this.state.simpleShowAll}
/>
</section>
);
}
}
export default AutocompleteTest;

22
spec/ts/avatar.tsx Normal file
View File

@ -0,0 +1,22 @@
import * as React from 'react';
import Avatar from '../../components/avatar';
import GithubIcon from './github_icon';
const AvatarTest = () => (
<section>
<h5>Avatars</h5>
<p>Provide an image source or object, a font icon, children or a title to use its first letter.</p>
<Avatar style={{ backgroundColor: 'deepskyblue' }} icon="folder" alt="icon folder" />
<Avatar icon={<GithubIcon />} />
<Avatar><img src="https://placeimg.com/80/80/animals" alt="foobar" /></Avatar>
<Avatar image="https://placeimg.com/80/80/animals" alt="foobar" />
<Avatar
alt="foobar"
image="http://www.thewrap.com/wp-content/uploads/2015/08/margot-robbie-harley-quinn_main.jpg" cover
/>
<Avatar title="Javier" />
<Avatar style={{ backgroundColor: 'yellowgreen' }}><GithubIcon /></Avatar>
</section>
);
export default AvatarTest;

51
spec/ts/button.tsx Normal file
View File

@ -0,0 +1,51 @@
import * as React from 'react';
import GithubIcon from './github_icon';
import { Button, IconButton, BrowseButton } from '../../components/button';
const ButtonTest = () => (
<section>
<h5>Buttons</h5>
<p>lorem ipsum...</p>
<Button href="http://github.com/javivelasco" target="_blank" raised>
<GithubIcon /> Github
</Button>
<Button icon="bookmark" label="Bookmark" accent onRippleEnded={rippleEnded} />
<Button icon="bookmark" label="Bookmark" raised primary rippleMultiple={false} onRippleEnded={rippleEnded} />
<Button icon="inbox" label="Inbox" flat />
<Button icon="add" floating />
<Button icon="add" floating primary />
<Button href="http://github.com/javivelasco" target="_blank" icon="link" floating accent />
<Button icon="add" floating primary disabled />
<Button icon="add" floating accent mini />
<IconButton icon="favorite" accent />
<IconButton icon="favorite" inverse />
<IconButton icon="favorite" />
<IconButton icon="favorite" disabled />
<IconButton primary><GithubIcon /></IconButton>
<Button icon="add" label="Add this" flat primary />
<Button icon="add" label="Add this" flat disabled />
<h5>Icon Button Alignment</h5>
<p>
Icon Buttons should align in the vertical center, to see this we need to
put them next to text or highlight thier background color.
</p>
<IconButton icon="menu" style={{ backgroundColor: 'red' }} inverse />
<span style={{ verticalAlign: 'middle' }}>Menu</span>
<IconButton icon="menu" />
<span style={{ verticalAlign: 'middle' }}>Menu</span>
<IconButton><GithubIcon /></IconButton>
<span style={{ verticalAlign: 'middle' }}>Github</span>
<h5>Browse Button</h5>
<br />
<BrowseButton icon="folder_open" label="BROWSE" raised primary />
&nbsp;
<BrowseButton label="BROWSE" raised />
</section>
);
function rippleEnded() {
console.log('Ripple animation ended!');
}
export default ButtonTest;

247
spec/ts/card.tsx Normal file
View File

@ -0,0 +1,247 @@
/* eslint-disable react/prop-types */
import * as React from 'react';
import Button, { IconButton } from '../../components/button';
import Card, { CardActions, CardMedia, CardText, CardTitle } from '../../components/card';
const style = require('../style.css');
const dummyText = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.';
const Spacer: React.SFC<any> = () => <div style={{ display: 'flex', flex: '1 1 auto' }} />;
const CardList: React.SFC<any> = ({ children }) => <ul className={style.cardsGroup}>{children}</ul>;
const CardListItem: React.SFC<any> = ({ component, name }) => (
<li className={style.cardItem}>
<div className={style.cardItemContent}>{component}</div>
<div className={style.cardItemName}>{name}</div>
</li>
);
const cards: any = {
basic: [{
name: 'Basic Card',
component: (
<Card className={style.card}>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardText>{dummyText}</CardText>
<CardActions>
<Button label="Action 1" />
<Button label="Action 2" />
</CardActions>
</Card>
),
}, {
name: 'Raised Card',
component: (
<Card raised className={style.card}>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardText>{dummyText}</CardText>
<CardActions>
<Button label="Action 1" />
<Button label="Action 2" />
</CardActions>
</Card>
),
}, {
name: 'Customized header',
component: (
<Card className={style.card}>
<CardTitle
title={<u>Title component</u>}
subtitle={<u>Subtitle component</u>}
/>
<CardText>{dummyText}</CardText>
<CardActions>
<Button label="Action 1" />
<Button label="Action 2" />
</CardActions>
</Card>
),
}],
media: [{
name: '16:9 Card Media Area',
component: (
<Card className={style.card}>
<CardMedia
aspectRatio="wide"
className={style.primary}
>
<CardTitle>Basic Card</CardTitle>
</CardMedia>
<CardTitle subtitle="You can also use a subtitle like this" />
<CardText>{dummyText}</CardText>
</Card>
),
}, {
name: '16:9 Card Media Image',
component: (
<Card className={style.card}>
<CardMedia
aspectRatio="wide"
image="https://placeimg.com/800/450/nature"
/>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardText>{dummyText}</CardText>
</Card>
),
}, {
name: 'Square Media Card',
component: (
<Card className={style.card}>
<CardMedia
contentOverlay
aspectRatio="square"
image="https://placeimg.com/700/700/nature"
>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardActions>
<Button inverse label="Action 1" />
<Button inverse label="Action 2" />
</CardActions>
</CardMedia>
</Card>
),
}],
avatar: [{
name: 'Avatar Card Title',
component: (
<Card className={style.card}>
<CardTitle
avatar="https://placeimg.com/80/80/animals"
title="Avatar Card"
subtitle="An awesome basic card"
/>
<CardMedia
aspectRatio="wide"
image="https://placeimg.com/800/450/nature"
/>
<CardActions style={{ justifyContent: 'flex-end' }}>
<IconButton icon="share" />
<IconButton icon="favorite" />
</CardActions>
</Card>
),
}, {
name: 'Video in a card',
component: (
<Card className={style.card}>
<CardTitle
avatar="https://placeimg.com/80/80/animals"
title="Avatar Card"
subtitle="An awesome basic card"
/>
<CardMedia
aspectRatio="wide"
>
<iframe width="1280" height="720" src="https://www.youtube.com/embed/sGbxmsDFVnE?rel=0&amp;showinfo=0" frameBorder="0" allowFullScreen />
</CardMedia>
<CardActions style={{ justifyContent: 'flex-end' }}>
<IconButton icon="report_problem" />
<Spacer />
<IconButton icon="share" />
<IconButton icon="favorite" />
</CardActions>
</Card>
),
}],
horizontal: [{
name: 'Alternative Layout Example',
component: (
<Card className={style.card}>
<div className={style.cardRow}>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardMedia
className={style.media}
image="https://placeimg.com/400/400/nature"
/>
</div>
<CardActions>
<Button label="Action 1" />
<Button label="Action 2" />
</CardActions>
</Card>
),
}, {
name: 'Another Variation',
component: (
<Card>
<div className={style.cardRow}>
<CardTitle
title="Title goes here"
subtitle="Subtitle here"
/>
<CardMedia
className={style.mediaLarge}
image="https://placeimg.com/400/400/nature"
/>
</div>
</Card>
),
}],
small: [{
name: 'Small Media Card',
component: (
<Card>
<CardMedia
aspectRatio="square"
image="https://placeimg.com/400/400/nature"
>
<CardTitle>Test</CardTitle>
</CardMedia>
<CardActions style={{ justifyContent: 'center' }}>
<IconButton icon="thumb_down" />
<IconButton icon="thumb_up" />
<IconButton icon="turned_in_not" />
</CardActions>
</Card>
),
}, {
name: 'Small Media Controls',
component: (
<Card style={{ width: '140px' }}>
<CardMedia
contentOverlay
aspectRatio="square"
image="https://placeimg.com/280/280/people"
>
<CardActions style={{ justifyContent: 'center' }}>
<IconButton inverse icon="fast_rewind" />
<IconButton inverse icon="play_arrow" />
<IconButton inverse icon="fast_forward" />
</CardActions>
</CardMedia>
</Card>
),
}],
};
const CardTest = () => (
<section>
<h5>Cards</h5>
<p>You have multiple options for cards. Combine different subcomponents to create your own:</p>
<div className={style.cards}>
{Object.keys(cards).map(key => (
<CardList key={key}>
{cards[key].map((demo: any, i: any) => <CardListItem key={key + i} {...demo} />)}
</CardList>
))}
</div>
</section>
);
export default CardTest;

56
spec/ts/checkbox.tsx Normal file
View File

@ -0,0 +1,56 @@
import * as React from 'react';
import Checkbox from '../../components/checkbox';
class CheckboxTest extends React.Component<any, any> {
state = {
checkbox_1: true,
checkbox_2: false,
checkbox_3: true,
};
handleChange = (field: any, value: any) => {
this.setState({ ...this.state, [field]: value });
};
handleFocus = () => {
console.log('Focused');
};
handleBlur = () => {
console.log('Blur');
};
render() {
return (
<section>
<h5>Checkbox</h5>
<p style={{ marginBottom: '10px' }}>Lorem ipsum...</p>
<Checkbox
checked={this.state.checkbox_1}
label="Checked checkbox"
onChange={this.handleChange.bind(this, 'checkbox_1')}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
<Checkbox
checked={this.state.checkbox_2}
label="Not checked checkbox"
onChange={this.handleChange.bind(this, 'checkbox_2')}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
<Checkbox
checked={this.state.checkbox_3}
label="Disabled checkbox"
disabled
onChange={this.handleChange.bind(this, 'checkbox_3')}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
/>
</section>
);
}
}
export default CheckboxTest;

67
spec/ts/chip.tsx Normal file
View File

@ -0,0 +1,67 @@
import * as React from 'react';
import Avatar from '../../components/avatar';
import Chip from '../../components/chip';
const style = require('../style.css');
class ChipTest extends React.Component<any, any> {
state = {
deleted: false,
};
handleDeleteClick = () => {
this.setState({
deleted: true,
});
};
render() {
return (
<section>
<h5>Chips</h5>
<p>Chips can be deletable and have an avatar.</p>
<Chip>Example chip</Chip>
<Chip>
<span style={{ textDecoration: 'line-through' }}>Standard</span>
<strong>Custom</strong> chip <small>(custom markup)</small>
</Chip>
{
this.state.deleted ? null : (
<Chip
deletable
onDeleteClick={this.handleDeleteClick}
>
Deletable Chip
</Chip>
)
}
<Chip>
<Avatar style={{ backgroundColor: 'deepskyblue' }} icon="folder" />
<span>Avatar Chip</span>
</Chip>
<Chip>
<Avatar title="A" /><span>Initial chip</span>
</Chip>
<Chip>
<Avatar><img src="https://placeimg.com/80/80/animals" /></Avatar>
<span>Image contact chip</span>
</Chip>
<div className={style.chipTruncateWrapper}>
<Chip deletable>
Truncated chip with long label. Lorem ipsum Amet quis mollit Excepteur id dolore.
</Chip>
</div>
</section>
);
}
}
export default ChipTest;

95
spec/ts/dialog.tsx Normal file
View File

@ -0,0 +1,95 @@
import * as React from 'react';
import Button from '../../components/button';
import Dialog from '../../components/dialog';
import Dropdown from '../../components/dropdown';
const dialogTypes = [
{ value: 'small', label: 'small' },
{ value: 'normal', label: 'normal' },
{ value: 'large', label: 'large' },
{ value: 'fullscreen', label: 'fullscreen' },
];
class DialogTest extends React.Component<any, any> {
state = {
active: false,
type: 'normal',
};
handleToggle = () => {
this.setState({
active: !this.state.active,
});
};
changeDialogType = (value: any) => {
this.setState({ type: value });
};
actions = [
{ label: 'Disagree', primary: true, onClick: this.handleToggle },
{ label: 'Agree', primary: true, onClick: this.handleToggle },
];
render() {
return (
<section>
<h5>Dialog</h5>
<p>lorem ipsum...</p>
<Dropdown
label="Dialog Type"
auto
onChange={this.changeDialogType}
source={dialogTypes}
value={this.state.type}
/>
<Button label="Show Dialog" raised primary onClick={this.handleToggle} />
<ContextComponent>
<Dialog
actions={this.actions}
active={this.state.active}
type={this.state.type}
title="Use Google's location service?"
onOverlayClick={this.handleToggle}
onEscKeyDown={this.handleToggle}
>
<p>Let Google help apps <strong>determine location</strong>. This means sending anonymous location data to Google, even when no apps are running.</p>
<DialogChild />
</Dialog>
</ContextComponent>
</section>
);
}
}
class ContextComponent extends React.Component<any, any> {
static propTypes = {
children: React.PropTypes.any,
};
static childContextTypes = {
message: React.PropTypes.string,
}
getChildContext() {
return {
message: 'Hi, I\'m the top container',
};
}
render() {
return this.props.children;
}
}
class DialogChild extends React.Component<any, any> {
static contextTypes = {
message: React.PropTypes.string,
}
render() {
return <p>This message comes from a parent: <strong>{this.context.message}</strong></p>;
}
}
export default DialogTest;

50
spec/ts/drawer.tsx Normal file
View File

@ -0,0 +1,50 @@
import * as React from 'react';
import Button from '../../components/button';
import Drawer from '../../components/drawer';
const style = require('../style.css');
class DrawerTest extends React.Component<any, any> {
state = {
leftActive: false,
rightActive: false,
};
handleToggleLeft = () => {
this.setState({ leftActive: !this.state.leftActive });
};
handleToggleRight = () => {
this.setState({ rightActive: !this.state.rightActive });
};
render() {
return (
<section>
<h5>Drawer</h5>
<p>You can navigate using a drawer to the left or right.</p>
<Drawer
active={this.state.leftActive}
className={style.drawer}
onOverlayClick={this.handleToggleLeft}
>
<h5>Officia deserunt mollit.</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</Drawer>
<Drawer active={this.state.rightActive} type="right">
<Button primary label="Close" onClick={this.handleToggleRight} />
</Drawer>
<nav>
<Button label="Drawer left" raised primary onClick={this.handleToggleLeft} />
<Button label="Drawer right" raised accent onClick={this.handleToggleRight} />
</nav>
</section>
);
}
}
export default DrawerTest;

82
spec/ts/dropdown.tsx Normal file
View File

@ -0,0 +1,82 @@
import * as React from 'react';
import Dropdown from '../../components/dropdown';
const style = require('../style.css');
const countries = [
{ value: 'EN-gb', label: 'England', img: 'http://' },
{ value: 'ES-es', label: 'Spain', img: 'http://' },
{ value: 'TH-th', label: 'Thailand', img: 'http://' },
{ value: 'EN-en', label: 'USA', img: 'http://' },
{ value: 'FR-fr', label: 'France', img: 'http://' },
];
class DropdownTest extends React.Component<any, any> {
state: any = {
dropdown4: 'TH-th',
};
handleChange = (dropdown: any, value: any) => {
console.log('selected', value);
const newState: any = {};
newState[dropdown] = value;
this.setState(newState);
};
customDropdownItem(data: any) {
return (
<div className={style.dropdownTemplate}>
<img className={style.dropdownTemplateImage} src={data.img} />
<div className={style.dropdownTemplateContent}>
<strong>{data.label}</strong>
<small>{data.value}</small>
</div>
</div>
);
}
render() {
return (
<section>
<h5>Dropdown</h5>
<p>lorem ipsum...</p>
<Dropdown
label="Country"
ref="dropdown1"
onChange={this.handleChange.bind(this, 'dropdown1')}
source={countries}
template={this.customDropdownItem}
value={this.state.dropdown1}
/>
<Dropdown
label="Country"
ref="dropdown4"
onChange={this.handleChange.bind(this, 'dropdown4')}
source={countries}
value={this.state.dropdown4}
/>
<Dropdown
disabled
ref="dropdown3"
label="Country"
onChange={this.handleChange.bind(this, 'dropdown3')}
source={countries}
/>
<Dropdown
label="Country"
ref="dropdown5"
onChange={this.handleChange.bind(this, 'dropdown5')}
source={countries}
value={this.state.dropdown5}
required
/>
</section>
);
}
}
export default DropdownTest;

17
spec/ts/font_icon.tsx Normal file
View File

@ -0,0 +1,17 @@
import * as React from 'react';
import FontIcon from '../../components/font_icon';
const FontIconTest = () => (
<section>
<h5>Font Icons</h5>
<p>lorem ipsum...</p>
<FontIcon value="add" alt="add icon" />
<FontIcon value="access_alarm" />
<FontIcon value="explore" alt="explore icon" />
<FontIcon value="zoom_in" alt="zoom icon" />
<FontIcon alt="input icon">input</FontIcon>
</section>
);
export default FontIconTest;

10
spec/ts/github_icon.tsx Normal file
View File

@ -0,0 +1,10 @@
import * as React from 'react';
const GithubIcon = () => (
<svg viewBox="0 0 284 277" aria-labelledby="title">
<title id="title">GitHub Icon</title>
<g><path d="M141.888675,0.0234927555 C63.5359948,0.0234927555 0,63.5477395 0,141.912168 C0,204.6023 40.6554239,257.788232 97.0321356,276.549924 C104.12328,277.86336 106.726656,273.471926 106.726656,269.724287 C106.726656,266.340838 106.595077,255.16371 106.533987,243.307542 C67.0604204,251.890693 58.7310279,226.56652 58.7310279,226.56652 C52.2766299,210.166193 42.9768456,205.805304 42.9768456,205.805304 C30.1032937,196.998939 43.9472374,197.17986 43.9472374,197.17986 C58.1953153,198.180797 65.6976425,211.801527 65.6976425,211.801527 C78.35268,233.493192 98.8906827,227.222064 106.987463,223.596605 C108.260955,214.426049 111.938106,208.166669 115.995895,204.623447 C84.4804813,201.035582 51.3508808,188.869264 51.3508808,134.501475 C51.3508808,119.01045 56.8936274,106.353063 65.9701981,96.4165325 C64.4969882,92.842765 59.6403297,78.411417 67.3447241,58.8673023 C67.3447241,58.8673023 79.2596322,55.0538738 106.374213,73.4114319 C117.692318,70.2676443 129.83044,68.6910512 141.888675,68.63701 C153.94691,68.6910512 166.09443,70.2676443 177.433682,73.4114319 C204.515368,55.0538738 216.413829,58.8673023 216.413829,58.8673023 C224.13702,78.411417 219.278012,92.842765 217.804802,96.4165325 C226.902519,106.353063 232.407672,119.01045 232.407672,134.501475 C232.407672,188.998493 199.214632,200.997988 167.619331,204.510665 C172.708602,208.913848 177.243363,217.54869 177.243363,230.786433 C177.243363,249.771339 177.078889,265.050898 177.078889,269.724287 C177.078889,273.500121 179.632923,277.92445 186.825101,276.531127 C243.171268,257.748288 283.775,204.581154 283.775,141.912168 C283.775,63.5477395 220.248404,0.0234927555 141.888675,0.0234927555" /></g>
</svg>
);
export default GithubIcon;

53
spec/ts/icon_menu.tsx Normal file
View File

@ -0,0 +1,53 @@
import * as React from 'react';
import { MenuItem, IconMenu, MenuDivider } from '../../components/menu';
class IconMenuTest extends React.Component<any, any> {
state: any = {
selected: undefined,
};
handleShow = () => {
console.log('Showing menu...');
};
handleHide = () => {
console.log('Hiding menu...');
};
handleSelect = (value: any) => {
console.log('Option selected', value);
this.setState({ selected: value });
};
handleItem = () => {
console.log('Refresh clicked');
};
render() {
return (
<section>
<h5>Icon Menus</h5>
<p>Although a menu can be used indepently with any component, we are providing a common use case with the icon menu.</p>
<IconMenu
icon="more_vert"
position="auto"
iconRipple
menuRipple
onShow={this.handleShow}
onHide={this.handleHide}
onSelect={this.handleSelect}
selectable
selected={this.state.selected}
>
<MenuItem onClick={this.handleItem} value="refresh" caption="Refresh" />
<MenuItem value="help" caption="Help & Feedback" />
<MenuItem value="settings" caption="Settings" />
<MenuDivider />
<MenuItem value="signout" caption="Sign out" disabled />
</IconMenu>
</section>
);
}
}
export default IconMenuTest;

43
spec/ts/input.tsx Normal file
View File

@ -0,0 +1,43 @@
import * as React from 'react';
import Input from '../../components/input';
class InputTest extends React.Component<any, any> {
state = {
normal: 'Tony Stark',
fixedLabel: '',
withIcon: '',
withCustomIcon: '',
withHintCustomIcon: '',
multilineHint: 'Long Description here',
multilineRows: 'A\n\B\nC\nD\nE\nF',
};
handleChange = (name: any, value: any) => {
this.setState({ ...this.state, [name]: value });
};
render() {
return (
<section>
<h5>Inputs</h5>
<p>lorem ipsum...</p>
<Input
type="text"
value={this.state.normal}
label="First Name" onChange={this.handleChange.bind(this, 'normal')}
maxLength={12}
/>
<Input type="email" value={this.state.fixedLabel} label="Label fixed" floating={false} onChange={this.handleChange.bind(this, 'fixedLabel')} />
<Input type="text" value="Read only" rows={1} label="Phone Number" />
<Input type="email" value={this.state.multilineHint} label="Description" hint="Enter Description" multiline onChange={this.handleChange.bind(this, 'multilineHint')} />
<Input type="text" value={this.state.multilineRows} label="Row Limited Description" hint="Enter Description" multiline rows={4} onChange={this.handleChange.bind(this, 'multilineRows')} />
<Input type="text" label="Disabled field" disabled />
<Input type="tel" value={this.state.withIcon} required label="With icon" onChange={this.handleChange.bind(this, 'withIcon')} icon="phone" />
<Input type="tel" value={this.state.withCustomIcon} label="With custom icon" onChange={this.handleChange.bind(this, 'withCustomIcon')} icon="favorite" />
<Input type="text" value={this.state.withHintCustomIcon} label="With Hint Text Icon" hint="Hint Text" onChange={this.handleChange.bind(this, 'withHintCustomIcon')} icon="share" />
</section>
);
}
}
export default InputTest;

13
spec/ts/link.tsx Normal file
View File

@ -0,0 +1,13 @@
import * as React from 'react';
import Link from '../../components/link';
const LinkTest = () => (
<section>
<h5>Links</h5>
<p>lorem ipsum...</p>
<Link label="Github" route="http://www.github.com" icon="bookmark" />
<Link label="Inbox" route="http://mail.google.com" icon="inbox" />
</section>
);
export default LinkTest;

190
spec/ts/list.tsx Normal file
View File

@ -0,0 +1,190 @@
import * as React from 'react';
import { ListCheckbox, ListSubHeader, List, ListItem, ListDivider, ListItemText, ListItemContent } from '../../components/list';
import { Button } from '../../components/button';
import Avatar from '../../components/avatar';
import FontIcon from '../../components/font_icon';
const listStyle = {
border: '1px solid #EEE',
display: 'inline-block',
minWidth: 340,
};
class ListTest extends React.Component<any, any> {
state: any = {
checkbox1: false,
checkbox2: true,
checkbox3: true,
};
handleCheckboxChange = (field: any) => {
const newState: any = {};
newState[field] = !this.state[field];
this.setState(newState);
};
render() {
return (
<section>
<h5>With simple text and icons</h5>
<p>This list can be used inside a Drawer for a list of options or as navigation.</p>
<div style={listStyle}>
<List selectable ripple>
<ListSubHeader caption="Contacts" />
<ListItem caption="Inbox" leftIcon="inbox" />
<ListItem caption="Outbox" selectable={false} ripple={false} leftIcon="send" />
<ListItem caption="Trash" leftIcon="delete" />
<ListItem caption="Spam" leftIcon="report" />
</List>
</div>
<h5>Two text lines, avatar and right icon</h5>
<p>Useful for a list of contacts or similar.</p>
<div style={listStyle}>
<List selectable ripple>
<ListSubHeader caption="Contacts" />
<ListItem
avatar="https://pbs.twimg.com/profile_images/614407428/s6pTalMzZs-nusCGWqoV.0_400x400.jpeg"
caption="Alfonso Rocha"
legend="Product Manager at Fon"
rightIcon="star"
/>
<ListItem
avatar="https://pbs.twimg.com/profile_images/693578804808278017/a5y4h8MN_400x400.png"
caption="Javi Velasco"
legend="Frontend engineer at Audiense"
rightIcon="star"
/>
<ListItem
avatar="https://avatars2.githubusercontent.com/u/559654?v=3&s=460"
caption="Javi Jiménez"
legend="Frontend engineer at MediaSmart"
rightIcon="star"
/>
<ListItem
avatar="https://pbs.twimg.com/profile_images/755797598565531649/Whsf9259.jpg"
caption="Tobias Van Schneider"
legend="Designer at Spotify"
rightIcon="star"
/>
</List>
</div>
<h5>Two line options and checkbox items</h5>
<p>It can be used to embed little checkboxes in the list. These behave as checkboxes.</p>
<div style={listStyle}>
<List>
<ListSubHeader caption="General" />
<ListItem caption="Profile Photo" legend="Change your Google+ profile photo" />
<ListItem disabled caption="Show your status" legend="Your status is visible to everyone you use with" />
</List>
<ListDivider />
<List>
<ListSubHeader caption="Hangout notifications" />
<ListCheckbox
caption="Notifications"
checked={this.state.checkbox1}
legend="Allow notifications"
onChange={this.handleCheckboxChange.bind(this, 'checkbox1')}
/>
<ListCheckbox
caption="Sound"
checked={this.state.checkbox2}
legend="Hangouts message"
onChange={this.handleCheckboxChange.bind(this, 'checkbox2')}
/>
<ListCheckbox
caption="Video sounds"
checked
disabled
legend="Hangouts video call"
/>
</List>
</div>
<h5>Avatar, single text and icon</h5>
<p>Similar to a previous one but only with one text line</p>
<div style={listStyle}>
<List>
<ListItem
avatar="https://pbs.twimg.com/profile_images/614407428/s6pTalMzZs-nusCGWqoV.0_400x400.jpeg"
caption="Alfonso Rocha"
rightIcon="mail"
/>
<ListItem
avatar="https://pbs.twimg.com/profile_images/693578804808278017/a5y4h8MN_400x400.png"
caption="Javi Velasco"
rightIcon="mail"
/>
<ListItem
avatar="https://avatars2.githubusercontent.com/u/559654?v=3&s=460"
caption="Javi Jiménez"
rightIcon="mail"
/>
<ListItem
avatar="https://pbs.twimg.com/profile_images/755797598565531649/Whsf9259.jpg"
caption="Tobias Van Schneider"
rightIcon="mail"
/>
</List>
</div>
<h5>Simple with just one text line</h5>
<p>The most simple list.</p>
<div style={listStyle}>
<List>
<ListItem caption="Alfonso Rocha" />
<ListItem caption="Javi Velasco" />
<ListItem caption="Javi Jiménez" />
<ListItem caption="Tobias Van Schneider" />
<ListDivider />
<ListItem caption="Other people" />
</List>
</div>
<h5> List with custom components </h5>
<p> Using custom components in list item </p>
<div style={listStyle}>
<List ripple selectable>
<ListItem leftIcon="send" rightIcon="done" caption="Reference item" />
<ListItem rightIcon="done" caption="Item with custom left icons">
<FontIcon value="send" />
<Avatar image="https://pbs.twimg.com/profile_images/693578804808278017/a5y4h8MN_400x400.png" />
</ListItem>
<ListItem leftIcon="send">
<ListItemContent caption="custom right icons" legend="ListItemContent acts as a divider" />
<FontIcon value="done" />
<FontIcon value="undo" />
</ListItem>
<ListItem leftIcon="mail" rightIcon="create">
<ListItemContent>
<ListItemText primary> Custom Caption </ListItemText>
</ListItemContent>
</ListItem>
<ListItem leftIcon="save" rightIcon="delete">
<ListItemContent>
<ListItemText primary onClick={() => { console.log('clicked caption'); }}>
Custom caption with events
</ListItemText>
<ListItemText> Custom legend with correct height </ListItemText>
</ListItemContent>
</ListItem>
<ListItem caption="Item with a button">
<Button icon="save" label="save" onClick={() => console.log('clicked button')} />
</ListItem>
<ListItem caption="Item with overlayed click events" onClick={() => console.log('clicked row')}>
<FontIcon value="send" onClick={() => console.log('clicked icon')} />
<Avatar
image="https://pbs.twimg.com/profile_images/693578804808278017/a5y4h8MN_400x400.png"
onMouseDown={() => console.log('avatar mouse down, should see ripple')}
onClick={() => console.log('clicked avatar')}
/>
</ListItem>
</List>
</div>
</section>
);
}
}
export default ListTest;

38
spec/ts/menu.tsx Normal file
View File

@ -0,0 +1,38 @@
import * as React from 'react';
import { Menu, MenuItem, MenuDivider } from '../../components/menu';
class MenuTest extends React.Component<any, any> {
state: any = {
value: undefined,
};
handleSelect = (item: any) => {
console.log('Menu selection changed!!, now its', item);
this.setState({ value: item });
};
handleItemClick = () => {
console.log('This item is so special that has a special handler');
};
render() {
return (
<section>
<h5>Menus</h5>
<p>This tabs can be disabled or hidden</p>
<Menu onSelect={this.handleSelect} selectable={false} selected={this.state.value}>
<MenuItem value="foo" caption="Caption" />
<MenuItem onClick={this.handleItemClick} value="bar" caption="Caption & Shortcut" shortcut="Ctrl + P" />
<MenuItem caption="Disabled ..." disabled shortcut="Ctrl + P" />
<MenuDivider />
<MenuItem caption="Caption & Icon" icon="phone" />
<MenuItem caption="Caption, Icon & Shortcut" icon="phone" shortcut="Ctrl + P" />
<MenuItem caption="Disabled ..." icon="phone" shortcut="Ctrl + P" disabled />
</Menu>
</section>
);
}
}
export default MenuTest;

22
spec/ts/navigation.tsx Normal file
View File

@ -0,0 +1,22 @@
import * as React from 'react';
import Navigation from '../../components/navigation';
import Link from '../../components/link';
const actions = [
{ label: 'Alarm', raised: true, icon: 'access_alarm' },
{ label: 'Location', raised: true, accent: true, icon: 'room' },
];
const NavigationTest = () => (
<section>
<h5>Navigation</h5>
<p>lorem ipsum...</p>
<Navigation type="horizontal" actions={actions} />
<Navigation type="vertical">
<Link href="http://" label="Inbox" icon="inbox" />
<Link href="http://" active label="Profile" icon="person" />
</Navigation>
</section>
);
export default NavigationTest;

131
spec/ts/pickers.tsx Normal file
View File

@ -0,0 +1,131 @@
import * as React from 'react';
import DatePicker from '../../components/date_picker';
import TimePicker from '../../components/time_picker';
const datetime = new Date(2015, 10, 16);
const min_datetime = new Date(new Date(datetime).setDate(8));
const max_datetime = new Date(new Date(datetime).setDate(24));
datetime.setHours(17);
datetime.setMinutes(28);
const today = new Date();
today.setHours(0, 0, 0, 0);
const enabledDisabledDates = [new Date(today.getTime()), new Date(today.setDate(today.getDate() - 1))];
class PickersTest extends React.Component<any, any> {
state: any = {
date2: datetime,
firstActive: false,
time2: datetime,
};
handleChange = (item: any, value: any) => {
const newState: any = {};
newState.firstActive = false;
newState[item] = value;
this.setState(newState);
};
makeFirstUnactive = () => {
this.setState({ firstActive: false });
};
localeExample = {
months: 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
monthsShort: 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
weekdays: 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
weekdaysShort: 'ig._al._ar._az._og._ol._lr.'.split('_'),
weekdaysLetter: 'ig_al_ar_az_og_ol_lr'.split('_'),
}
render() {
return (
<section>
<h5>Pickers</h5>
<p>Date pickers and time pickers with Material flavour.</p>
<DatePicker
active={this.state.firstActive}
label="Birthdate"
onChange={this.handleChange.bind(this, 'date1')}
onEscKeyDown={this.makeFirstUnactive}
onOverlayClick={this.makeFirstUnactive}
value={this.state.date1}
sundayFirstDayOfWeek
/>
<DatePicker
label="With locale (string) - Spanish (string: en|es|af|ar|be|bg|bn|bo|br|bs|ca|gl|eu|pt|it|fr)"
locale="es"
onChange={this.handleChange.bind(this, 'date2')}
value={this.state.date2}
/>
<DatePicker
label="With locale (object) - Basque"
locale={this.localeExample}
onChange={this.handleChange.bind(this, 'date2')}
value={this.state.date2}
/>
<DatePicker
label="Expiration date (Read Only)"
maxDate={max_datetime}
minDate={min_datetime}
onChange={this.handleChange.bind(this, 'date2')}
readonly
value={this.state.date2}
sundayFirstDayOfWeek
/>
<DatePicker
label="Formatted Date"
inputFormat={(value: any) => `${value.getDate()}/${value.getMonth() + 1}/${value.getFullYear()}`}
onChange={this.handleChange.bind(this, 'date3')}
value={this.state.date3}
sundayFirstDayOfWeek
/>
<DatePicker
label="Auto Picker"
autoOk
sundayFirstDayOfWeek
onChange={this.handleChange.bind(this, 'date4')}
value={this.state.date4}
/>
<DatePicker
label="Date picker with enabled dates"
onChange={this.handleChange.bind(this, 'date5')}
enabledDates={enabledDisabledDates}
value={this.state.date5}
/>
<DatePicker
label="Date picker with disabled dates"
onChange={this.handleChange.bind(this, 'date6')}
disabledDates={enabledDisabledDates}
value={this.state.date6}
/>
<TimePicker
format="ampm"
label="Start time"
onChange={this.handleChange.bind(this, 'time1')}
onEscKeyDown={() => console.log('esc key down')}
onOverlayClick={() => console.log('overlay click')}
value={this.state.time1}
/>
<TimePicker
format="ampm"
label="Finishing time (Read Only)"
readonly
onChange={this.handleChange.bind(this, 'time2')}
value={this.state.time2}
/>
</section>
);
}
}
export default PickersTest;

59
spec/ts/progress.tsx Normal file
View File

@ -0,0 +1,59 @@
import * as React from 'react';
import ProgressBar from '../../components/progress_bar';
const style = require('../style.css');
const initialState = {
progress: 0,
buffer: 10,
};
class ProgressBarTest extends React.Component<any, any> {
state = initialState;
componentWillMount() {
this.simulateProgress();
}
simulateProgress() {
setTimeout(() => {
if (this.state.progress < 100) {
this.increaseProgress();
if (this.state.progress > this.state.buffer) this.increaseBuffer();
} else {
this.setState(initialState);
}
this.simulateProgress();
}, (Math.random() * 1 + 1) * 1000);
}
increaseProgress() {
this.setState({
progress: Math.random() * 30 + this.state.progress,
});
}
increaseBuffer() {
this.setState({
buffer: Math.random() * (100 - this.state.progress) + this.state.progress,
});
}
render() {
return (
<section>
<h5>Progress bars</h5>
<p style={{ margin: '10px auto' }}>Determinate</p>
<ProgressBar mode="determinate" value={this.state.progress} buffer={this.state.buffer} />
<p style={{ margin: '10px auto' }}>Indeterminate...</p>
<ProgressBar mode="indeterminate" />
<p style={{ margin: '10px auto' }}>Circular</p>
<ProgressBar type="circular" mode="indeterminate" />
<p style={{ margin: '10px auto' }}>Circular with custom size</p>
<ProgressBar className={style.customSizedProgress} type="circular" mode="indeterminate" theme={style} />
</section>
);
}
}
export default ProgressBarTest;

39
spec/ts/radio.tsx Normal file
View File

@ -0,0 +1,39 @@
import * as React from 'react';
import { RadioGroup, RadioButton } from '../../components/radio';
class RadioGroupTest extends React.Component<any, any> {
state = {
value: 'vvendetta',
};
handleChange = (value: any) => {
console.log('Changed!', { comic: value });
this.setState({ value });
};
handleFocus = () => {
console.log('Focused V for a Vendetta');
};
handleBlur = () => {
console.log('Blurred Watchmen');
};
render() {
return (
<section>
<h5>Radio Button</h5>
<p style={{ marginBottom: '10px' }}>Lorem ipsum...</p>
<RadioGroup name="comic" value={this.state.value} onChange={this.handleChange}>
<RadioButton label="The Walking Dead" value="thewalkingdead" />
<RadioButton label="From Hell" value="fromhell" disabled />
<RadioButton label="V for a Vendetta" value="vvendetta" onFocus={this.handleFocus} />
<RadioButton label="Watchmen" value="watchmen" onBlur={this.handleBlur} />
</RadioGroup>
</section>
);
}
}
export default RadioGroupTest;

31
spec/ts/slider.tsx Normal file
View File

@ -0,0 +1,31 @@
import * as React from 'react';
import Slider from '../../components/slider';
class SliderTest extends React.Component<any, any> {
state: any = {
slider2: 5,
slider3: 1,
};
handleChange = (slider: any, value: any) => {
this.setState({ ...this.state, [slider]: value });
};
render() {
return (
<section>
<h5>Sliders</h5>
<p>Normal slider</p>
<Slider value={this.state.slider1} onChange={this.handleChange.bind(this, 'slider1')} />
<p>With steps, initial value and editable</p>
<Slider min={0} max={10} editable value={this.state.slider2} onChange={this.handleChange.bind(this, 'slider2')} />
<p>Pinned and with snaps</p>
<Slider pinned snaps min={0} max={10} step={2} editable value={this.state.slider3} onChange={this.handleChange.bind(this, 'slider3')} />
<p>Disabled status</p>
<Slider disabled pinned snaps min={0} max={10} step={2} editable value={this.state.slider3} onChange={this.handleChange.bind(this, 'slider3')} />
</section>
);
}
}
export default SliderTest;

43
spec/ts/snackbar.tsx Normal file
View File

@ -0,0 +1,43 @@
import * as React from 'react';
import Button from '../../components/button';
import Snackbar from '../../components/snackbar';
class SnackbarTest extends React.Component<any, any> {
state = {
active: false,
};
handleSnackbarClick = () => {
this.setState({ active: false });
};
handleSnackbarTimeout = () => {
this.setState({ active: false });
};
handleClick = () => {
this.setState({ active: true });
};
render() {
return (
<section>
<h5>Snackbars & Toasts</h5>
<p>lorem ipsum...</p>
<Button label="Show snackbar" primary raised onClick={this.handleClick} />
<Snackbar
action="Hide"
active={this.state.active}
timeout={2000}
onClick={this.handleSnackbarClick}
onTimeout={this.handleSnackbarTimeout}
type="warning"
>
Snackbar action <strong>cancel</strong>
</Snackbar>
</section>
);
}
}
export default SnackbarTest;

41
spec/ts/switch.tsx Normal file
View File

@ -0,0 +1,41 @@
import * as React from 'react';
import Switch from '../../components/switch';
class SwitchTest extends React.Component<any, any> {
state = {
switch_1: true,
switch_2: false,
switch_3: true,
};
handleChange = (field: any, value: any) => {
this.setState({ ...this.state, [field]: value });
};
render() {
return (
<section>
<h5>Switches</h5>
<p style={{ marginBottom: '10px' }}>This is more beautiful than the old fashion checkboxes...</p>
<Switch
checked={this.state.switch_1}
label="Push notifications"
onChange={this.handleChange.bind(this, 'switch_1')}
/>
<Switch
checked={this.state.switch_2}
label="Mail notifications"
onChange={this.handleChange.bind(this, 'switch_2')}
/>
<Switch
checked={this.state.switch_3}
disabled
label="Nothing, thanks"
onChange={this.handleChange.bind(this, 'switch_3')}
/>
</section>
);
}
}
export default SwitchTest;

91
spec/ts/table.tsx Normal file
View File

@ -0,0 +1,91 @@
import * as React from 'react';
import { Table, TableHead, TableRow, TableCell } from '../../components/table';
import Tooltip from '../../components/tooltip';
const data = [
{ name: 'Cupcake', calories: 305, fat: 3.7, carbs: 67, protein: 4.3, sodium: 413, calcium: '3%', iron: '8%' },
{ name: 'Donut', calories: 452, fat: 25.0, carbs: 51, protein: 4.9, sodium: 326, calcium: '2%', iron: '22%' },
{ name: 'Eclair', calories: 262, fat: 16.0, carbs: 24, protein: 6.0, sodium: 337, calcium: '6%', iron: '7%' },
{ name: 'Frozen yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, sodium: 87, calcium: '14%', iron: '1%' },
{ name: 'Gingerbread', calories: 356, fat: 16.0, carbs: 49, protein: 3.9, sodium: 327, calcium: '7%', iron: '16%' },
{ name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, sodium: 129, calcium: '8%', iron: '1%' },
{ name: 'Jelly bean', calories: 375, fat: 0.0, carbs: 94, protein: 0.0, sodium: 50, calcium: '0%', iron: '0%' },
{ name: 'KitKat', calories: 518, fat: 26.0, carbs: 65, protein: 7, sodium: 54, calcium: '12%', iron: '6%' },
];
const TooltippedCell = Tooltip(TableCell);
const sortByCaloriesAsc = (a: any, b: any) => {
if (a.calories < b.calories) return -1;
if (a.calories > b.calories) return 1;
return 0;
};
const sortByCaloriesDesc = (a: any, b: any) => {
if (a.calories > b.calories) return -1;
if (a.calories < b.calories) return 1;
return 0;
};
class TableTest extends React.Component<any, any> {
state: any = {
selected: ['Donut'],
sorted: 'asc',
};
getSortedData = () => {
const compare = this.state.sorted === 'asc' ? sortByCaloriesAsc : sortByCaloriesDesc;
return data.sort(compare);
}
handleRowSelect = (selected: any) => {
const sortedData = this.getSortedData();
this.setState({ selected: selected.map((item: any) => sortedData[item].name) });
};
handleSortClick = () => {
const { sorted } = this.state;
const nextSorting = sorted === 'asc' ? 'desc' : 'asc';
this.setState({ sorted: nextSorting });
};
render() {
const { sorted } = this.state;
const sortedData = this.getSortedData();
return (
<section>
<h5>Table</h5>
<p>Organized data.</p>
<Table multiSelectable onRowSelect={this.handleRowSelect} style={{ marginTop: 10 }}>
<TableHead>
<TooltippedCell tooltip="The total amount of food energy in the given serving size">
Dessert (100g serving)
</TooltippedCell>
<TableCell onClick={this.handleSortClick} numeric sorted={sorted}>Calories</TableCell>
<TableCell numeric>Fat (g)</TableCell>
<TableCell numeric>Carbs (g)</TableCell>
<TableCell numeric>Protein (g)</TableCell>
<TableCell numeric>Sodium (mg)</TableCell>
<TableCell numeric>Calcium (%)</TableCell>
<TableCell numeric>Iron (%)</TableCell>
</TableHead>
{sortedData.map((item, idx) => (
<TableRow key={idx} selected={this.state.selected.indexOf(item.name) !== -1}>
<TableCell>{item.name}</TableCell>
<TableCell numeric>{item.calories}</TableCell>
<TableCell numeric>{item.fat}</TableCell>
<TableCell numeric>{item.carbs}</TableCell>
<TableCell numeric>{item.protein}</TableCell>
<TableCell numeric>{item.sodium}</TableCell>
<TableCell numeric>{item.calcium}</TableCell>
<TableCell numeric>{item.iron}</TableCell>
</TableRow>
))}
</Table>
</section>
);
}
}
export default TableTest;

73
spec/ts/tabs.tsx Normal file
View File

@ -0,0 +1,73 @@
import * as React from 'react';
import { Tabs, Tab } from '../../components/tabs';
class TabsTest extends React.Component<any, any> {
state = {
index: 1,
fixedIndex: 1,
inverseIndex: 1,
};
handleTabChange = (index: any) => {
this.setState({ index });
};
handleFixedTabChange = (index: any) => {
this.setState({ fixedIndex: index });
};
handleInverseTabChange = (index: any) => {
this.setState({ inverseIndex: index });
};
handleActive = () => {
console.log('Special one activated');
};
render() {
return (
<section>
<h5>Tabs</h5>
<p>This tabs can be disabled or hidden</p>
<Tabs disableAnimatedBottomBorder index={this.state.index} onChange={this.handleTabChange}>
<Tab ripple={false} label="Primary"><small>Primary content (no ripple)</small></Tab>
<Tab label="Secondary" onActive={this.handleActive}><small>Secondary content</small></Tab>
<Tab label="Third" disabled><small>Disabled content</small></Tab>
<Tab label="Fourth" hidden><small>Fourth content hidden</small></Tab>
<Tab label="Fifth"><small>Fifth content</small></Tab>
</Tabs>
<h5>Fixed Tabs</h5>
<p>These tabs fill the given space.</p>
<Tabs index={this.state.fixedIndex} onChange={this.handleFixedTabChange} fixed>
<Tab label="First"><small>First Content</small></Tab>
<Tab label="Second"><small>Second Content</small></Tab>
<Tab label="Third"><small>Third Content</small></Tab>
<Tab label="Fourth"><small>Fourth Content</small></Tab>
<Tab label="Fifth"><small>Fifth Content</small></Tab>
</Tabs>
<h5>Inverse Tabs</h5>
<p>These tabs have an inverted theme.</p>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab label="First"><small>First Content</small></Tab>
<Tab label="Second"><small>Second Content</small></Tab>
<Tab label="Third"><small>Third Content</small></Tab>
<Tab label="Disabled" disabled><small>Disabled Content</small></Tab>
</Tabs>
<h5>Inverse Tabs with labels and icons</h5>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab label="Home" icon="home"><small>First Content</small></Tab>
<Tab label="Favorite" icon="favorite"><small>Second Content</small></Tab>
<Tab label="Call" icon="call"><small>Third Content</small></Tab>
</Tabs>
<h5>Inverse Tabs with icons</h5>
<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse>
<Tab icon="home"><small>First Content</small></Tab>
<Tab icon="favorite"><small>Second Content</small></Tab>
<Tab icon="call"><small>Third Content</small></Tab>
</Tabs>
</section>
);
}
}
export default TabsTest;

49
spec/ts/tooltip.tsx Normal file
View File

@ -0,0 +1,49 @@
import * as React from 'react';
import Button from '../../components/button';
import Input from '../../components/input';
import FontIcon from '../../components/font_icon';
import Tooltip, { tooltipFactory } from '../../components/tooltip';
import Chip from '../../components/chip';
import Avatar from '../../components/avatar';
const TooltipFontIcon = tooltipFactory({ passthrough: false })(FontIcon);
const TooltipButton = Tooltip(Button);
const TooltipInput = Tooltip(Input);
const TooltipStrong = Tooltip(({ children, ...other }) => {
delete other.theme;
return <strong {...other}>{children}</strong>;
});
const TooltipStrongDirect = Tooltip('strong');
const ChipTooltip = Tooltip(Chip);
const TooltipTest = () => (
<section>
<h5>Tooltip</h5>
<p>Give information on :hover</p>
<TooltipButton label="Bookmark" icon="bookmark" raised primary tooltip="Bookmark Tooltip" tooltipDelay={1000} />
<TooltipButton icon="add" floating accent tooltip="Floating Tooltip" />
<TooltipButton icon="add" floating disabled tooltip="Floating can not be shown" />
<TooltipButton
icon="add"
floating
tooltip={<div><p>An example with</p><p>Multiline!</p></div>}
/>
<ChipTooltip tooltip="Dolor sit amet" tooltipPosition="top">
<Avatar icon="home" />
<span>Tooltip in a chip</span>
</ChipTooltip>
<TooltipInput tooltip="lorem ipsum..." />
<p>Lorem ipsum dolor sit amet, <TooltipStrong tooltip="This is a auto show tooltip">consectetur</TooltipStrong> adipiscing elit.</p>
<p>
Click this next word to show and hide on click:
{' '}
<TooltipStrongDirect tooltip="This is a auto show tooltip" tooltipShowOnClick>
oh hai
</TooltipStrongDirect>
{' '}. This is useful for mobile!
</p>
<TooltipFontIcon value="code" tooltip="This is a test with FontIcon" />
</section>
);
export default TooltipTest;

22
tsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "es5",
"moduleResolution": "node",
"jsx": "react",
"noEmit": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"baseUrl": ".",
"paths": {
"components/*": [
"./components/*"
]
}
},
"exclude": [
"./index.d.ts",
"node_modules",
"docs/node_modules",
"lib"
]
}

View File

@ -2,6 +2,14 @@
# yarn lockfile v1
"@types/node@^7.0.4":
version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.4.tgz#9aabc135979ded383325749f508894c662948c8b"
"@types/react@^15.0.0":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/react/-/react-15.0.0.tgz#33eb3438130614f25c07c09e46ebec5a8d45b3b0"
JSONStream@^0.8.4:
version "0.8.4"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.8.4.tgz#91657dfe6ff857483066132b4618b62e8f4887bd"
@ -6999,6 +7007,10 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@^2.1.5:
version "2.1.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.5.tgz#6fe9479e00e01855247cea216e7561bafcdbcd4a"
ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"